@psnext/slingcli 3.0.20260810-3 → 3.0.20260811-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@earendil-works/pi-coding-agent/dist/core/project-trust.js +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/docs/compaction.md +9 -9
- package/node_modules/@earendil-works/pi-coding-agent/docs/containerization.md +8 -8
- package/node_modules/@earendil-works/pi-coding-agent/docs/custom-provider.md +20 -12
- package/node_modules/@earendil-works/pi-coding-agent/docs/development.md +71 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/docs.json +14 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/environment-variables.md +9 -9
- package/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md +53 -26
- package/node_modules/@earendil-works/pi-coding-agent/docs/index.md +10 -9
- package/node_modules/@earendil-works/pi-coding-agent/docs/json.md +21 -16
- package/node_modules/@earendil-works/pi-coding-agent/docs/keybindings.md +46 -14
- package/node_modules/@earendil-works/pi-coding-agent/docs/llama-cpp.md +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/docs/mcp.md +2 -2
- package/node_modules/@earendil-works/pi-coding-agent/docs/models.md +25 -4
- package/node_modules/@earendil-works/pi-coding-agent/docs/packages.md +13 -13
- package/node_modules/@earendil-works/pi-coding-agent/docs/prompt-templates.md +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/providers.md +317 -0
- package/node_modules/@earendil-works/pi-coding-agent/docs/quickstart.md +11 -9
- package/node_modules/@earendil-works/pi-coding-agent/docs/rpc.md +15 -13
- package/node_modules/@earendil-works/pi-coding-agent/docs/sdk.md +33 -14
- package/node_modules/@earendil-works/pi-coding-agent/docs/security.md +5 -5
- package/node_modules/@earendil-works/pi-coding-agent/docs/session-format.md +3 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/sessions.md +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/settings.md +6 -2
- package/node_modules/@earendil-works/pi-coding-agent/docs/shell-aliases.md +1 -1
- package/node_modules/@earendil-works/pi-coding-agent/docs/skills.md +5 -5
- package/node_modules/@earendil-works/pi-coding-agent/docs/terminal-setup.md +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/docs/termux.md +5 -5
- package/node_modules/@earendil-works/pi-coding-agent/docs/themes.md +7 -5
- package/node_modules/@earendil-works/pi-coding-agent/docs/tmux.md +3 -3
- package/node_modules/@earendil-works/pi-coding-agent/docs/usage.md +17 -10
- package/node_modules/@earendil-works/pi-coding-agent/docs/windows.md +1 -1
- package/package.json +2 -2
- package/slingshot/index.js +7 -5
package/slingshot/index.js
CHANGED
|
@@ -286,7 +286,7 @@ ${a}
|
|
|
286
286
|
${l}`,()=>`${i}
|
|
287
287
|
${o}
|
|
288
288
|
|
|
289
|
-
${l}`,this.getStartupExpansionState(),1,0),this.headerContainer.addChild(new W(1)),this.headerContainer.addChild(this.builtInHeader),this.headerContainer.addChild(new W(1))}else this.builtInHeader=new E("",0,0),this.headerContainer.addChild(this.builtInHeader);this.ui.requestRender(),await this.rebindCurrentSession(),this.renderInitialMessages(),lA(()=>{this.ui.invalidate(),this.updateEditorBorderColor(),this.ui.requestRender()}),this.footerDataProvider.onBranchChange(()=>{this.ui.requestRender()}),await this.updateAvailableProviderCount()}updateTerminalTitle(){let e=st.basename(this.sessionManager.getCwd()),n=this.sessionManager.getSessionName();n?this.ui.terminal.setTitle(`Sling - ${n} - ${e}`):this.ui.terminal.setTitle(`Sling - ${e}`)}async run(){if(await this.init(),!process.env.PI_OFFLINE){let a=new AbortController,l=setTimeout(()=>a.abort(),15e3);this.session.modelRuntime.refresh({signal:a.signal}).then(()=>this.updateAvailableProviderCount()).catch(()=>{}).finally(()=>clearTimeout(l))}O_(this.version).then(a=>{}),this.checkForPackageUpdates().then(a=>{a.length>0&&this.showPackageUpdateNotification(a)}).finally(()=>{process.platform==="win32"&&this.isInitialized&&this.updateTerminalTitle()}),this.checkTmuxKeyboardSetup().then(a=>{a&&this.showWarning(a)});let{migratedProviders:e,modelFallbackMessage:n,initialMessage:i,initialImages:r,initialMessages:o}=this.options;e&&e.length>0&&this.showWarning(`Migrated credentials to auth.json: ${e.join(", ")}`);let s=this.session.modelRuntime.getError();if(s&&this.showError(`models.json error: ${s}`),n&&this.showWarning(n),this.maybeWarnAboutAnthropicSubscriptionAuth(),i)try{await this.session.prompt(i,{images:r})}catch(a){let l=a instanceof Error?a.message:"Unknown error occurred";this.showError(l)}if(o)for(let a of o)try{await this.session.prompt(a)}catch(l){let c=l instanceof Error?l.message:"Unknown error occurred";this.showError(c)}for(;;){let a=await this.getUserInput();try{await this.session.prompt(a)}catch(l){let c=l instanceof Error?l.message:"Unknown error occurred";this.showError(c)}}}async checkForPackageUpdates(){if(process.env.PI_OFFLINE)return[];try{return(await new Ni({cwd:this.sessionManager.getCwd(),agentDir:Ee(),settingsManager:this.settingsManager}).checkForAvailableUpdates()).map(i=>i.displayName)}catch{return[]}}async checkTmuxKeyboardSetup(){if(!process.env.TMUX)return;let e=r=>new Promise(o=>{let s=Z_("tmux",["show","-gv",r],{stdio:["ignore","pipe","ignore"]}),a="",l=setTimeout(()=>{s.kill(),o(void 0)},2e3);s.stdout?.on("data",c=>{a+=c.toString()}),s.on("error",()=>{clearTimeout(l),o(void 0)}),s.on("close",c=>{clearTimeout(l),o(c===0?a.trim():void 0)})}),[n,i]=await Promise.all([e("extended-keys"),e("extended-keys-format")]);if(n!==void 0){if(n!=="on"&&n!=="always")return"tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.";if(i==="xterm")return"tmux extended-keys-format is xterm.
|
|
289
|
+
${l}`,this.getStartupExpansionState(),1,0),this.headerContainer.addChild(new W(1)),this.headerContainer.addChild(this.builtInHeader),this.headerContainer.addChild(new W(1))}else this.builtInHeader=new E("",0,0),this.headerContainer.addChild(this.builtInHeader);this.ui.requestRender(),await this.rebindCurrentSession(),this.renderInitialMessages(),lA(()=>{this.ui.invalidate(),this.updateEditorBorderColor(),this.ui.requestRender()}),this.footerDataProvider.onBranchChange(()=>{this.ui.requestRender()}),await this.updateAvailableProviderCount()}updateTerminalTitle(){let e=st.basename(this.sessionManager.getCwd()),n=this.sessionManager.getSessionName();n?this.ui.terminal.setTitle(`Sling - ${n} - ${e}`):this.ui.terminal.setTitle(`Sling - ${e}`)}async run(){if(await this.init(),!process.env.PI_OFFLINE){let a=new AbortController,l=setTimeout(()=>a.abort(),15e3);this.session.modelRuntime.refresh({signal:a.signal}).then(()=>this.updateAvailableProviderCount()).catch(()=>{}).finally(()=>clearTimeout(l))}O_(this.version).then(a=>{}),this.checkForPackageUpdates().then(a=>{a.length>0&&this.showPackageUpdateNotification(a)}).finally(()=>{process.platform==="win32"&&this.isInitialized&&this.updateTerminalTitle()}),this.checkTmuxKeyboardSetup().then(a=>{a&&this.showWarning(a)});let{migratedProviders:e,modelFallbackMessage:n,initialMessage:i,initialImages:r,initialMessages:o}=this.options;e&&e.length>0&&this.showWarning(`Migrated credentials to auth.json: ${e.join(", ")}`);let s=this.session.modelRuntime.getError();if(s&&this.showError(`models.json error: ${s}`),n&&this.showWarning(n),this.maybeWarnAboutAnthropicSubscriptionAuth(),i)try{await this.session.prompt(i,{images:r})}catch(a){let l=a instanceof Error?a.message:"Unknown error occurred";this.showError(l)}if(o)for(let a of o)try{await this.session.prompt(a)}catch(l){let c=l instanceof Error?l.message:"Unknown error occurred";this.showError(c)}for(;;){let a=await this.getUserInput();try{await this.session.prompt(a)}catch(l){let c=l instanceof Error?l.message:"Unknown error occurred";this.showError(c)}}}async checkForPackageUpdates(){if(process.env.PI_OFFLINE)return[];try{return(await new Ni({cwd:this.sessionManager.getCwd(),agentDir:Ee(),settingsManager:this.settingsManager}).checkForAvailableUpdates()).map(i=>i.displayName)}catch{return[]}}async checkTmuxKeyboardSetup(){if(!process.env.TMUX)return;let e=r=>new Promise(o=>{let s=Z_("tmux",["show","-gv",r],{stdio:["ignore","pipe","ignore"]}),a="",l=setTimeout(()=>{s.kill(),o(void 0)},2e3);s.stdout?.on("data",c=>{a+=c.toString()}),s.on("error",()=>{clearTimeout(l),o(void 0)}),s.on("close",c=>{clearTimeout(l),o(c===0?a.trim():void 0)})}),[n,i]=await Promise.all([e("extended-keys"),e("extended-keys-format")]);if(n!==void 0){if(n!=="on"&&n!=="always")return"tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.";if(i==="xterm")return"tmux extended-keys-format is xterm. sling works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux."}}getChangelogForDisplay(){if(this.session.state.messages.length>0)return;let e=this.settingsManager.getLastChangelogVersion(),n=Id(),i=Fv(n);if(!e){this.settingsManager.setLastChangelogVersion(Ii),this.reportInstallTelemetry(Ii);return}let r=w_(i,e);if(r.length>0)return this.settingsManager.setLastChangelogVersion(Ii),this.reportInstallTelemetry(Ii),r.map(o=>Wv(o.content,o)).join(`
|
|
290
290
|
|
|
291
291
|
`)}reportInstallTelemetry(e){process.env.PI_OFFLINE||Sv(this.settingsManager)&&fetch(`https://pi.dev/api/report-install?version=${encodeURIComponent(e)}`,{headers:{"User-Agent":Vu(e)},signal:AbortSignal.timeout(5e3)}).then(()=>{}).catch(()=>{})}getMarkdownThemeWithSettings(){return{...It(),codeBlockIndent:this.settingsManager.getCodeBlockIndent()}}formatDisplayPath(e){let n=fp.homedir(),i=e;return i.startsWith(n)&&(i=`~${i.slice(n.length)}`),i}formatExtensionDisplayPath(e){let n=this.formatDisplayPath(e);return n=n.replace(/\/index\.ts$/,"").replace(/\/index\.js$/,""),n}formatContextPath(e){let n=st.resolve(this.sessionManager.getCwd()),i=st.isAbsolute(e)?st.resolve(e):st.resolve(n,e),r=Rd(i,n);return r!==void 0?r:this.formatDisplayPath(i)}getStartupExpansionState(){return this.options.verbose||this.toolOutputExpanded}getShortPath(e,n){let i=e.replace(/\\/g,"/"),r=n?.baseDir;if(r&&this.isPackageSource(n)){let l=r.replace(/\\/g,"/"),c=l.match(/^(.*\/node_modules)\/(@?[^/]+(?:\/[^/]+)?)$/);if(c?.[1]&&i.startsWith(`${c[1]}/`))return st.posix.relative(l,i);let u=st.relative(st.resolve(r),st.resolve(e));if(u&&u!=="."&&!u.startsWith("..")&&!u.startsWith(`..${st.sep}`)&&!st.isAbsolute(u))return u.replace(/\\/g,"/")}let o=n?.source??"",s=i.match(/node_modules\/(@?[^/]+(?:\/[^/]+)?)\/(.*)/);if(s&&o.startsWith("npm:"))return s[2];let a=i.match(/git\/[^/]+\/[^/]+\/(.*)/);return a&&o.startsWith("git:")?a[1]:this.formatDisplayPath(e)}getCompactPathLabel(e,n){let i=this.getShortPath(e,n),o=i.replace(/\\/g,"/").split("/").filter(s=>s.length>0&&s!=="~");return o.length>0?o[o.length-1]:i}getCompactPackageSourceLabel(e){let n=e?.source??"";if(n.startsWith("npm:"))return n.slice(4)||n;let i=Qu(n);return i&&i.path||n}getCompactExtensionLabel(e,n){if(!this.isPackageSource(n))return this.getCompactPathLabel(e,n);let i=this.getCompactPackageSourceLabel(n);if(!i)return this.getCompactPathLabel(e,n);let r=this.getShortPath(e,n).replace(/\\/g,"/"),o=r.startsWith("extensions/")?r.slice(11):r,s=st.posix.parse(o);return s.name==="index"?!s.dir||s.dir==="."?i:`${i}:${s.dir}`:`${i}:${o}`}getCompactDisplayPathSegments(e){return this.formatDisplayPath(e).replace(/\\/g,"/").split("/").filter(n=>n.length>0&&n!=="~")}getCompactNonPackageExtensionLabel(e,n,i){let r=i[n]?.segments;if(!r||r.length===0)return this.getCompactPathLabel(e);for(let o=1;o<=r.length;o+=1){let s=r.slice(-o).join("/");if(i.every((l,c)=>c===n?!0:l.segments.slice(-o).join("/")!==s))return s}return r.join("/")}getCompactExtensionLabels(e){let n=e.map(i=>{let r=this.getCompactDisplayPathSegments(i.path),o=r[r.length-1];return r.length>1&&(o==="index.ts"||o==="index.js")&&r.pop(),{path:i.path,sourceInfo:i.sourceInfo,segments:r}}).filter(i=>!this.isPackageSource(i.sourceInfo));return e.map(i=>{if(this.isPackageSource(i.sourceInfo))return this.getCompactExtensionLabel(i.path,i.sourceInfo);let r=n.findIndex(o=>o.path===i.path);return r===-1?this.getCompactPathLabel(i.path,i.sourceInfo):this.getCompactNonPackageExtensionLabel(i.path,r,n)})}getDisplaySourceInfo(e){let n=e?.source??"local",i=e?.scope??"project";return n==="local"?i==="user"?{label:"user",color:"muted"}:i==="project"?{label:"project",color:"muted"}:i==="temporary"?{label:"path",scopeLabel:"temp",color:"muted"}:{label:"path",color:"muted"}:n==="cli"?{label:"path",scopeLabel:i==="temporary"?"temp":void 0,color:"muted"}:{label:n,scopeLabel:i==="user"?"user":i==="project"?"project":i==="temporary"?"temp":void 0,color:"accent"}}getScopeGroup(e){let n=e?.source??"local",i=e?.scope??"project";return n==="cli"||i==="temporary"?"path":i==="user"?"user":i==="project"?"project":"path"}isPackageSource(e){let n=e?.source??"";return n.startsWith("npm:")||n.startsWith("git:")}buildScopeGroups(e){let n={user:{scope:"user",paths:[],packages:new Map},project:{scope:"project",paths:[],packages:new Map},path:{scope:"path",paths:[],packages:new Map}};for(let i of e){let r=this.getScopeGroup(i.sourceInfo),o=n[r],s=i.sourceInfo?.source??"local";if(this.isPackageSource(i.sourceInfo)){let a=o.packages.get(s)??[];a.push(i),o.packages.set(s,a)}else o.paths.push(i)}return[n.project,n.user,n.path].filter(i=>i.paths.length>0||i.packages.size>0)}formatScopeGroups(e,n){let i=[];for(let r of e){i.push(` ${x.fg("accent",r.scope)}`);let o=[...r.paths].sort((a,l)=>a.path.localeCompare(l.path));for(let a of o)i.push(x.fg("dim",` ${n.formatPath(a)}`));let s=Array.from(r.packages.entries()).sort(([a],[l])=>a.localeCompare(l));for(let[a,l]of s){i.push(` ${x.fg("mdLink",a)}`);let c=[...l].sort((u,p)=>u.path.localeCompare(p.path));for(let u of c)i.push(x.fg("dim",` ${n.formatPackagePath(u,a)}`))}}return i.join(`
|
|
292
292
|
`)}findSourceInfoForPath(e,n){let i=n.get(e);if(i)return i;let r=e;for(;r.includes("/");){r=r.substring(0,r.lastIndexOf("/"));let o=n.get(r);if(o)return o}}formatPathWithSource(e,n){if(n){let i=this.getShortPath(e,n),{label:r,scopeLabel:o}=this.getDisplaySourceInfo(n);return`${o?`${r} (${o})`:r} ${i}`}return this.formatDisplayPath(e)}formatDiagnostics(e,n){let i=[],r=new Map,o=[];for(let s of e)if(s.type==="collision"&&s.collision){let a=r.get(s.collision.name)??[];a.push(s),r.set(s.collision.name,a)}else o.push(s);for(let[s,a]of r){let l=a[0]?.collision;if(l){i.push(x.fg("warning",` "${s}" collision:`)),i.push(x.fg("dim",` ${x.fg("success","\u2713")} ${this.formatPathWithSource(l.winnerPath,this.findSourceInfoForPath(l.winnerPath,n))}`));for(let c of a)c.collision&&i.push(x.fg("dim",` ${x.fg("warning","\u2717")} ${this.formatPathWithSource(c.collision.loserPath,this.findSourceInfoForPath(c.collision.loserPath,n))} (skipped)`))}}for(let s of o)if(s.path){let a=this.formatPathWithSource(s.path,this.findSourceInfoForPath(s.path,n));i.push(x.fg(s.type==="error"?"error":"warning",` ${a}`)),i.push(x.fg(s.type==="error"?"error":"warning",` ${s.message}`))}else i.push(x.fg(s.type==="error"?"error":"warning",` ${s.message}`));return i.join(`
|
|
@@ -301,7 +301,7 @@ ${y}`,0,0)),this.loadedResourcesContainer.addChild(new W(1))}}}async bindCurrent
|
|
|
301
301
|
${n}`,["Yes","No"],i)==="Yes"}async promptForMissingSessionCwd(e){return await this.showExtensionConfirm("Session cwd not found",Tv(e.issue))?e.issue.fallbackCwd:void 0}showExtensionInput(e,n,i){return new Promise(r=>{if(i?.signal?.aborted){r(void 0);return}let o=()=>{this.hideExtensionInput(),r(void 0)};i?.signal?.addEventListener("abort",o,{once:!0}),this.extensionInput=new ks(e,n,s=>{i?.signal?.removeEventListener("abort",o),this.hideExtensionInput(),r(s)},()=>{i?.signal?.removeEventListener("abort",o),this.hideExtensionInput(),r(void 0)},{tui:this.ui,timeout:i?.timeout}),this.disposeActiveSelector(),this.editorContainer.clear(),this.editorContainer.addChild(this.extensionInput),this.ui.setFocus(this.extensionInput),this.ui.requestRender()})}hideExtensionInput(){this.extensionInput?.dispose(),this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.extensionInput=void 0,this.ui.setFocus(this.editor),this.ui.requestRender()}showExtensionEditor(e,n){return new Promise(i=>{this.extensionEditor=new Yl(this.ui,this.keybindings,e,n,r=>{this.hideExtensionEditor(),i(r)},()=>{this.hideExtensionEditor(),i(void 0)},void 0,this.settingsManager.getExternalEditorCommand()),this.disposeActiveSelector(),this.editorContainer.clear(),this.editorContainer.addChild(this.extensionEditor),this.ui.setFocus(this.extensionEditor),this.ui.requestRender()})}hideExtensionEditor(){this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.extensionEditor=void 0,this.ui.setFocus(this.editor),this.ui.requestRender()}setCustomEditorComponent(e){this.editorComponentFactory=e;let n=this.editor.getText();if(this.disposeActiveSelector(),this.editorContainer.clear(),e){let i=e(this.ui,Pu(),this.keybindings);i.onSubmit=this.defaultEditor.onSubmit,i.onChange=this.defaultEditor.onChange,i.setText(n),i.borderColor!==void 0&&(i.borderColor=this.defaultEditor.borderColor),i.setPaddingX!==void 0&&i.setPaddingX(this.defaultEditor.getPaddingX()),i.setAutocompleteMaxVisible!==void 0&&i.setAutocompleteMaxVisible(this.defaultEditor.getAutocompleteMaxVisible()),i.setAutocompleteProvider&&this.autocompleteProvider&&i.setAutocompleteProvider(this.autocompleteProvider);let r=i;if("actionHandlers"in r&&r.actionHandlers instanceof Map){r.onEscape||(r.onEscape=()=>this.defaultEditor.onEscape?.()),r.onCtrlD||(r.onCtrlD=()=>this.defaultEditor.onCtrlD?.()),r.onPasteImage||(r.onPasteImage=()=>this.defaultEditor.onPasteImage?.()),r.onExtensionShortcut||(r.onExtensionShortcut=o=>this.defaultEditor.onExtensionShortcut?.(o));for(let[o,s]of this.defaultEditor.actionHandlers)r.actionHandlers.set(o,s)}this.editor=i}else this.defaultEditor.setText(n),this.editor=this.defaultEditor;this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()}showExtensionNotify(e,n){n==="error"?this.showError(e):n==="warning"?this.showWarning(e):this.showStatus(e)}async showExtensionCustom(e,n){let i=this.editor.getText(),r=n?.overlay??!1,o=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.editor.setText(i),this.ui.setFocus(this.editor),this.ui.requestRender()};return new Promise((s,a)=>{let l,c=!1,u=p=>{if(!c){c=!0,r?this.ui.hideOverlay():o(),s(p);try{l?.dispose?.()}catch{}}};Promise.resolve(e(this.ui,x,this.keybindings,u)).then(p=>{if(!c)if(l=p,r){let d=()=>{if(n?.overlayOptions)return typeof n.overlayOptions=="function"?n.overlayOptions():n.overlayOptions;let g=l.width;return g?{width:g}:void 0},m=this.ui.showOverlay(l,d());n?.onHandle?.(m)}else this.disposeActiveSelector(),this.editorContainer.clear(),this.editorContainer.addChild(l),this.ui.setFocus(l),this.ui.requestRender()}).catch(p=>{c||(r||o(),a(p))})})}showExtensionError(e,n,i){let r=`Extension "${e}" error: ${n}`,o=new E(x.fg("error",r),1,0);if(this.chatContainer.addChild(o),i){let s=i.split(`
|
|
302
302
|
`).slice(1).map(a=>x.fg("dim",` ${a.trim()}`)).join(`
|
|
303
303
|
`);s&&this.chatContainer.addChild(new E(s,1,0))}this.ui.requestRender()}setupKeyHandlers(){this.defaultEditor.onEscape=()=>{if(this.session.isStreaming)this.restoreQueuedMessagesToEditor({abort:!0});else if(this.session.isBashRunning)this.session.abortBash();else if(this.isBashMode)this.editor.setText(""),this.isBashMode=!1,this.updateEditorBorderColor();else if(!this.editor.getText().trim()){let e=this.settingsManager.getDoubleEscapeAction();if(e!=="none"){let n=Date.now();n-this.lastEscapeTime<500?(e==="tree"?this.showTreeSelector():this.showUserMessageSelector(),this.lastEscapeTime=0):this.lastEscapeTime=n}}},this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onAction("app.suspend",()=>this.handleCtrlZ()),this.defaultEditor.onAction("app.thinking.cycle",()=>this.cycleThinkingLevel()),this.defaultEditor.onAction("app.model.cycleForward",()=>this.cycleModel("forward")),this.defaultEditor.onAction("app.model.cycleBackward",()=>this.cycleModel("backward")),this.ui.onDebug=()=>this.handleDebugCommand(),this.defaultEditor.onAction("app.model.select",()=>this.showModelSelector()),this.defaultEditor.onAction("app.tools.expand",()=>this.toggleToolOutputExpansion()),this.defaultEditor.onAction("app.thinking.toggle",()=>this.toggleThinkingBlockVisibility()),this.defaultEditor.onAction("app.editor.external",()=>{this.handleOpenExternalEditor()}),this.defaultEditor.onAction("app.message.copy",()=>{this.handleCopyCommand({flashConfirmation:!0})}),this.defaultEditor.onAction("app.message.followUp",()=>this.handleFollowUp()),this.defaultEditor.onAction("app.message.dequeue",()=>this.handleDequeue()),this.defaultEditor.onAction("app.session.new",()=>this.handleClearCommand()),this.defaultEditor.onAction("app.session.tree",()=>this.showTreeSelector()),this.defaultEditor.onAction("app.session.fork",()=>this.showUserMessageSelector()),this.defaultEditor.onAction("app.session.resume",()=>this.showSessionSelector()),this.defaultEditor.onChange=e=>{let n=this.isBashMode;this.isBashMode=e.trimStart().startsWith("!"),n!==this.isBashMode&&this.updateEditorBorderColor()},this.defaultEditor.onPasteImage=()=>{this.handleClipboardPaste()}}async handleRightClickPaste(){let e=this.renderer.getFocusedComponent(),n=e?.handleInput;if(!(!e||!n))try{let i=await $v();if(!i||this.renderer.getFocusedComponent()!==e)return;n.call(e,`\x1B[200~${i}\x1B[201~`),this.ui.requestRender()}catch{}}async handleClipboardPaste(){try{let e=await P_();if(e){let i=fp.tmpdir(),r=R_(e.mimeType)??"png",o=`pi-clipboard-${rO.randomUUID()}.${r}`,s=st.join(i,o);Tr.writeFileSync(s,Buffer.from(e.bytes)),this.editor.insertTextAtCursor?.(s),this.ui.requestRender();return}let n=await $v();n&&(this.editor.insertTextAtCursor?.(n),this.ui.requestRender())}catch{}}setupEditorSubmitHandler(){this.defaultEditor.onSubmit=async e=>{if(e=e.trim(),!!e){if(e==="/settings"){this.showSettingsSelector(),this.editor.setText("");return}if(e==="/scoped-models"){this.editor.setText(""),await this.showModelsSelector();return}if(e==="/model"||e.startsWith("/model ")){let n=e.startsWith("/model ")?e.slice(7).trim():void 0;this.editor.setText(""),await this.handleModelCommand(n);return}if(e==="/export"||e.startsWith("/export ")){await this.handleExportCommand(e),this.editor.setText("");return}if(e==="/import"||e.startsWith("/import ")){await this.handleImportCommand(e),this.editor.setText("");return}if(e==="/share"){await this.handleShareCommand(),this.editor.setText("");return}if(e==="/copy"){await this.handleCopyCommand(),this.editor.setText("");return}if(e==="/name"||e.startsWith("/name ")){this.handleNameCommand(e),this.editor.setText("");return}if(e==="/session"){this.handleSessionCommand(),this.editor.setText("");return}if(e==="/changelog"){this.handleChangelogCommand(),this.editor.setText("");return}if(e==="/hotkeys"){this.handleHotkeysCommand(),this.editor.setText("");return}if(e==="/fork"){this.showUserMessageSelector(),this.editor.setText("");return}if(e==="/clone"){this.editor.setText(""),await this.handleCloneCommand();return}if(e==="/tree"){this.showTreeSelector(),this.editor.setText("");return}if(e==="/trust"){this.showTrustSelector(),this.editor.setText("");return}if(e==="/login"||e.startsWith("/login ")){let n=e.startsWith("/login ")?e.slice(7).trim():void 0;this.editor.setText(""),await this.handleLoginCommand(n||"slingshot");return}if(e==="/logout"){this.showOAuthSelector("logout"),this.editor.setText("");return}if(e==="/new"){this.editor.setText(""),await this.handleClearCommand();return}if(e==="/compact"||e.startsWith("/compact ")){let n=e.startsWith("/compact ")?e.slice(9).trim():void 0;this.editor.setText(""),await this.handleCompactCommand(n);return}if(e==="/reload"){this.editor.setText(""),await this.handleReloadCommand();return}if(e==="/debug"){this.handleDebugCommand(),this.editor.setText("");return}if(e==="/arminsayshi"){this.handleArminSaysHi(),this.editor.setText("");return}if(e==="/dementedelves"){this.handleDementedDelves(),this.editor.setText("");return}if(e==="/resume"){this.showSessionSelector(),this.editor.setText("");return}if(e==="/quit"){this.editor.setText(""),await this.shutdown();return}if(e.startsWith("!")){let n=e.startsWith("!!"),i=n?e.slice(2).trim():e.slice(1).trim();if(i){if(this.session.isBashRunning){this.showWarning("A bash command is already running. Press Esc to cancel it first."),this.editor.setText(e);return}this.editor.addToHistory?.(e),await this.handleBashCommand(i,n),this.isBashMode=!1,this.updateEditorBorderColor();return}}if(this.session.isCompacting){this.isExtensionCommand(e)?(this.editor.addToHistory?.(e),this.editor.setText(""),await this.session.prompt(e)):this.queueCompactionMessage(e,"steer");return}if(this.session.isStreaming){this.editor.addToHistory?.(e),this.editor.setText(""),await this.session.prompt(e,{streamingBehavior:"steer"}),this.updatePendingMessagesDisplay(),this.ui.requestRender();return}this.flushPendingBashComponents(),this.onInputCallback?this.onInputCallback(e):this.pendingUserInputs.push(e),this.editor.addToHistory?.(e)}}}subscribeToAgent(){this.unsubscribe=this.session.subscribe(async e=>{await this.handleEvent(e)})}async handleEvent(e){switch(this.isInitialized||await this.init(),this.footer.invalidate(),e.type){case"agent_start":this.pendingTools.clear(),this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.workingVisible?this.showStatusIndicator(new up(this.ui,this.workingMessage??this.defaultWorkingMessage,this.workingIndicatorOptions)):this.clearStatusIndicator(),this.ui.requestRender();break;case"queue_update":this.updatePendingMessagesDisplay(),this.ui.requestRender();break;case"entry_appended":e.entry.type==="custom"&&(this.addCustomEntryToChat(e.entry),this.ui.requestRender());break;case"session_info_changed":this.updateTerminalTitle(),this.footer.invalidate(),this.ui.requestRender();break;case"thinking_level_changed":this.footer.invalidate(),this.updateEditorBorderColor();break;case"message_start":e.message.role==="custom"?(this.addMessageToChat(e.message),this.ui.requestRender()):e.message.role==="user"?(this.addMessageToChat(e.message),this.updatePendingMessagesDisplay(),this.ui.requestRender()):e.message.role==="assistant"&&(this.streamingComponent=new ji(void 0,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers()),this.streamingMessage=e.message,this.chatContainer.addChild(this.streamingComponent),this.streamingComponent.updateContent(this.streamingMessage,!0),this.ui.requestRender());break;case"message_update":if(this.streamingComponent&&e.message.role==="assistant"){this.streamingMessage=e.message,this.streamingComponent.updateContent(this.streamingMessage,!0);for(let n of this.streamingMessage.content)if(n.type==="toolCall")if(this.pendingTools.has(n.id)){let i=this.pendingTools.get(n.id);i&&i.updateArgs(n.arguments)}else{let i=new qi(n.name,n.id,n.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(n.name),this.ui,this.sessionManager.getCwd());i.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(i),this.pendingTools.set(n.id,i)}this.ui.requestRender()}break;case"message_end":if(e.message.role==="user")break;if(this.streamingComponent&&e.message.role==="assistant"){this.streamingMessage=e.message;let n;if(this.streamingMessage.stopReason==="aborted"){let i=this.session.retryAttempt;n=i>0?`Aborted after ${i} retry attempt${i>1?"s":""}`:"Operation aborted",this.streamingMessage.errorMessage=n}if(this.streamingComponent.updateContent(this.streamingMessage,!1),this.streamingMessage.stopReason==="aborted"||this.streamingMessage.stopReason==="error"){n||(n=this.streamingMessage.errorMessage||"Error");for(let[,i]of this.pendingTools.entries())i.updateResult({content:[{type:"text",text:n}],isError:!0});this.pendingTools.clear()}else{for(let[,i]of this.pendingTools.entries())i.setArgsComplete();this.maybeShowCacheMissNotice(this.streamingMessage)}this.streamingComponent=void 0,this.streamingMessage=void 0,this.footer.invalidate()}this.ui.requestRender();break;case"bash_execution_update":break;case"tool_execution_start":{let n=this.pendingTools.get(e.toolCallId);n||(n=new qi(e.toolName,e.toolCallId,e.args,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(e.toolName),this.ui,this.sessionManager.getCwd()),n.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(n),this.pendingTools.set(e.toolCallId,n)),n.markExecutionStarted(),this.ui.requestRender();break}case"tool_execution_update":{let n=this.pendingTools.get(e.toolCallId);n&&(n.updateResult({...e.partialResult,isError:!1},!0),this.ui.requestRender());break}case"tool_execution_end":{let n=this.pendingTools.get(e.toolCallId);n&&(n.updateResult({...e.result,isError:e.isError}),this.pendingTools.delete(e.toolCallId),this.ui.requestRender());break}case"agent_end":this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.clearStatusIndicator("working"),this.streamingComponent&&(this.chatContainer.removeChild(this.streamingComponent),this.streamingComponent=void 0,this.streamingMessage=void 0),this.pendingTools.clear(),this.ui.requestRender();break;case"agent_settled":await this.checkShutdownRequested();break;case"compaction_start":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!0),this.autoCompactionEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortCompaction()},this.showStatusIndicator(new dp(this.ui,e.reason)),this.ui.requestRender();break}case"compaction_end":{this.settingsManager.getShowTerminalProgress()&&this.ui.terminal.setProgress(!1),this.autoCompactionEscapeHandler&&(this.defaultEditor.onEscape=this.autoCompactionEscapeHandler,this.autoCompactionEscapeHandler=void 0),this.clearStatusIndicator("compaction"),e.aborted?e.reason==="manual"?this.showError("Compaction cancelled"):this.showStatus("Auto-compaction cancelled"):e.result?(this.chatContainer.clear(),this.rebuildChatFromMessages(),this.addMessageToChat(Ou(e.result.summary,e.result.tokensBefore,new Date().toISOString())),this.footer.invalidate()):e.errorMessage&&(e.reason==="manual"?this.showError(e.errorMessage):(this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new E(x.fg("error",e.errorMessage),1,0)))),this.flushCompactionQueue({willRetry:e.willRetry}),this.ui.requestRender();break}case"auto_retry_start":{this.retryEscapeHandler=this.defaultEditor.onEscape,this.defaultEditor.onEscape=()=>{this.session.abortRetry()},this.showStatusIndicator(new pp(this.ui,e.attempt,e.maxAttempts,e.delayMs)),this.ui.requestRender();break}case"auto_retry_end":{this.retryEscapeHandler&&(this.defaultEditor.onEscape=this.retryEscapeHandler,this.retryEscapeHandler=void 0),this.clearStatusIndicator("retry"),e.success||this.showError(`Retry failed after ${e.attempt} attempts: ${e.finalError||"Unknown error"}`),this.ui.requestRender();break}case"summarization_retry_scheduled":{this.showError(e.errorMessage),this.showStatusIndicator(new pp(this.ui,e.attempt,e.maxAttempts,e.delayMs)),this.ui.requestRender();break}case"summarization_retry_attempt_start":{this.clearStatusIndicator("retry"),e.source==="branchSummary"?this.showStatusIndicator(new mp(this.ui)):this.showStatusIndicator(new dp(this.ui,e.reason)),this.ui.requestRender();break}case"summarization_retry_finished":{this.clearStatusIndicator("retry"),this.ui.requestRender();break}}}getUserMessageText(e){return e.role!=="user"?"":(typeof e.content=="string"?[{type:"text",text:e.content}]:e.content.filter(i=>i.type==="text")).map(i=>i.text).join("")}showStatus(e){let n=this.chatContainer.children,i=n.length>0?n[n.length-1]:void 0,r=n.length>1?n[n.length-2]:void 0;if(i&&r&&i===this.lastStatusText&&r===this.lastStatusSpacer){this.lastStatusText.setText(x.fg("dim",e)),this.ui.requestRender();return}let o=new W(1),s=new E(x.fg("dim",e),1,0);this.chatContainer.addChild(o),this.chatContainer.addChild(s),this.lastStatusSpacer=o,this.lastStatusText=s,this.ui.requestRender()}addCustomEntryToChat(e){let n=this.session.extensionRunner.getEntryRenderer(e.customType);if(!n)return;let i=new zh(e,n);if(i.setExpanded(this.toolOutputExpanded),!!i.hasContent()){if(this.streamingComponent){let r=this.chatContainer.children.indexOf(this.streamingComponent);if(r>=0){this.chatContainer.children.splice(r,0,i);return}}this.chatContainer.addChild(i)}}addMessageToChat(e,n){switch(e.role){case"bashExecution":{let i=new mo(e.command,this.ui,e.excludeFromContext);e.output&&i.appendOutput(e.output),i.setComplete(e.exitCode,e.cancelled,e.truncated?{truncated:!0}:void 0,e.fullOutputPath),this.chatContainer.addChild(i);break}case"custom":{if(e.display){let i=this.session.extensionRunner.getMessageRenderer(e.customType),r=new Rs(e,i,this.getMarkdownThemeWithSettings(),this.outputPad);r.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(r)}break}case"compactionSummary":{this.chatContainer.addChild(new W(1));let i=new Jl(e,this.getMarkdownThemeWithSettings());i.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(i);break}case"branchSummary":{this.chatContainer.addChild(new W(1));let i=new Ql(e,this.getMarkdownThemeWithSettings());i.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(i);break}case"user":{let i=this.getUserMessageText(e);if(i){this.chatContainer.children.length>0&&this.chatContainer.addChild(new W(1));let r=nv(i);if(r){let o=new tc(r,this.getMarkdownThemeWithSettings());if(o.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(o),r.userMessage){this.chatContainer.addChild(new W(1));let s=new bo(r.userMessage,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(s)}}else{let o=new bo(i,this.getMarkdownThemeWithSettings(),this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(o)}n?.populateHistory&&this.editor.addToHistory?.(i)}break}case"assistant":{let i=new ji(e,this.hideThinkingBlock,this.getMarkdownThemeWithSettings(),this.hiddenThinkingLabel,this.outputPad,this.getMarkdownTransformers());this.chatContainer.addChild(i);break}case"toolResult":break;default:{let i=e}}}renderSessionItems(e,n={}){this.pendingTools.clear();let i=new Map,r=this.settingsManager.getShowCacheMissNotices()?v_(this.sessionManager.getEntries(),this.session.modelRuntime):new Map;n.updateFooter&&(this.footer.invalidate(),this.updateEditorBorderColor());for(let o of e){if(iQ(o)){this.addCustomEntryToChat(o);continue}let s=o;if(s.role==="assistant"){this.addMessageToChat(s);for(let a of s.content)if(a.type==="toolCall"){let l=new qi(a.name,a.id,a.arguments,{showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells()},this.getRegisteredToolDefinition(a.name),this.ui,this.sessionManager.getCwd());if(l.setExpanded(this.toolOutputExpanded),this.chatContainer.addChild(l),s.stopReason==="aborted"||s.stopReason==="error"){let c;if(s.stopReason==="aborted"){let u=this.session.retryAttempt;c=u>0?`Aborted after ${u} retry attempt${u>1?"s":""}`:"Operation aborted"}else c=s.errorMessage||"Error";l.updateResult({content:[{type:"text",text:c}],isError:!0})}else i.set(a.id,l)}if(s.stopReason!=="aborted"&&s.stopReason!=="error"){let a=r.get(s);a&&this.addCacheMissNotice(a)}}else if(s.role==="toolResult"){let a=i.get(s.toolCallId);a&&(a.updateResult(s),i.delete(s.toolCallId))}else this.addMessageToChat(s,n)}for(let[o,s]of i)this.pendingTools.set(o,s);this.ui.requestRender()}renderSessionEntries(e,n={}){let i=e.flatMap(r=>r.type==="custom"?[r]:Wu(r));this.renderSessionItems(i,n)}maybeShowCacheMissNotice(e){if(!this.settingsManager.getShowCacheMissNotices())return;let n=y_(this.sessionManager.getEntries(),e,this.session.modelRuntime);n&&this.addCacheMissNotice(n)}addCacheMissNotice(e){if(e.missedTokens<2e4&&e.missedCost<.1)return;let n=e.missedCost>=.01?` (~$${e.missedCost.toFixed(2)})`:"",i=`${Sr(e.missedTokens)} tokens re-billed${n}`,r="Cache miss";e.modelChanged?r="Cache miss after model switch":e.idleMs>=3e5&&(r=`Cache miss after ${Math.round(e.idleMs/6e4)}m idle`);let o=x.fg("warning",`${r}: ${i}`);this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new E(o,1,0))}renderInitialMessages(){let e=this.sessionManager.buildContextEntries();this.renderSessionEntries(e,{updateFooter:!0,populateHistory:!0}),this.renderProjectTrustWarningIfNeeded();let i=this.sessionManager.getEntries().filter(r=>r.type==="compaction").length;if(i>0){let r=i===1?"1 time":`${i} times`;this.showStatus(`Session compacted ${r}`)}}renderProjectTrustWarningIfNeeded(){this.settingsManager.isProjectTrusted()||!Ts(this.sessionManager.getCwd())||(this.chatContainer.children.length>0&&this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new E(x.fg("warning",`This project is not trusted. Project ${rt} resources and packages are ignored. Use /trust to save a trust decision, then restart sling.`),1,0)))}async getUserInput(){let e=this.pendingUserInputs.shift();return e!==void 0?e:new Promise(n=>{this.onInputCallback=i=>{this.onInputCallback=void 0,n(i)}})}rebuildChatFromMessages(){this.chatContainer.clear(),this.renderSessionEntries(this.sessionManager.buildContextEntries())}handleCtrlC(){let e=Date.now();e-this.lastSigintTime<500?this.shutdown():(this.clearEditor(),this.lastSigintTime=e)}handleCtrlD(){this.shutdown()}async shutdown(e){if(this.isShuttingDown)return;this.isShuttingDown=!0,e?.fromSignal&&(await this.runtimeHost.dispose(),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),process.exit(0)),this.themeController.disableAutoSync(),await this.ui.terminal.drainInput(1e3),this.stop(),await this.runtimeHost.dispose();let n=cQ(this.sessionManager);n&&process.stdout.write(`${tQ.dim("To resume this session:")} ${n}
|
|
304
|
-
`),process.exit(0)}emergencyTerminalExit(){this.isShuttingDown=!0,this.unregisterSignalHandlers(),Pl(),process.exit(129)}uncaughtCrash(e){this.isShuttingDown&&process.exit(1),this.isShuttingDown=!0;try{this.unregisterSignalHandlers()}catch{}try{Pl()}catch{}try{this.ui.stop()}catch{}console.error("
|
|
304
|
+
`),process.exit(0)}emergencyTerminalExit(){this.isShuttingDown=!0,this.unregisterSignalHandlers(),Pl(),process.exit(129)}uncaughtCrash(e){this.isShuttingDown&&process.exit(1),this.isShuttingDown=!0;try{this.unregisterSignalHandlers()}catch{}try{Pl()}catch{}try{this.ui.stop()}catch{}console.error("sling exiting due to uncaughtException:"),console.error(e),process.exit(1)}async checkShutdownRequested(){this.shutdownRequested&&await this.shutdown()}registerSignalHandlers(){this.unregisterSignalHandlers();let e=["SIGTERM"];process.platform!=="win32"&&e.push("SIGHUP");for(let r of e){let o=()=>{Pl(),this.shutdown({fromSignal:!0})};process.prependListener(r,o),this.signalCleanupHandlers.push(()=>process.off(r,o))}let n=r=>{throw oQ(r)&&this.emergencyTerminalExit(),r};process.stdout.on("error",n),process.stderr.on("error",n),this.signalCleanupHandlers.push(()=>process.stdout.off("error",n)),this.signalCleanupHandlers.push(()=>process.stderr.off("error",n));let i=r=>this.uncaughtCrash(r);process.prependListener("uncaughtException",i),this.signalCleanupHandlers.push(()=>process.off("uncaughtException",i))}unregisterSignalHandlers(){for(let e of this.signalCleanupHandlers)e();this.signalCleanupHandlers=[]}handleCtrlZ(){if(process.platform==="win32"){this.showStatus("Suspend to background is not supported on Windows");return}let e=setInterval(()=>{},2**30),n=()=>{};process.on("SIGINT",n),process.once("SIGCONT",()=>{clearInterval(e),process.removeListener("SIGINT",n),this.ui.start(),this.ui.requestRender(!0)});try{this.ui.stop(),process.kill(0,"SIGTSTP")}catch(i){throw clearInterval(e),process.removeListener("SIGINT",n),i}}async handleFollowUp(){let e=(this.editor.getExpandedText?.()??this.editor.getText()).trim();if(e){if(this.session.isCompacting){this.isExtensionCommand(e)?(this.editor.addToHistory?.(e),this.editor.setText(""),await this.session.prompt(e)):this.queueCompactionMessage(e,"followUp");return}this.session.isStreaming?(this.editor.addToHistory?.(e),this.editor.setText(""),await this.session.prompt(e,{streamingBehavior:"followUp"}),this.updatePendingMessagesDisplay(),this.ui.requestRender()):this.editor.onSubmit&&(this.editor.setText(""),this.editor.onSubmit(e))}}handleDequeue(){let e=this.restoreQueuedMessagesToEditor();e===0?this.showStatus("No queued messages to restore"):this.showStatus(`Restored ${e} queued message${e>1?"s":""} to editor`)}updateEditorBorderColor(){if(this.isBashMode)this.editor.borderColor=x.getBashModeBorderColor();else{let e=this.session.thinkingLevel||"off";this.editor.borderColor=x.getThinkingBorderColor(e)}this.ui.requestRender()}cycleThinkingLevel(){let e=this.session.cycleThinkingLevel();e===void 0?this.showStatus("Current model does not support thinking"):(this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Thinking level: ${e}`))}async cycleModel(e){try{let n=await this.session.cycleModel(e);if(n===void 0){let i=this.session.scopedModels.length>0?"Only one model in scope":"Only one model available";this.showStatus(i)}else{this.footer.invalidate(),this.updateEditorBorderColor();let i=n.model.reasoning&&n.thinkingLevel!=="off"?` (thinking: ${n.thinkingLevel})`:"";this.showStatus(`Switched to ${n.model.name||n.model.id}${i}`),this.maybeWarnAboutAnthropicSubscriptionAuth(n.model)}}catch(n){this.showError(n instanceof Error?n.message:String(n))}}toggleToolOutputExpansion(){this.setToolsExpanded(!this.toolOutputExpanded)}setToolsExpanded(e){if(e===this.toolOutputExpanded)return;this.toolOutputExpanded=e;let n=this.customHeader??this.builtInHeader;gp(n)&&n.setExpanded(e);for(let i of[this.loadedResourcesContainer,this.chatContainer])for(let r of i.children)gp(r)&&r.setExpanded(e);this.showStatus(`Tool output: ${e?"expanded":"collapsed"}`)}toggleThinkingBlockVisibility(){this.hideThinkingBlock=!this.hideThinkingBlock,this.settingsManager.setHideThinkingBlock(this.hideThinkingBlock),this.chatContainer.clear(),this.rebuildChatFromMessages(),this.streamingComponent&&this.streamingMessage&&(this.streamingComponent.setHideThinkingBlock(this.hideThinkingBlock),this.streamingComponent.updateContent(this.streamingMessage),this.chatContainer.addChild(this.streamingComponent)),this.showStatus(`Thinking blocks: ${this.hideThinkingBlock?"hidden":"visible"}`)}async handleOpenExternalEditor(){let e=this.settingsManager.getExternalEditorCommand(),n=this.editor.getExpandedText?.()??this.editor.getText();this.ui.stop();try{let i=await Jh({command:e,content:n});i.status==="complete"&&this.editor.setText(i.content)}finally{this.ui.start(),this.ui.requestRender(!0)}}clearEditor(){this.editor.setText(""),this.ui.requestRender()}showError(e){this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new E(x.fg("error",`Error: ${e}`),this.outputPad,0)),this.ui.requestRender()}showWarning(e){this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new E(x.fg("warning",`Warning: ${e}`),1,0)),this.ui.requestRender()}showNewVersionNotification(e){let n=x.fg("accent",`${Mt} update`),i=x.fg("muted",`New version ${e.version} is available. Run `)+n,r="https://pi.dev/changelog",o=at().hyperlinks?no(x.fg("accent",r),r):x.fg("accent",r),s=x.fg("muted","Changelog: ")+o,a=e.note?.trim();this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new V(l=>x.fg("warning",l))),this.chatContainer.addChild(new E(`${x.bold(x.fg("warning","Update Available"))}
|
|
305
305
|
${i}`,1,0)),a&&(this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new Xe(a,1,0,this.getMarkdownThemeWithSettings(),{color:l=>x.fg("muted",l)})),this.chatContainer.addChild(new W(1))),this.chatContainer.addChild(new E(s,1,0)),this.chatContainer.addChild(new V(l=>x.fg("warning",l))),this.ui.requestRender()}showPackageUpdateNotification(e){let n=x.fg("accent",`${Mt} update --extensions`),i=x.fg("muted","Package updates are available. Run ")+n,r=e.map(o=>`- ${o}`).join(`
|
|
306
306
|
`);this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new V(o=>x.fg("warning",o))),this.chatContainer.addChild(new E(`${x.bold(x.fg("warning","Package Updates Available"))}
|
|
307
307
|
${i}
|
|
@@ -310,7 +310,7 @@ ${r}`,1,0)),this.chatContainer.addChild(new V(o=>x.fg("warning",o))),this.ui.req
|
|
|
310
310
|
|
|
311
311
|
`),s=e?.currentText??this.editor.getText(),a=[o,s].filter(l=>l.trim()).join(`
|
|
312
312
|
|
|
313
|
-
`);return this.editor.setText(a),this.updatePendingMessagesDisplay(),e?.abort&&this.agent.abort(),r.length}queueCompactionMessage(e,n){this.compactionQueuedMessages.push({text:e,mode:n}),this.editor.addToHistory?.(e),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(e){if(!e.startsWith("/"))return!1;let n=this.session.extensionRunner,i=e.indexOf(" "),r=i===-1?e.slice(1):e.slice(1,i);return!!n.getCommand(r)}async flushCompactionQueue(e){if(this.compactionQueuedMessages.length===0)return;let n=[...this.compactionQueuedMessages];this.compactionQueuedMessages=[],this.updatePendingMessagesDisplay();let i=r=>{this.session.clearQueue(),this.compactionQueuedMessages=n,this.updatePendingMessagesDisplay(),this.showError(`Failed to send queued message${n.length>1?"s":""}: ${r instanceof Error?r.message:String(r)}`)};try{if(e?.willRetry){for(let c of n)this.isExtensionCommand(c.text)?await this.session.prompt(c.text):c.mode==="followUp"?await this.session.followUp(c.text):await this.session.steer(c.text);this.updatePendingMessagesDisplay();return}let r=n.findIndex(c=>!this.isExtensionCommand(c.text));if(r===-1){for(let c of n)await this.session.prompt(c.text);return}let o=n.slice(0,r),s=n[r],a=n.slice(r+1);for(let c of o)await this.session.prompt(c.text);let l=this.session.prompt(s.text,{streamingBehavior:s.mode}).catch(c=>{i(c)});for(let c of a)this.isExtensionCommand(c.text)?await this.session.prompt(c.text):c.mode==="followUp"?await this.session.followUp(c.text):await this.session.steer(c.text);this.updatePendingMessagesDisplay()}catch(r){i(r)}}flushPendingBashComponents(){for(let e of this.pendingBashComponents)this.pendingMessagesContainer.removeChild(e),this.chatContainer.addChild(e);this.pendingBashComponents=[]}disposeActiveSelector(){let e=this.activeSelectorDispose;this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,e?.()}showSelector(e){let n={},i,o=e(()=>{i?.(),this.activeSelectorToken===n&&(this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor))});i=o.dispose,this.disposeActiveSelector(),this.activeSelectorToken=n,this.activeSelectorDispose=i,this.editorContainer.clear(),this.editorContainer.addChild(o.component),this.ui.setFocus(o.focus),this.ui.requestRender()}showSettingsSelector(){this.showSelector(e=>{let n;return n=new ec({autoCompact:this.session.autoCompactionEnabled,showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),autoResizeImages:this.settingsManager.getImageAutoResize(),blockImages:this.settingsManager.getBlockImages(),enableSkillCommands:this.settingsManager.getEnableSkillCommands(),steeringMode:this.session.steeringMode,followUpMode:this.session.followUpMode,transport:this.settingsManager.getTransport(),httpIdleTimeoutMs:this.settingsManager.getHttpIdleTimeoutMs(),thinkingLevel:this.session.thinkingLevel,availableThinkingLevels:this.session.getAvailableThinkingLevels(),currentTheme:this.settingsManager.getThemeSetting()||"dark",terminalTheme:this.themeController.getTerminalTheme(),availableThemes:ax(),hideThinkingBlock:this.hideThinkingBlock,mermaidRenderingMode:this.settingsManager.getMermaidRenderingMode(),collapseChangelog:this.settingsManager.getCollapseChangelog(),enableInstallTelemetry:this.settingsManager.getEnableInstallTelemetry(),doubleEscapeAction:this.settingsManager.getDoubleEscapeAction(),treeFilterMode:this.settingsManager.getTreeFilterMode(),showHardwareCursor:this.settingsManager.getShowHardwareCursor(),showCacheMissNotices:this.settingsManager.getShowCacheMissNotices(),defaultProjectTrust:this.settingsManager.getDefaultProjectTrust(),editorPaddingX:this.settingsManager.getEditorPaddingX(),outputPad:this.settingsManager.getOutputPad(),autocompleteMaxVisible:this.settingsManager.getAutocompleteMaxVisible(),quietStartup:this.settingsManager.getQuietStartup(),clearOnShrink:this.settingsManager.getClearOnShrink(),showTerminalProgress:this.settingsManager.getShowTerminalProgress(),tuiMode:this.ui.mode,fullscreenExitOutput:this.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:this.settingsManager.getFullscreenScrollbar(),warnings:this.settingsManager.getWarnings()},{onAutoCompactChange:i=>{this.session.setAutoCompactionEnabled(i),this.footer.setAutoCompactEnabled(i)},onShowImagesChange:i=>{this.settingsManager.setShowImages(i);for(let r of this.chatContainer.children)r instanceof qi&&r.setShowImages(i)},onImageWidthCellsChange:i=>{this.settingsManager.setImageWidthCells(i);for(let r of this.chatContainer.children)r instanceof qi&&r.setImageWidthCells(i)},onAutoResizeImagesChange:i=>{this.settingsManager.setImageAutoResize(i)},onBlockImagesChange:i=>{this.settingsManager.setBlockImages(i)},onEnableSkillCommandsChange:i=>{this.settingsManager.setEnableSkillCommands(i),this.setupAutocompleteProvider()},onSteeringModeChange:i=>{this.session.setSteeringMode(i)},onFollowUpModeChange:i=>{this.session.setFollowUpMode(i)},onTransportChange:i=>{this.settingsManager.setTransport(i),this.session.agent.transport=i},onHttpIdleTimeoutMsChange:i=>{this.settingsManager.setHttpIdleTimeoutMs(i),Nh(i),this.showStatus(`HTTP idle timeout: ${$h(i)}`)},onThinkingLevelChange:i=>{this.session.setThinkingLevel(i),this.footer.invalidate(),this.updateEditorBorderColor()},onThemeChange:i=>{this.settingsManager.setTheme(i),this.themeController.applyFromSettings()},onThemePreview:i=>this.themeController.preview(i),onHideThinkingBlockChange:i=>{this.hideThinkingBlock=i,this.settingsManager.setHideThinkingBlock(i);for(let r of this.chatContainer.children)r instanceof ji&&r.setHideThinkingBlock(i);this.chatContainer.clear(),this.rebuildChatFromMessages()},onMermaidRenderingModeChange:i=>{this.settingsManager.setMermaidRenderingMode(i),this.chatContainer.invalidate(),this.ui.requestRender()},onShowCacheMissNoticesChange:i=>{this.settingsManager.setShowCacheMissNotices(i),this.rebuildChatFromMessages()},onCollapseChangelogChange:i=>{this.settingsManager.setCollapseChangelog(i)},onEnableInstallTelemetryChange:i=>{this.settingsManager.setEnableInstallTelemetry(i)},onQuietStartupChange:i=>{this.settingsManager.setQuietStartup(i)},onDefaultProjectTrustChange:i=>{this.settingsManager.setDefaultProjectTrust(i)},onDoubleEscapeActionChange:i=>{this.settingsManager.setDoubleEscapeAction(i)},onTreeFilterModeChange:i=>{this.settingsManager.setTreeFilterMode(i)},onShowHardwareCursorChange:i=>{this.settingsManager.setShowHardwareCursor(i),this.ui.setShowHardwareCursor(i)},onEditorPaddingXChange:i=>{this.settingsManager.setEditorPaddingX(i),this.defaultEditor.setPaddingX(i),this.editor!==this.defaultEditor&&this.editor.setPaddingX!==void 0&&this.editor.setPaddingX(i)},onOutputPadChange:i=>{if(this.settingsManager.setOutputPad(i),this.outputPad=i,this.streamingComponent||this.session.isStreaming){for(let r of this.chatContainer.children)(r instanceof ji||r instanceof Rs||r instanceof bo)&&r.setOutputPad(i);this.streamingComponent&&this.streamingComponent.setOutputPad(i),this.ui.requestRender();return}this.rebuildChatFromMessages()},onAutocompleteMaxVisibleChange:i=>{this.settingsManager.setAutocompleteMaxVisible(i),this.defaultEditor.setAutocompleteMaxVisible(i),this.editor!==this.defaultEditor&&this.editor.setAutocompleteMaxVisible!==void 0&&this.editor.setAutocompleteMaxVisible(i)},onClearOnShrinkChange:i=>{this.settingsManager.setClearOnShrink(i),this.ui.setClearOnShrink(i),!i&&!this.activeStatusIndicator&&this.statusContainer.clear()},onShowTerminalProgressChange:i=>{this.settingsManager.setShowTerminalProgress(i)},onTuiModeChange:i=>{if(!this.switchTuiMode(i)){n?.getSettingsList().updateValue("tui-mode",this.ui.mode),this.showStatus("Close active overlays before changing TUI mode");return}this.settingsManager.setTuiMode(i),this.activeStatusIndicator||this.statusContainer.clear(),this.showStatus(`TUI mode: ${i}`)},onFullscreenExitOutputChange:i=>{this.settingsManager.setFullscreenExitOutput(i)},onFullscreenScrollbarChange:i=>{this.settingsManager.setFullscreenScrollbar(i),this.applyFullscreenScrollbarSetting()},onWarningsChange:i=>{this.settingsManager.setWarnings(i)},onCancel:()=>{e(),this.ui.requestRender()}}),{component:n,focus:n.getSettingsList()}})}async handleModelCommand(e){if(!e){this.showModelSelector();return}let n=await this.findExactModelMatch(e);if(n){try{await this.session.setModel(n),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${n.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(n),this.checkDaxnutsEasterEgg(n)}catch(i){this.showError(i instanceof Error?i.message:String(i))}return}this.showModelSelector(e)}async findExactModelMatch(e){let n=this.session.scopedModels.length>0?this.session.scopedModels.map(a=>a.model):[...this.session.modelRuntime.getAvailableSnapshot()],i=zu(e,n);if(i||this.session.scopedModels.length>0)return i;this.showStatus("Refreshing model catalogs\u2026");let r=new AbortController,o=!1,s=setTimeout(()=>{o=!0,r.abort()},15e3);try{let a=await this.session.modelRuntime.refresh({signal:r.signal});a.aborted&&o?this.showWarning("Model refresh timed out; searching cached models."):a.errors.size>0&&this.showWarning(`Could not refresh ${[...a.errors.keys()].join(", ")}; searching cached models.`)}catch(a){this.showWarning(o?"Model refresh timed out; searching cached models.":`Could not refresh model catalogs: ${a instanceof Error?a.message:String(a)}`)}finally{clearTimeout(s)}return zu(e,[...this.session.modelRuntime.getAvailableSnapshot()])}updateAvailableProviderCount(){let e=this.session.scopedModels.length>0?this.session.scopedModels.map(i=>i.model):this.session.modelRuntime.getAvailableSnapshot(),n=new Set(e.map(i=>i.provider));this.footerDataProvider.setAvailableProviderCount(n.size)}async maybeWarnAboutAnthropicSubscriptionAuth(e=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!e||e.provider!=="anthropic"))try{if((await this.session.modelRuntime.checkAuth("anthropic"))?.type==="oauth"){this.anthropicSubscriptionWarningShown=!0,this.showWarning(eO);return}let n=(await this.session.modelRuntime.getAuth(e.provider))?.auth.apiKey;if(!sQ(n))return;this.anthropicSubscriptionWarningShown=!0,this.showWarning(eO)}catch{}}maybeSaveImplicitProjectTrustAfterReload(){let e=this.sessionManager.getCwd();if(this.autoTrustOnReloadCwd!==e||!this.settingsManager.isProjectTrusted()||!Ts(e))return!1;let n=new co(this.runtimeHost.services.agentDir);try{return n.get(e)!==null?(this.autoTrustOnReloadCwd=void 0,!1):(n.set(e,!0),this.autoTrustOnReloadCwd=void 0,!0)}catch(i){return this.showWarning(`Could not save project trust after reload: ${i instanceof Error?i.message:String(i)}`),!1}}showTrustSelector(){let e=this.sessionManager.getCwd(),n=new co(this.runtimeHost.services.agentDir),i=n.getEntry(e);this.showSelector(r=>{let o=new hp({cwd:e,savedDecision:i,projectTrusted:this.settingsManager.isProjectTrusted(),onSelect:s=>{n.setMany(s.updates),r(),this.showStatus(`Saved trust decision: ${s.trusted?"trusted":"untrusted"}. Restart pi for this to take effect.`)},onCancel:()=>{r(),this.ui.requestRender()}});return{component:o,focus:o}})}showModelSelector(e){this.showSelector(n=>{let i=new Zl(this.ui,this.session.model,this.settingsManager,this.session.modelRuntime,this.session.scopedModels,async r=>{try{await this.session.setModel(r),this.footer.invalidate(),this.updateEditorBorderColor(),n(),this.showStatus(`Model: ${r.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(r),this.checkDaxnutsEasterEgg(r)}catch(o){n(),this.showError(o instanceof Error?o.message:String(o))}},()=>{n(),this.ui.requestRender()},e);return{component:i,focus:i,dispose:()=>i.dispose()}})}showModelsSelector(){let e=[...this.session.modelRuntime.getAvailableSnapshot()],n=new Set(e.map(c=>`${c.provider}/${c.id}`)),i=this.settingsManager.getEnabledModels(),r=this.session.scopedModels,o=c=>{if(!i?.length)return null;let u=ov(i,c),p=u.scopedModels.map(d=>`${d.model.provider}/${d.model.id}`);for(let d of u.diagnostics)d.code==="no-match"&&!p.includes(d.pattern)&&p.push(d.pattern);return p},s=r.length>0?r.map(c=>`${c.model.provider}/${c.model.id}`):o(e),a=!1,l=c=>{s=c===null?null:[...c];let u=c?.some(d=>n.has(d))??!1,p=c!==null&&[...n].every(d=>c.includes(d));if(c&&u&&!p){let d=ov(c,e).scopedModels;this.session.setScopedModels(d.map(m=>({model:m.model,thinkingLevel:m.thinkingLevel})))}else this.session.setScopedModels([]);this.updateAvailableProviderCount(),this.ui.requestRender()};this.showSelector(c=>{let u=!1,p=!1,d=new AbortController,m=setTimeout(()=>{p=!0,d.abort()},15e3),g=new lp({allModels:e,enabledModelIds:s,refreshStatus:"Refreshing model catalogs\u2026"},{onChange:h=>{a=!0,l(h)},onPersist:h=>{let f=h!==null&&h.length===e.length&&h.every(v=>n.has(v)),b=h===null||f?void 0:h;this.settingsManager.setEnabledModels(b?[...b]:void 0),this.showStatus("Model selection saved to settings")},onCancel:()=>{c(),this.ui.requestRender()}});return this.session.modelRuntime.refresh({signal:d.signal}).then(h=>{u||(e=[...this.session.modelRuntime.getAvailableSnapshot()],n=new Set(e.map(f=>`${f.provider}/${f.id}`)),!a&&r.length===0?(s=o(e),g.updateModels(e,s)):g.updateModels(e),s!==null&&l(s),h.aborted&&p?g.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):h.errors.size>0?g.setRefreshStatus(`Could not refresh ${[...h.errors.keys()].join(", ")}; showing cached models.`,"warning"):g.setRefreshStatus("Model catalogs refreshed.","success"),this.ui.requestRender())}).catch(h=>{u||(g.setRefreshStatus(p?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${h instanceof Error?h.message:String(h)}`,"warning"),this.ui.requestRender())}).finally(()=>clearTimeout(m)),{component:g,focus:g,dispose:()=>{u=!0,clearTimeout(m),d.abort()}}})}showUserMessageSelector(){let e=this.session.getUserMessagesForForking();if(e.length===0){this.showStatus("No messages to fork from");return}let n=e[e.length-1]?.entryId;this.showSelector(i=>{let r=new rc(e.map(o=>({id:o.entryId,text:o.text})),async o=>{i();try{let s=await this.runtimeHost.fork(o);if(s.cancelled){this.ui.requestRender();return}this.editor.setText(s.selectedText??""),this.showStatus("Forked to new session")}catch(s){this.showError(s instanceof Error?s.message:String(s))}},()=>{i(),this.ui.requestRender()},n);return{component:r,focus:r.getMessageList()}})}async handleCloneCommand(){let e=this.sessionManager.getLeafId();if(!e){this.showStatus("Nothing to clone yet");return}try{if((await this.runtimeHost.fork(e,{position:"at"})).cancelled){this.ui.requestRender();return}this.editor.setText(""),this.showStatus("Cloned to new session")}catch(n){this.showError(n instanceof Error?n.message:String(n))}}showTreeSelector(e){let n=this.sessionManager.getTree(),i=this.sessionManager.getLeafId(),r=this.settingsManager.getTreeFilterMode();if(n.length===0){this.showStatus("No entries in session");return}this.showSelector(o=>{let s=new ic(n,i,this.ui.terminal.rows,async a=>{if(a===this.sessionManager.getLeafId()){o(),this.showStatus("Already at this point");return}o();let l=!1,c;if(!this.settingsManager.getBranchSummarySkipPrompt())for(;;){let d=await this.showExtensionSelector("Summarize branch?",["No summary","Summarize","Summarize with custom prompt"]);if(d===void 0){this.showTreeSelector(a);return}if(l=d!=="No summary",!(d==="Summarize with custom prompt"&&(c=await this.showExtensionEditor("Custom summarization instructions"),c===void 0)))break}this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort());let u=!1,p=this.defaultEditor.onEscape;l&&(this.defaultEditor.onEscape=()=>{this.session.abortBranchSummary()},this.chatContainer.addChild(new W(1)),this.showStatusIndicator(new mp(this.ui)),u=!0,this.ui.requestRender());try{let d=await this.session.navigateTree(a,{summarize:l,customInstructions:c});if(d.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(a);return}if(d.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),d.editorText&&!this.editor.getText().trim()&&this.editor.setText(d.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1})}catch(d){this.showError(d instanceof Error?d.message:String(d))}finally{u&&this.clearStatusIndicator("branchSummary"),this.defaultEditor.onEscape=p}},()=>{o(),this.ui.requestRender()},(a,l)=>{this.sessionManager.appendLabelChange(a,l),this.ui.requestRender()},e,r);return s.onCopy=async a=>{if(!a){this.showError("Selected entry has no text to copy");return}try{await zl(a),this.showStatus("Copied selected message to clipboard")}catch(l){this.showError(l instanceof Error?l.message:String(l))}},{component:s,focus:s}})}showSessionSelector(){this.showSelector(e=>{let n=new Cs(i=>Xn.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),i),i=>this.sessionManager.usesDefaultSessionDir()?Xn.listAll(i):Xn.listAll(this.sessionManager.getSessionDir(),i),async i=>{e(),await this.handleResumeSession(i)},()=>{e(),this.ui.requestRender()},()=>{this.shutdown()},()=>this.ui.requestRender(),{renameSession:async(i,r)=>{let o=(r??"").trim();if(!o)return;Xn.open(i).appendSessionInfo(o)},showRenameHint:!0,keybindings:this.keybindings},this.sessionManager.getSessionFile());return{component:n,focus:n}})}async handleResumeSession(e,n){this.clearStatusIndicator();try{let i=await this.runtimeHost.switchSession(e,{withSession:n?.withSession,projectTrustContextFactory:r=>this.createProjectTrustContext(r)});return i.cancelled||this.showStatus("Resumed session"),i}catch(i){if(i instanceof Gl){let r=await this.promptForMissingSessionCwd(i);if(!r)return this.showStatus("Resume cancelled"),{cancelled:!0};let o=await this.runtimeHost.switchSession(e,{cwdOverride:r,withSession:n?.withSession,projectTrustContextFactory:s=>this.createProjectTrustContext(s)});return o.cancelled||this.showStatus("Resumed session in current cwd"),o}return this.handleFatalRuntimeError("Failed to resume session",i)}}getLoginProviderOptions(e){let n=[];for(let i of this.session.modelRuntime.getProviders()){let r=this.session.modelRuntime.getProviderAuthStatus(i.id),o=r.configured?{type:this.session.modelRuntime.isUsingOAuth(i.id)?"oauth":"api_key",source:r.label??r.source}:void 0;(!e||e==="oauth")&&i.auth.oauth&&n.push({id:i.id,name:i.name,authType:"oauth",method:i.auth.oauth,status:o}),(!e||e==="api_key")&&i.auth.apiKey&&n.push({id:i.id,name:i.name,authType:"api_key",method:i.auth.apiKey,status:o})}return n.sort((i,r)=>i.name.localeCompare(r.name))}async getLogoutProviderOptions(){return(await this.session.modelRuntime.listCredentials({signal:AbortSignal.timeout(15e3)})).map(({providerId:e,type:n})=>({id:e,name:this.session.modelRuntime.getProvider(e)?.name??e,authType:n,status:{type:n,source:"stored credential"}})).sort((e,n)=>e.name.localeCompare(n.name))}findLoginProviderOptions(e){let n=e.trim().toLowerCase();return n?this.getLoginProviderOptions().filter(i=>i.id.toLowerCase()===n||i.name.toLowerCase()===n):[]}async handleLoginCommand(e){if(!e){this.showLoginAuthTypeSelector();return}let n=this.findLoginProviderOptions(e);if(n.length===1){await this.startProviderLogin(n[0]);return}if(n.length>1&&new Set(n.map(r=>r.id)).size===1){this.showLoginAuthTypeSelector(n);return}this.showLoginProviderSelector(void 0,e)}async startProviderLogin(e){e.authType==="oauth"?await this.showLoginDialog(e.id,e.name):e.method?.login?await this.showApiKeyLoginDialog(e.id,e.name):this.showAmbientAuthDialog(e)}showLoginAuthTypeSelector(e){let n=e?.find(c=>c.authType==="oauth"),r=(n?.method&&"loginLabel"in n.method?n.method.loginLabel:void 0)??"Sign in with an account",o="Sign in with an API key",s=e?new Set(e.map(c=>c.authType)):new Set(["oauth","api_key"]),a=[];if(s.has("oauth")&&a.push(r),s.has("api_key")&&a.push(o),a.length===0){this.showStatus("No login methods available.");return}if(e&&a.length===1){let c=e[0];c&&this.startProviderLogin(c);return}let l=e?.[0]?`Select authentication method for ${e[0].name}:`:"Select authentication method:";this.showSelector(c=>{let u=new yr(l,a,p=>{c();let d=p===r?"oauth":"api_key";if(e){let m=e.find(g=>g.authType===d);m&&this.startProviderLogin(m);return}this.showLoginProviderSelector(d)},()=>{c(),this.ui.requestRender()});return{component:u,focus:u}})}showLoginProviderSelector(e,n){let i=this.getLoginProviderOptions(e);if(i.length===0){let r=e==="oauth"?"No subscription providers available.":e==="api_key"?"No API key providers available.":"No login providers available.";this.showStatus(r);return}this.showSelector(r=>{let o=new Ms("login",i,async(s,a)=>{r();let l=i.find(c=>c.id===s&&c.authType===a);l&&await this.startProviderLogin(l)},()=>{r(),e?this.showLoginAuthTypeSelector():this.ui.requestRender()},n);return{component:o,focus:o}})}async showOAuthSelector(e){if(e==="login"){this.showLoginAuthTypeSelector();return}let n;try{n=(await this.getLogoutProviderOptions()).filter(i=>i.name==="slingshot")}catch(i){this.showError(`Could not read stored credentials: ${i instanceof Error?i.message:String(i)}`);return}if(n.length===0){this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");return}this.showSelector(i=>{let r=new Ms(e,n,async o=>{i();let s=n.find(a=>a.id===o);if(s)try{await this.session.modelRuntime.logout(s.id,{signal:AbortSignal.timeout(15e3)}),await this.updateAvailableProviderCount();let a=s.authType==="oauth"?`Logged out of ${s.name}`:`Removed stored API key for ${s.name}. Environment variables and models.json config are unchanged.`;this.showStatus(a)}catch(a){let l=a instanceof Error?a.message:String(a);this.showError(a instanceof ys?`Credentials removed for ${s.name}, but local model state could not be synchronized: ${l}`:`Logout failed: ${l}`)}},()=>{i(),this.ui.requestRender()});return{component:r,focus:r}})}async completeProviderAuthentication(e,n,i,r){let o=i==="oauth"?`Logged in to ${n}`:`Saved API key for ${n}`,s,a;if(aQ(r)){let p=this.session.modelRuntime.getAvailableSnapshot().filter(d=>d.provider===e);if(!uQ(e))a=`${o}, but no default model is configured for provider "${e}". Use /model to select a model.`;else if(p.length===0)a=`${o}, but no models are available for that provider. Use /model to select a model.`;else{let d=rv[e];if(s=p.find(m=>m.id===d),!s)a=`${o}, but its default model "${d}" is not available. Use /model to select a model.`;else try{await this.session.setModel(s)}catch(m){s=void 0;let g=m instanceof Error?m.message:String(m);a=`${o}, but selecting its default model failed: ${g}. Use /model to select a model.`}}}await this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),s?(this.showStatus(`${o}. Selected ${s.id}. Credentials saved to ${S0()}`),this.maybeWarnAboutAnthropicSubscriptionAuth(s),this.checkDaxnutsEasterEgg(s)):(this.showStatus(`${o}. Credentials saved to ${S0()}`),a?this.showError(a):this.maybeWarnAboutAnthropicSubscriptionAuth());let l=new AbortController,c=setTimeout(()=>l.abort(),15e3);this.session.modelRuntime.refresh({providers:[e],signal:l.signal}).then(u=>{u.aborted?this.showWarning(`${o}, but its model catalog refresh timed out; using cached models.`):u.errors.size>0&&this.showWarning(`${o}, but its model catalog could not be refreshed; using cached models.`),this.updateAvailableProviderCount(),this.footer.invalidate(),this.ui.requestRender()}).catch(u=>{this.showWarning(`${o}, but its model catalog could not be refreshed: ${u instanceof Error?u.message:String(u)}`)}).finally(()=>clearTimeout(c))}showAmbientAuthDialog(e){let n=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},i=new fo(this.ui,e.id,()=>n(),e.name,`${e.name} setup`);i.showInfo(`${e.method?.name??"Authentication"} is configured outside pi.`,[],!0),this.editorContainer.clear(),this.editorContainer.addChild(i),this.ui.setFocus(i),this.ui.requestRender()}async showApiKeyLoginDialog(e,n){let i=this.session.model,r=new fo(this.ui,e,(s,a)=>{},n);e==="amazon-bedrock"&&r.showDetails([x.fg("text","You can also use an AWS profile, IAM keys, or role-based credentials."),x.fg("muted","See:"),x.fg("accent",` ${st.join(Kc(),"providers.md")}`)]),this.editorContainer.clear(),this.editorContainer.addChild(r),this.ui.setFocus(r),this.ui.requestRender();let o=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(r,e,"api_key"),o(),await this.completeProviderAuthentication(e,n,"api_key",i)}catch(s){o();let a=s instanceof Error?s.message:String(s);s instanceof ys?this.showError(`Saved API key for ${n}, but local model state could not be synchronized: ${a}`):a!=="Login cancelled"&&this.showError(`Failed to save API key for ${n}: ${a}`)}}showAuthSelect(e,n){return new Promise((i,r)=>{let o=()=>{this.editorContainer.clear(),this.editorContainer.addChild(e),this.ui.setFocus(e),this.ui.requestRender()},s=n.options.map(l=>l.label),a=new yr(n.message,s,l=>{o();let c=n.options.find(u=>u.label===l)?.id;c?i(c):r(new Error("Login cancelled"))},()=>{o(),r(new Error("Login cancelled"))});this.editorContainer.clear(),this.editorContainer.addChild(a),this.ui.setFocus(a),this.ui.requestRender()})}async showAuthPrompt(e,n){let i;if(n.type==="select"?i=this.showAuthSelect(e,n):n.type==="manual_code"?i=e.showManualInput(n.message):i=e.showPrompt(n.message,n.placeholder),!n.signal)return i;if(n.signal.aborted)throw new Error("Login cancelled");let r=n.signal,o,s=new Promise((a,l)=>{o=()=>l(new Error("Login cancelled")),r.addEventListener("abort",o,{once:!0})});try{return await Promise.race([i,s])}finally{o&&r.removeEventListener("abort",o)}}notifyAuthDialog(e,n){n.type==="auth_url"?e.showAuth(n.url,n.instructions):n.type==="device_code"?(e.showDeviceCode(n),e.showWaiting("Waiting for authentication...")):n.type==="info"?e.showInfo(n.message,n.links):e.showProgress(n.message)}async loginProvider(e,n,i){await this.session.modelRuntime.login(n,i,{signal:e.signal,prompt:r=>this.showAuthPrompt(e,r),notify:r=>this.notifyAuthDialog(e,r)})}async showLoginDialog(e,n){let i=this.session.model,r=new fo(this.ui,e,(s,a)=>{},n);this.editorContainer.clear(),this.editorContainer.addChild(r),this.ui.setFocus(r),this.ui.requestRender();let o=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(r,e,"oauth"),o(),await this.completeProviderAuthentication(e,n,"oauth",i)}catch(s){o();let a=s instanceof Error?s.message:String(s);s instanceof ys?this.showError(`Logged in to ${n}, but local model state could not be synchronized: ${a}`):a!=="Login cancelled"&&this.showError(`Failed to login to ${n}: ${a}`)}}async handleReloadCommand(){if(this.session.isStreaming){this.showWarning("Wait for the current response to finish before reloading.");return}if(this.session.isCompacting){this.showWarning("Wait for compaction to finish before reloading.");return}this.resetExtensionUI();let e=new K,n=l=>x.fg("border",l);e.addChild(new V(n)),e.addChild(new W(1)),e.addChild(new E(x.fg("muted","Reloading keybindings, extensions, skills, prompts, themes, and context files..."),1,0)),e.addChild(new W(1)),e.addChild(new V(n));let i=this.editor;this.editorContainer.clear(),this.editorContainer.addChild(e),this.ui.setFocus(e),this.ui.requestRender(!0),await new Promise(l=>process.nextTick(l));let r=l=>{this.editorContainer.clear(),this.editorContainer.addChild(l),this.ui.setFocus(l),this.ui.requestRender()},o=!1,s=!1,a=()=>{o||(this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.rebuildChatFromMessages(),o=!0)};try{await this.session.reload({beforeSessionStart:a}),a(),this.keybindings.reload();let l=this.customHeader??this.builtInHeader;gp(l)&&l.setExpanded(this.toolOutputExpanded),Mu(this.session.resourceLoader.getThemes().themes),await this.themeController.applyFromSettings(),this.applyRuntimeSettings(),this.setupAutocompleteProvider();let c=this.session.extensionRunner;this.setupExtensionShortcuts(c),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0});let u=this.maybeSaveImplicitProjectTrustAfterReload(),p=this.session.modelRuntime.getError();p&&this.showError(`models.json error: ${p}`),this.showStatus(u?"Reloaded keybindings, extensions, skills, prompts, themes, and context files; saved project trust":"Reloaded keybindings, extensions, skills, prompts, themes, and context files"),r(this.editor),s=!0}catch(l){s||r(i),this.showError(`Reload failed: ${l instanceof Error?l.message:String(l)}`)}}async handleExportCommand(e){let n=this.getPathCommandArgument(e,"/export");try{if(n?.endsWith(".jsonl")){let i=this.session.exportToJsonl(n);this.showStatus(`Session exported to: ${i}`)}else{let i=await this.session.exportToHtml(n);this.showStatus(`Session exported to: ${i}`)}}catch(i){this.showError(`Failed to export session: ${i instanceof Error?i.message:"Unknown error"}`)}}getPathCommandArgument(e,n){if(e===n||!e.startsWith(`${n} `))return;let i=e.slice(n.length+1).trimStart();if(!i)return;let r=i[0];if(r==='"'||r==="'"){let s=i.indexOf(r,1);return s<0?void 0:i.slice(1,s)}let o=i.search(/\s/);return o<0?i:i.slice(0,o)}async handleImportCommand(e){let n=this.getPathCommandArgument(e,"/import");if(!n){this.showError("Usage: /import <path.jsonl>");return}if(!await this.showExtensionConfirm("Import session",`Replace current session with ${n}?`)){this.showStatus("Import cancelled");return}try{if(this.clearStatusIndicator(),(await this.runtimeHost.importFromJsonl(n)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${n}`)}catch(r){if(r instanceof Gl){let o=await this.promptForMissingSessionCwd(r);if(!o){this.showStatus("Import cancelled");return}if((await this.runtimeHost.importFromJsonl(n,o)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${n}`);return}if(r instanceof Bh){this.showError(`Failed to import session: ${r.message}`);return}await this.handleFatalRuntimeError("Failed to import session",r)}}async handleShareCommand(){try{if(nQ("gh",["auth","status"],{encoding:"utf-8"}).status!==0){this.showError("GitHub CLI is not logged in. Run 'gh auth login' first.");return}}catch{this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");return}let e=st.join(fp.tmpdir(),"session.html");try{await this.session.exportToHtml(e)}catch(o){this.showError(`Failed to export session: ${o instanceof Error?o.message:"Unknown error"}`);return}let n=new ho(this.ui,x,"Creating gist...");this.editorContainer.clear(),this.editorContainer.addChild(n),this.ui.setFocus(n),this.ui.requestRender();let i=()=>{n.dispose(),this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor);try{Tr.unlinkSync(e)}catch{}},r=null;n.onAbort=()=>{r?.kill(),i(),this.showStatus("Share cancelled")};try{let o=await new Promise(c=>{r=Z_("gh",["gist","create","--public=false",e]);let u="",p="";r.stdout?.on("data",d=>{u+=d.toString()}),r.stderr?.on("data",d=>{p+=d.toString()}),r.on("close",d=>c({stdout:u,stderr:p,code:d}))});if(n.signal.aborted)return;if(i(),o.code!==0){let c=o.stderr?.trim()||"Unknown error";this.showError(`Failed to create gist: ${c}`);return}let s=o.stdout?.trim(),a=s?.split("/").pop();if(!a){this.showError("Failed to parse gist ID from gh output");return}let l=qk(a);this.showStatus(`Share URL: ${l}
|
|
313
|
+
`);return this.editor.setText(a),this.updatePendingMessagesDisplay(),e?.abort&&this.agent.abort(),r.length}queueCompactionMessage(e,n){this.compactionQueuedMessages.push({text:e,mode:n}),this.editor.addToHistory?.(e),this.editor.setText(""),this.updatePendingMessagesDisplay(),this.showStatus("Queued message for after compaction")}isExtensionCommand(e){if(!e.startsWith("/"))return!1;let n=this.session.extensionRunner,i=e.indexOf(" "),r=i===-1?e.slice(1):e.slice(1,i);return!!n.getCommand(r)}async flushCompactionQueue(e){if(this.compactionQueuedMessages.length===0)return;let n=[...this.compactionQueuedMessages];this.compactionQueuedMessages=[],this.updatePendingMessagesDisplay();let i=r=>{this.session.clearQueue(),this.compactionQueuedMessages=n,this.updatePendingMessagesDisplay(),this.showError(`Failed to send queued message${n.length>1?"s":""}: ${r instanceof Error?r.message:String(r)}`)};try{if(e?.willRetry){for(let c of n)this.isExtensionCommand(c.text)?await this.session.prompt(c.text):c.mode==="followUp"?await this.session.followUp(c.text):await this.session.steer(c.text);this.updatePendingMessagesDisplay();return}let r=n.findIndex(c=>!this.isExtensionCommand(c.text));if(r===-1){for(let c of n)await this.session.prompt(c.text);return}let o=n.slice(0,r),s=n[r],a=n.slice(r+1);for(let c of o)await this.session.prompt(c.text);let l=this.session.prompt(s.text,{streamingBehavior:s.mode}).catch(c=>{i(c)});for(let c of a)this.isExtensionCommand(c.text)?await this.session.prompt(c.text):c.mode==="followUp"?await this.session.followUp(c.text):await this.session.steer(c.text);this.updatePendingMessagesDisplay()}catch(r){i(r)}}flushPendingBashComponents(){for(let e of this.pendingBashComponents)this.pendingMessagesContainer.removeChild(e),this.chatContainer.addChild(e);this.pendingBashComponents=[]}disposeActiveSelector(){let e=this.activeSelectorDispose;this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,e?.()}showSelector(e){let n={},i,o=e(()=>{i?.(),this.activeSelectorToken===n&&(this.activeSelectorToken=void 0,this.activeSelectorDispose=void 0,this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor))});i=o.dispose,this.disposeActiveSelector(),this.activeSelectorToken=n,this.activeSelectorDispose=i,this.editorContainer.clear(),this.editorContainer.addChild(o.component),this.ui.setFocus(o.focus),this.ui.requestRender()}showSettingsSelector(){this.showSelector(e=>{let n;return n=new ec({autoCompact:this.session.autoCompactionEnabled,showImages:this.settingsManager.getShowImages(),imageWidthCells:this.settingsManager.getImageWidthCells(),autoResizeImages:this.settingsManager.getImageAutoResize(),blockImages:this.settingsManager.getBlockImages(),enableSkillCommands:this.settingsManager.getEnableSkillCommands(),steeringMode:this.session.steeringMode,followUpMode:this.session.followUpMode,transport:this.settingsManager.getTransport(),httpIdleTimeoutMs:this.settingsManager.getHttpIdleTimeoutMs(),thinkingLevel:this.session.thinkingLevel,availableThinkingLevels:this.session.getAvailableThinkingLevels(),currentTheme:this.settingsManager.getThemeSetting()||"dark",terminalTheme:this.themeController.getTerminalTheme(),availableThemes:ax(),hideThinkingBlock:this.hideThinkingBlock,mermaidRenderingMode:this.settingsManager.getMermaidRenderingMode(),collapseChangelog:this.settingsManager.getCollapseChangelog(),enableInstallTelemetry:this.settingsManager.getEnableInstallTelemetry(),doubleEscapeAction:this.settingsManager.getDoubleEscapeAction(),treeFilterMode:this.settingsManager.getTreeFilterMode(),showHardwareCursor:this.settingsManager.getShowHardwareCursor(),showCacheMissNotices:this.settingsManager.getShowCacheMissNotices(),defaultProjectTrust:this.settingsManager.getDefaultProjectTrust(),editorPaddingX:this.settingsManager.getEditorPaddingX(),outputPad:this.settingsManager.getOutputPad(),autocompleteMaxVisible:this.settingsManager.getAutocompleteMaxVisible(),quietStartup:this.settingsManager.getQuietStartup(),clearOnShrink:this.settingsManager.getClearOnShrink(),showTerminalProgress:this.settingsManager.getShowTerminalProgress(),tuiMode:this.ui.mode,fullscreenExitOutput:this.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:this.settingsManager.getFullscreenScrollbar(),warnings:this.settingsManager.getWarnings()},{onAutoCompactChange:i=>{this.session.setAutoCompactionEnabled(i),this.footer.setAutoCompactEnabled(i)},onShowImagesChange:i=>{this.settingsManager.setShowImages(i);for(let r of this.chatContainer.children)r instanceof qi&&r.setShowImages(i)},onImageWidthCellsChange:i=>{this.settingsManager.setImageWidthCells(i);for(let r of this.chatContainer.children)r instanceof qi&&r.setImageWidthCells(i)},onAutoResizeImagesChange:i=>{this.settingsManager.setImageAutoResize(i)},onBlockImagesChange:i=>{this.settingsManager.setBlockImages(i)},onEnableSkillCommandsChange:i=>{this.settingsManager.setEnableSkillCommands(i),this.setupAutocompleteProvider()},onSteeringModeChange:i=>{this.session.setSteeringMode(i)},onFollowUpModeChange:i=>{this.session.setFollowUpMode(i)},onTransportChange:i=>{this.settingsManager.setTransport(i),this.session.agent.transport=i},onHttpIdleTimeoutMsChange:i=>{this.settingsManager.setHttpIdleTimeoutMs(i),Nh(i),this.showStatus(`HTTP idle timeout: ${$h(i)}`)},onThinkingLevelChange:i=>{this.session.setThinkingLevel(i),this.footer.invalidate(),this.updateEditorBorderColor()},onThemeChange:i=>{this.settingsManager.setTheme(i),this.themeController.applyFromSettings()},onThemePreview:i=>this.themeController.preview(i),onHideThinkingBlockChange:i=>{this.hideThinkingBlock=i,this.settingsManager.setHideThinkingBlock(i);for(let r of this.chatContainer.children)r instanceof ji&&r.setHideThinkingBlock(i);this.chatContainer.clear(),this.rebuildChatFromMessages()},onMermaidRenderingModeChange:i=>{this.settingsManager.setMermaidRenderingMode(i),this.chatContainer.invalidate(),this.ui.requestRender()},onShowCacheMissNoticesChange:i=>{this.settingsManager.setShowCacheMissNotices(i),this.rebuildChatFromMessages()},onCollapseChangelogChange:i=>{this.settingsManager.setCollapseChangelog(i)},onEnableInstallTelemetryChange:i=>{this.settingsManager.setEnableInstallTelemetry(i)},onQuietStartupChange:i=>{this.settingsManager.setQuietStartup(i)},onDefaultProjectTrustChange:i=>{this.settingsManager.setDefaultProjectTrust(i)},onDoubleEscapeActionChange:i=>{this.settingsManager.setDoubleEscapeAction(i)},onTreeFilterModeChange:i=>{this.settingsManager.setTreeFilterMode(i)},onShowHardwareCursorChange:i=>{this.settingsManager.setShowHardwareCursor(i),this.ui.setShowHardwareCursor(i)},onEditorPaddingXChange:i=>{this.settingsManager.setEditorPaddingX(i),this.defaultEditor.setPaddingX(i),this.editor!==this.defaultEditor&&this.editor.setPaddingX!==void 0&&this.editor.setPaddingX(i)},onOutputPadChange:i=>{if(this.settingsManager.setOutputPad(i),this.outputPad=i,this.streamingComponent||this.session.isStreaming){for(let r of this.chatContainer.children)(r instanceof ji||r instanceof Rs||r instanceof bo)&&r.setOutputPad(i);this.streamingComponent&&this.streamingComponent.setOutputPad(i),this.ui.requestRender();return}this.rebuildChatFromMessages()},onAutocompleteMaxVisibleChange:i=>{this.settingsManager.setAutocompleteMaxVisible(i),this.defaultEditor.setAutocompleteMaxVisible(i),this.editor!==this.defaultEditor&&this.editor.setAutocompleteMaxVisible!==void 0&&this.editor.setAutocompleteMaxVisible(i)},onClearOnShrinkChange:i=>{this.settingsManager.setClearOnShrink(i),this.ui.setClearOnShrink(i),!i&&!this.activeStatusIndicator&&this.statusContainer.clear()},onShowTerminalProgressChange:i=>{this.settingsManager.setShowTerminalProgress(i)},onTuiModeChange:i=>{if(!this.switchTuiMode(i)){n?.getSettingsList().updateValue("tui-mode",this.ui.mode),this.showStatus("Close active overlays before changing TUI mode");return}this.settingsManager.setTuiMode(i),this.activeStatusIndicator||this.statusContainer.clear(),this.showStatus(`TUI mode: ${i}`)},onFullscreenExitOutputChange:i=>{this.settingsManager.setFullscreenExitOutput(i)},onFullscreenScrollbarChange:i=>{this.settingsManager.setFullscreenScrollbar(i),this.applyFullscreenScrollbarSetting()},onWarningsChange:i=>{this.settingsManager.setWarnings(i)},onCancel:()=>{e(),this.ui.requestRender()}}),{component:n,focus:n.getSettingsList()}})}async handleModelCommand(e){if(!e){this.showModelSelector();return}let n=await this.findExactModelMatch(e);if(n){try{await this.session.setModel(n),this.footer.invalidate(),this.updateEditorBorderColor(),this.showStatus(`Model: ${n.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(n),this.checkDaxnutsEasterEgg(n)}catch(i){this.showError(i instanceof Error?i.message:String(i))}return}this.showModelSelector(e)}async findExactModelMatch(e){let n=this.session.scopedModels.length>0?this.session.scopedModels.map(a=>a.model):[...this.session.modelRuntime.getAvailableSnapshot()],i=zu(e,n);if(i||this.session.scopedModels.length>0)return i;this.showStatus("Refreshing model catalogs\u2026");let r=new AbortController,o=!1,s=setTimeout(()=>{o=!0,r.abort()},15e3);try{let a=await this.session.modelRuntime.refresh({signal:r.signal});a.aborted&&o?this.showWarning("Model refresh timed out; searching cached models."):a.errors.size>0&&this.showWarning(`Could not refresh ${[...a.errors.keys()].join(", ")}; searching cached models.`)}catch(a){this.showWarning(o?"Model refresh timed out; searching cached models.":`Could not refresh model catalogs: ${a instanceof Error?a.message:String(a)}`)}finally{clearTimeout(s)}return zu(e,[...this.session.modelRuntime.getAvailableSnapshot()])}updateAvailableProviderCount(){let e=this.session.scopedModels.length>0?this.session.scopedModels.map(i=>i.model):this.session.modelRuntime.getAvailableSnapshot(),n=new Set(e.map(i=>i.provider));this.footerDataProvider.setAvailableProviderCount(n.size)}async maybeWarnAboutAnthropicSubscriptionAuth(e=this.session.model){if(this.settingsManager.getWarnings().anthropicExtraUsage!==!1&&!this.anthropicSubscriptionWarningShown&&!(!e||e.provider!=="anthropic"))try{if((await this.session.modelRuntime.checkAuth("anthropic"))?.type==="oauth"){this.anthropicSubscriptionWarningShown=!0,this.showWarning(eO);return}let n=(await this.session.modelRuntime.getAuth(e.provider))?.auth.apiKey;if(!sQ(n))return;this.anthropicSubscriptionWarningShown=!0,this.showWarning(eO)}catch{}}maybeSaveImplicitProjectTrustAfterReload(){let e=this.sessionManager.getCwd();if(this.autoTrustOnReloadCwd!==e||!this.settingsManager.isProjectTrusted()||!Ts(e))return!1;let n=new co(this.runtimeHost.services.agentDir);try{return n.get(e)!==null?(this.autoTrustOnReloadCwd=void 0,!1):(n.set(e,!0),this.autoTrustOnReloadCwd=void 0,!0)}catch(i){return this.showWarning(`Could not save project trust after reload: ${i instanceof Error?i.message:String(i)}`),!1}}showTrustSelector(){let e=this.sessionManager.getCwd(),n=new co(this.runtimeHost.services.agentDir),i=n.getEntry(e);this.showSelector(r=>{let o=new hp({cwd:e,savedDecision:i,projectTrusted:this.settingsManager.isProjectTrusted(),onSelect:s=>{n.setMany(s.updates),r(),this.showStatus(`Saved trust decision: ${s.trusted?"trusted":"untrusted"}. Restart sling for this to take effect.`)},onCancel:()=>{r(),this.ui.requestRender()}});return{component:o,focus:o}})}showModelSelector(e){this.showSelector(n=>{let i=new Zl(this.ui,this.session.model,this.settingsManager,this.session.modelRuntime,this.session.scopedModels,async r=>{try{await this.session.setModel(r),this.footer.invalidate(),this.updateEditorBorderColor(),n(),this.showStatus(`Model: ${r.id}`),this.maybeWarnAboutAnthropicSubscriptionAuth(r),this.checkDaxnutsEasterEgg(r)}catch(o){n(),this.showError(o instanceof Error?o.message:String(o))}},()=>{n(),this.ui.requestRender()},e);return{component:i,focus:i,dispose:()=>i.dispose()}})}showModelsSelector(){let e=[...this.session.modelRuntime.getAvailableSnapshot()],n=new Set(e.map(c=>`${c.provider}/${c.id}`)),i=this.settingsManager.getEnabledModels(),r=this.session.scopedModels,o=c=>{if(!i?.length)return null;let u=ov(i,c),p=u.scopedModels.map(d=>`${d.model.provider}/${d.model.id}`);for(let d of u.diagnostics)d.code==="no-match"&&!p.includes(d.pattern)&&p.push(d.pattern);return p},s=r.length>0?r.map(c=>`${c.model.provider}/${c.model.id}`):o(e),a=!1,l=c=>{s=c===null?null:[...c];let u=c?.some(d=>n.has(d))??!1,p=c!==null&&[...n].every(d=>c.includes(d));if(c&&u&&!p){let d=ov(c,e).scopedModels;this.session.setScopedModels(d.map(m=>({model:m.model,thinkingLevel:m.thinkingLevel})))}else this.session.setScopedModels([]);this.updateAvailableProviderCount(),this.ui.requestRender()};this.showSelector(c=>{let u=!1,p=!1,d=new AbortController,m=setTimeout(()=>{p=!0,d.abort()},15e3),g=new lp({allModels:e,enabledModelIds:s,refreshStatus:"Refreshing model catalogs\u2026"},{onChange:h=>{a=!0,l(h)},onPersist:h=>{let f=h!==null&&h.length===e.length&&h.every(v=>n.has(v)),b=h===null||f?void 0:h;this.settingsManager.setEnabledModels(b?[...b]:void 0),this.showStatus("Model selection saved to settings")},onCancel:()=>{c(),this.ui.requestRender()}});return this.session.modelRuntime.refresh({signal:d.signal}).then(h=>{u||(e=[...this.session.modelRuntime.getAvailableSnapshot()],n=new Set(e.map(f=>`${f.provider}/${f.id}`)),!a&&r.length===0?(s=o(e),g.updateModels(e,s)):g.updateModels(e),s!==null&&l(s),h.aborted&&p?g.setRefreshStatus("Model refresh timed out; showing cached models.","warning"):h.errors.size>0?g.setRefreshStatus(`Could not refresh ${[...h.errors.keys()].join(", ")}; showing cached models.`,"warning"):g.setRefreshStatus("Model catalogs refreshed.","success"),this.ui.requestRender())}).catch(h=>{u||(g.setRefreshStatus(p?"Model refresh timed out; showing cached models.":`Could not refresh model catalogs: ${h instanceof Error?h.message:String(h)}`,"warning"),this.ui.requestRender())}).finally(()=>clearTimeout(m)),{component:g,focus:g,dispose:()=>{u=!0,clearTimeout(m),d.abort()}}})}showUserMessageSelector(){let e=this.session.getUserMessagesForForking();if(e.length===0){this.showStatus("No messages to fork from");return}let n=e[e.length-1]?.entryId;this.showSelector(i=>{let r=new rc(e.map(o=>({id:o.entryId,text:o.text})),async o=>{i();try{let s=await this.runtimeHost.fork(o);if(s.cancelled){this.ui.requestRender();return}this.editor.setText(s.selectedText??""),this.showStatus("Forked to new session")}catch(s){this.showError(s instanceof Error?s.message:String(s))}},()=>{i(),this.ui.requestRender()},n);return{component:r,focus:r.getMessageList()}})}async handleCloneCommand(){let e=this.sessionManager.getLeafId();if(!e){this.showStatus("Nothing to clone yet");return}try{if((await this.runtimeHost.fork(e,{position:"at"})).cancelled){this.ui.requestRender();return}this.editor.setText(""),this.showStatus("Cloned to new session")}catch(n){this.showError(n instanceof Error?n.message:String(n))}}showTreeSelector(e){let n=this.sessionManager.getTree(),i=this.sessionManager.getLeafId(),r=this.settingsManager.getTreeFilterMode();if(n.length===0){this.showStatus("No entries in session");return}this.showSelector(o=>{let s=new ic(n,i,this.ui.terminal.rows,async a=>{if(a===this.sessionManager.getLeafId()){o(),this.showStatus("Already at this point");return}o();let l=!1,c;if(!this.settingsManager.getBranchSummarySkipPrompt())for(;;){let d=await this.showExtensionSelector("Summarize branch?",["No summary","Summarize","Summarize with custom prompt"]);if(d===void 0){this.showTreeSelector(a);return}if(l=d!=="No summary",!(d==="Summarize with custom prompt"&&(c=await this.showExtensionEditor("Custom summarization instructions"),c===void 0)))break}this.session.isStreaming&&(this.restoreQueuedMessagesToEditor(),await this.session.abort());let u=!1,p=this.defaultEditor.onEscape;l&&(this.defaultEditor.onEscape=()=>{this.session.abortBranchSummary()},this.chatContainer.addChild(new W(1)),this.showStatusIndicator(new mp(this.ui)),u=!0,this.ui.requestRender());try{let d=await this.session.navigateTree(a,{summarize:l,customInstructions:c});if(d.aborted){this.showStatus("Branch summarization cancelled"),this.showTreeSelector(a);return}if(d.cancelled){this.showStatus("Navigation cancelled");return}this.chatContainer.clear(),this.renderInitialMessages(),d.editorText&&!this.editor.getText().trim()&&this.editor.setText(d.editorText),this.showStatus("Navigated to selected point"),this.flushCompactionQueue({willRetry:!1})}catch(d){this.showError(d instanceof Error?d.message:String(d))}finally{u&&this.clearStatusIndicator("branchSummary"),this.defaultEditor.onEscape=p}},()=>{o(),this.ui.requestRender()},(a,l)=>{this.sessionManager.appendLabelChange(a,l),this.ui.requestRender()},e,r);return s.onCopy=async a=>{if(!a){this.showError("Selected entry has no text to copy");return}try{await zl(a),this.showStatus("Copied selected message to clipboard")}catch(l){this.showError(l instanceof Error?l.message:String(l))}},{component:s,focus:s}})}showSessionSelector(){this.showSelector(e=>{let n=new Cs(i=>Xn.list(this.sessionManager.getCwd(),this.sessionManager.getSessionDir(),i),i=>this.sessionManager.usesDefaultSessionDir()?Xn.listAll(i):Xn.listAll(this.sessionManager.getSessionDir(),i),async i=>{e(),await this.handleResumeSession(i)},()=>{e(),this.ui.requestRender()},()=>{this.shutdown()},()=>this.ui.requestRender(),{renameSession:async(i,r)=>{let o=(r??"").trim();if(!o)return;Xn.open(i).appendSessionInfo(o)},showRenameHint:!0,keybindings:this.keybindings},this.sessionManager.getSessionFile());return{component:n,focus:n}})}async handleResumeSession(e,n){this.clearStatusIndicator();try{let i=await this.runtimeHost.switchSession(e,{withSession:n?.withSession,projectTrustContextFactory:r=>this.createProjectTrustContext(r)});return i.cancelled||this.showStatus("Resumed session"),i}catch(i){if(i instanceof Gl){let r=await this.promptForMissingSessionCwd(i);if(!r)return this.showStatus("Resume cancelled"),{cancelled:!0};let o=await this.runtimeHost.switchSession(e,{cwdOverride:r,withSession:n?.withSession,projectTrustContextFactory:s=>this.createProjectTrustContext(s)});return o.cancelled||this.showStatus("Resumed session in current cwd"),o}return this.handleFatalRuntimeError("Failed to resume session",i)}}getLoginProviderOptions(e){let n=[];for(let i of this.session.modelRuntime.getProviders()){let r=this.session.modelRuntime.getProviderAuthStatus(i.id),o=r.configured?{type:this.session.modelRuntime.isUsingOAuth(i.id)?"oauth":"api_key",source:r.label??r.source}:void 0;(!e||e==="oauth")&&i.auth.oauth&&n.push({id:i.id,name:i.name,authType:"oauth",method:i.auth.oauth,status:o}),(!e||e==="api_key")&&i.auth.apiKey&&n.push({id:i.id,name:i.name,authType:"api_key",method:i.auth.apiKey,status:o})}return n.sort((i,r)=>i.name.localeCompare(r.name))}async getLogoutProviderOptions(){return(await this.session.modelRuntime.listCredentials({signal:AbortSignal.timeout(15e3)})).map(({providerId:e,type:n})=>({id:e,name:this.session.modelRuntime.getProvider(e)?.name??e,authType:n,status:{type:n,source:"stored credential"}})).sort((e,n)=>e.name.localeCompare(n.name))}findLoginProviderOptions(e){let n=e.trim().toLowerCase();return n?this.getLoginProviderOptions().filter(i=>i.id.toLowerCase()===n||i.name.toLowerCase()===n):[]}async handleLoginCommand(e){if(!e){this.showLoginAuthTypeSelector();return}let n=this.findLoginProviderOptions(e);if(n.length===1){await this.startProviderLogin(n[0]);return}if(n.length>1&&new Set(n.map(r=>r.id)).size===1){this.showLoginAuthTypeSelector(n);return}this.showLoginProviderSelector(void 0,e)}async startProviderLogin(e){e.authType==="oauth"?await this.showLoginDialog(e.id,e.name):e.method?.login?await this.showApiKeyLoginDialog(e.id,e.name):this.showAmbientAuthDialog(e)}showLoginAuthTypeSelector(e){let n=e?.find(c=>c.authType==="oauth"),r=(n?.method&&"loginLabel"in n.method?n.method.loginLabel:void 0)??"Sign in with an account",o="Sign in with an API key",s=e?new Set(e.map(c=>c.authType)):new Set(["oauth","api_key"]),a=[];if(s.has("oauth")&&a.push(r),s.has("api_key")&&a.push(o),a.length===0){this.showStatus("No login methods available.");return}if(e&&a.length===1){let c=e[0];c&&this.startProviderLogin(c);return}let l=e?.[0]?`Select authentication method for ${e[0].name}:`:"Select authentication method:";this.showSelector(c=>{let u=new yr(l,a,p=>{c();let d=p===r?"oauth":"api_key";if(e){let m=e.find(g=>g.authType===d);m&&this.startProviderLogin(m);return}this.showLoginProviderSelector(d)},()=>{c(),this.ui.requestRender()});return{component:u,focus:u}})}showLoginProviderSelector(e,n){let i=this.getLoginProviderOptions(e);if(i.length===0){let r=e==="oauth"?"No subscription providers available.":e==="api_key"?"No API key providers available.":"No login providers available.";this.showStatus(r);return}this.showSelector(r=>{let o=new Ms("login",i,async(s,a)=>{r();let l=i.find(c=>c.id===s&&c.authType===a);l&&await this.startProviderLogin(l)},()=>{r(),e?this.showLoginAuthTypeSelector():this.ui.requestRender()},n);return{component:o,focus:o}})}async showOAuthSelector(e){if(e==="login"){this.showLoginAuthTypeSelector();return}let n;try{n=(await this.getLogoutProviderOptions()).filter(i=>i.name==="slingshot")}catch(i){this.showError(`Could not read stored credentials: ${i instanceof Error?i.message:String(i)}`);return}if(n.length===0){this.showStatus("No stored credentials to remove. /logout only removes credentials saved by /login; environment variables and models.json config are unchanged.");return}this.showSelector(i=>{let r=new Ms(e,n,async o=>{i();let s=n.find(a=>a.id===o);if(s)try{await this.session.modelRuntime.logout(s.id,{signal:AbortSignal.timeout(15e3)}),await this.updateAvailableProviderCount();let a=s.authType==="oauth"?`Logged out of ${s.name}`:`Removed stored API key for ${s.name}. Environment variables and models.json config are unchanged.`;this.showStatus(a)}catch(a){let l=a instanceof Error?a.message:String(a);this.showError(a instanceof ys?`Credentials removed for ${s.name}, but local model state could not be synchronized: ${l}`:`Logout failed: ${l}`)}},()=>{i(),this.ui.requestRender()});return{component:r,focus:r}})}async completeProviderAuthentication(e,n,i,r){let o=i==="oauth"?`Logged in to ${n}`:`Saved API key for ${n}`,s,a;if(aQ(r)){let p=this.session.modelRuntime.getAvailableSnapshot().filter(d=>d.provider===e);if(!uQ(e))a=`${o}, but no default model is configured for provider "${e}". Use /model to select a model.`;else if(p.length===0)a=`${o}, but no models are available for that provider. Use /model to select a model.`;else{let d=rv[e];if(s=p.find(m=>m.id===d),!s)a=`${o}, but its default model "${d}" is not available. Use /model to select a model.`;else try{await this.session.setModel(s)}catch(m){s=void 0;let g=m instanceof Error?m.message:String(m);a=`${o}, but selecting its default model failed: ${g}. Use /model to select a model.`}}}await this.updateAvailableProviderCount(),this.footer.invalidate(),this.updateEditorBorderColor(),s?(this.showStatus(`${o}. Selected ${s.id}. Credentials saved to ${S0()}`),this.maybeWarnAboutAnthropicSubscriptionAuth(s),this.checkDaxnutsEasterEgg(s)):(this.showStatus(`${o}. Credentials saved to ${S0()}`),a?this.showError(a):this.maybeWarnAboutAnthropicSubscriptionAuth());let l=new AbortController,c=setTimeout(()=>l.abort(),15e3);this.session.modelRuntime.refresh({providers:[e],signal:l.signal}).then(u=>{u.aborted?this.showWarning(`${o}, but its model catalog refresh timed out; using cached models.`):u.errors.size>0&&this.showWarning(`${o}, but its model catalog could not be refreshed; using cached models.`),this.updateAvailableProviderCount(),this.footer.invalidate(),this.ui.requestRender()}).catch(u=>{this.showWarning(`${o}, but its model catalog could not be refreshed: ${u instanceof Error?u.message:String(u)}`)}).finally(()=>clearTimeout(c))}showAmbientAuthDialog(e){let n=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()},i=new fo(this.ui,e.id,()=>n(),e.name,`${e.name} setup`);i.showInfo(`${e.method?.name??"Authentication"} is configured outside pi.`,[],!0),this.editorContainer.clear(),this.editorContainer.addChild(i),this.ui.setFocus(i),this.ui.requestRender()}async showApiKeyLoginDialog(e,n){let i=this.session.model,r=new fo(this.ui,e,(s,a)=>{},n);e==="amazon-bedrock"&&r.showDetails([x.fg("text","You can also use an AWS profile, IAM keys, or role-based credentials."),x.fg("muted","See:"),x.fg("accent",` ${st.join(Kc(),"providers.md")}`)]),this.editorContainer.clear(),this.editorContainer.addChild(r),this.ui.setFocus(r),this.ui.requestRender();let o=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(r,e,"api_key"),o(),await this.completeProviderAuthentication(e,n,"api_key",i)}catch(s){o();let a=s instanceof Error?s.message:String(s);s instanceof ys?this.showError(`Saved API key for ${n}, but local model state could not be synchronized: ${a}`):a!=="Login cancelled"&&this.showError(`Failed to save API key for ${n}: ${a}`)}}showAuthSelect(e,n){return new Promise((i,r)=>{let o=()=>{this.editorContainer.clear(),this.editorContainer.addChild(e),this.ui.setFocus(e),this.ui.requestRender()},s=n.options.map(l=>l.label),a=new yr(n.message,s,l=>{o();let c=n.options.find(u=>u.label===l)?.id;c?i(c):r(new Error("Login cancelled"))},()=>{o(),r(new Error("Login cancelled"))});this.editorContainer.clear(),this.editorContainer.addChild(a),this.ui.setFocus(a),this.ui.requestRender()})}async showAuthPrompt(e,n){let i;if(n.type==="select"?i=this.showAuthSelect(e,n):n.type==="manual_code"?i=e.showManualInput(n.message):i=e.showPrompt(n.message,n.placeholder),!n.signal)return i;if(n.signal.aborted)throw new Error("Login cancelled");let r=n.signal,o,s=new Promise((a,l)=>{o=()=>l(new Error("Login cancelled")),r.addEventListener("abort",o,{once:!0})});try{return await Promise.race([i,s])}finally{o&&r.removeEventListener("abort",o)}}notifyAuthDialog(e,n){n.type==="auth_url"?e.showAuth(n.url,n.instructions):n.type==="device_code"?(e.showDeviceCode(n),e.showWaiting("Waiting for authentication...")):n.type==="info"?e.showInfo(n.message,n.links):e.showProgress(n.message)}async loginProvider(e,n,i){await this.session.modelRuntime.login(n,i,{signal:e.signal,prompt:r=>this.showAuthPrompt(e,r),notify:r=>this.notifyAuthDialog(e,r)})}async showLoginDialog(e,n){let i=this.session.model,r=new fo(this.ui,e,(s,a)=>{},n);this.editorContainer.clear(),this.editorContainer.addChild(r),this.ui.setFocus(r),this.ui.requestRender();let o=()=>{this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor),this.ui.requestRender()};try{await this.loginProvider(r,e,"oauth"),o(),await this.completeProviderAuthentication(e,n,"oauth",i)}catch(s){o();let a=s instanceof Error?s.message:String(s);s instanceof ys?this.showError(`Logged in to ${n}, but local model state could not be synchronized: ${a}`):a!=="Login cancelled"&&this.showError(`Failed to login to ${n}: ${a}`)}}async handleReloadCommand(){if(this.session.isStreaming){this.showWarning("Wait for the current response to finish before reloading.");return}if(this.session.isCompacting){this.showWarning("Wait for compaction to finish before reloading.");return}this.resetExtensionUI();let e=new K,n=l=>x.fg("border",l);e.addChild(new V(n)),e.addChild(new W(1)),e.addChild(new E(x.fg("muted","Reloading keybindings, extensions, skills, prompts, themes, and context files..."),1,0)),e.addChild(new W(1)),e.addChild(new V(n));let i=this.editor;this.editorContainer.clear(),this.editorContainer.addChild(e),this.ui.setFocus(e),this.ui.requestRender(!0),await new Promise(l=>process.nextTick(l));let r=l=>{this.editorContainer.clear(),this.editorContainer.addChild(l),this.ui.setFocus(l),this.ui.requestRender()},o=!1,s=!1,a=()=>{o||(this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),this.rebuildChatFromMessages(),o=!0)};try{await this.session.reload({beforeSessionStart:a}),a(),this.keybindings.reload();let l=this.customHeader??this.builtInHeader;gp(l)&&l.setExpanded(this.toolOutputExpanded),Mu(this.session.resourceLoader.getThemes().themes),await this.themeController.applyFromSettings(),this.applyRuntimeSettings(),this.setupAutocompleteProvider();let c=this.session.extensionRunner;this.setupExtensionShortcuts(c),this.showLoadedResources({force:!1,showDiagnosticsWhenQuiet:!0});let u=this.maybeSaveImplicitProjectTrustAfterReload(),p=this.session.modelRuntime.getError();p&&this.showError(`models.json error: ${p}`),this.showStatus(u?"Reloaded keybindings, extensions, skills, prompts, themes, and context files; saved project trust":"Reloaded keybindings, extensions, skills, prompts, themes, and context files"),r(this.editor),s=!0}catch(l){s||r(i),this.showError(`Reload failed: ${l instanceof Error?l.message:String(l)}`)}}async handleExportCommand(e){let n=this.getPathCommandArgument(e,"/export");try{if(n?.endsWith(".jsonl")){let i=this.session.exportToJsonl(n);this.showStatus(`Session exported to: ${i}`)}else{let i=await this.session.exportToHtml(n);this.showStatus(`Session exported to: ${i}`)}}catch(i){this.showError(`Failed to export session: ${i instanceof Error?i.message:"Unknown error"}`)}}getPathCommandArgument(e,n){if(e===n||!e.startsWith(`${n} `))return;let i=e.slice(n.length+1).trimStart();if(!i)return;let r=i[0];if(r==='"'||r==="'"){let s=i.indexOf(r,1);return s<0?void 0:i.slice(1,s)}let o=i.search(/\s/);return o<0?i:i.slice(0,o)}async handleImportCommand(e){let n=this.getPathCommandArgument(e,"/import");if(!n){this.showError("Usage: /import <path.jsonl>");return}if(!await this.showExtensionConfirm("Import session",`Replace current session with ${n}?`)){this.showStatus("Import cancelled");return}try{if(this.clearStatusIndicator(),(await this.runtimeHost.importFromJsonl(n)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${n}`)}catch(r){if(r instanceof Gl){let o=await this.promptForMissingSessionCwd(r);if(!o){this.showStatus("Import cancelled");return}if((await this.runtimeHost.importFromJsonl(n,o)).cancelled){this.showStatus("Import cancelled");return}this.showStatus(`Session imported from: ${n}`);return}if(r instanceof Bh){this.showError(`Failed to import session: ${r.message}`);return}await this.handleFatalRuntimeError("Failed to import session",r)}}async handleShareCommand(){try{if(nQ("gh",["auth","status"],{encoding:"utf-8"}).status!==0){this.showError("GitHub CLI is not logged in. Run 'gh auth login' first.");return}}catch{this.showError("GitHub CLI (gh) is not installed. Install it from https://cli.github.com/");return}let e=st.join(fp.tmpdir(),"session.html");try{await this.session.exportToHtml(e)}catch(o){this.showError(`Failed to export session: ${o instanceof Error?o.message:"Unknown error"}`);return}let n=new ho(this.ui,x,"Creating gist...");this.editorContainer.clear(),this.editorContainer.addChild(n),this.ui.setFocus(n),this.ui.requestRender();let i=()=>{n.dispose(),this.editorContainer.clear(),this.editorContainer.addChild(this.editor),this.ui.setFocus(this.editor);try{Tr.unlinkSync(e)}catch{}},r=null;n.onAbort=()=>{r?.kill(),i(),this.showStatus("Share cancelled")};try{let o=await new Promise(c=>{r=Z_("gh",["gist","create","--public=false",e]);let u="",p="";r.stdout?.on("data",d=>{u+=d.toString()}),r.stderr?.on("data",d=>{p+=d.toString()}),r.on("close",d=>c({stdout:u,stderr:p,code:d}))});if(n.signal.aborted)return;if(i(),o.code!==0){let c=o.stderr?.trim()||"Unknown error";this.showError(`Failed to create gist: ${c}`);return}let s=o.stdout?.trim(),a=s?.split("/").pop();if(!a){this.showError("Failed to parse gist ID from gh output");return}let l=qk(a);this.showStatus(`Share URL: ${l}
|
|
314
314
|
Gist: ${s}`)}catch(o){n.signal.aborted||(i(),this.showError(`Failed to create gist: ${o instanceof Error?o.message:"Unknown error"}`))}}async handleCopyCommand(e={}){let n=this.session.getLastAssistantText();if(!n){this.showError("No agent messages to copy yet.");return}try{await zl(n),e.flashConfirmation&&this.ui instanceof fl?this.ui.flash("Copied!"):this.showStatus("Copied last agent message to clipboard")}catch(i){this.showError(i instanceof Error?i.message:String(i))}}handleNameCommand(e){let n=e.replace(/^\/name\s*/,"").trim();if(!n){let r=this.sessionManager.getSessionName();r?(this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new E(x.fg("dim",`Session name: ${r}`),1,0))):this.showWarning("Usage: /name <name>"),this.ui.requestRender();return}this.session.setSessionName(n);let i=this.sessionManager.getSessionName();i!==n&&this.showWarning(`Session name was normalized from ${JSON.stringify(n)} to ${JSON.stringify(i)}`),this.chatContainer.addChild(new W(1)),this.chatContainer.addChild(new E(x.fg("dim",`Session name set: ${i??n}`),1,0)),this.ui.requestRender()}handleSessionCommand(){let e=this.session.getSessionStats(),n=this.sessionManager.getSessionName(),i=this.sessionManager.getEntries(),r=x_(i,this.session.modelRuntime),o=CE(i),s=`${x.bold("Session Info")}
|
|
315
315
|
|
|
316
316
|
`;n&&(s+=`${x.fg("dim","Name:")} ${n}
|
|
@@ -401,7 +401,7 @@ Log file: ${kr}
|
|
|
401
401
|
`;xo.appendFileSync(kr,n)}catch{}}function gt(t,e){if(!(!kr||!xo||!xp))try{let i=`[${new Date().toISOString()}] ${t}:
|
|
402
402
|
${JSON.stringify(e,null,2)}
|
|
403
403
|
|
|
404
|
-
`;xo.appendFileSync(kr,i)}catch{}}var vo=null;function cO(t){if(!t)return;let e=t.trim();if(e)return e.replace(/\/+$/,"")}var oe=class t{static{this.BASE_URL="base_url"}static{this.ANALYTICS_DOMAIN="analytics_domain"}static{this.CLIENT_ID="client_id"}static{this.PROJECT_ID="project_id"}static{this.WORKSPACE_ID="workspace_id"}static{this.PROJECT_NAME="project_name"}static{this.WORKSPACE_NAME="workspace_name"}static{this.defaultValues={[t.BASE_URL]:"https://sapientaiproducts.com",[t.ANALYTICS_DOMAIN]:"https://slingshot.sapientaiproducts.com",[t.CLIENT_ID]:"b97fbef7-cad9-4e56-9850-39e86c8fdf61",[t.PROJECT_ID]:"fa8121c4-e2fc-48f1-9478-8949c04e13cc",[t.WORKSPACE_ID]:"6e5756eb-d7e2-4d80-ad07-9d7a51600d85"}}static{this.LOGIN_PATH="/web/v1/studio-auth/login"}static{this.EXCHANGE_PATH="/api/v1/studio-auth/auth/desktop/exchange"}static{this.REFRESH_PATH="/api/v3/auth/refreshtoken"}static{this.API_BASE_PATH="/api/v1/llm"}static{this.SAGE_EVENTS_PATH="/api/v1/ai-portal/sage_events"}static{this.APP_TOKEN_PATH="/api/v3/auth/app-token"}static{this.CONFIG_SERVICE_PATH="/api/v2/configservice/client"}static{this.SLINGSHOT_RAG_MCP="/api/v1/ai-prompt-lib/mcp/"}static{this.SAPI="/save/api/v1"}static{this.REFRESH_CLIENT_NAME="machine"}static{this.SLINGSHOT_APP_TOKEN_ENV="SLINGSHOT_APP_TOKEN_HEADER"}static{this.APP_TOKEN_REFRESH_BUFFER_MS=60*1e3}static{this.TOKEN_EXPIRY_BUFFER_MS=300*1e3}static{this.CLIENT_NAME="desktop"}static defaults(e){return this.defaultValues[e]}static getLocalSettingsPath(){return ng.resolve(process.cwd(),".sling","sling.settings.json")}static getGlobalSettingsPath(){return ng.resolve(Ee(),"sling.settings.json")}static getSettingsPath(e){if(e==="local")return this.getLocalSettingsPath();if(e==="global")return this.getGlobalSettingsPath();let n=this.getLocalSettingsPath();return wi.existsSync(n)?n:this.getGlobalSettingsPath()}static getSettings(){if(!vo){let i=this.getSettingsPath();try{if(wi.existsSync(i)){let r=wi.readFileSync(i,"utf-8"),o=JSON.parse(r)||{};vo={...this.defaultValues,...o}}else{let r=ng.dirname(i);wi.existsSync(r)||wi.mkdirSync(r,{recursive:!0}),wi.writeFileSync(i,JSON.stringify(this.defaultValues,null,2),"utf-8"),vo={...this.defaultValues}}}catch(r){gt("Error reading/writing sling.settings.json: ",r),vo={...this.defaultValues}}}let e=cO(process.env.SLINGSHOT_API_DOMAIN),n=cO(process.env.SLINGSHOT_ANALYTICS_DOMAIN);return{...vo,[t.BASE_URL]:e||vo[t.BASE_URL],[t.ANALYTICS_DOMAIN]:n||vo[t.ANALYTICS_DOMAIN]}}static updateSettings(e,n){let i=n?.scope??"global",r=this.getSettingsPath(i);try{let o={};if(wi.existsSync(r)){let l=wi.readFileSync(r,"utf-8");o=JSON.parse(l)||{}}let s={...this.defaultValues,...o,...e},a=ng.dirname(r);wi.existsSync(a)||wi.mkdirSync(a,{recursive:!0}),wi.writeFileSync(r,JSON.stringify(s,null,2),"utf-8"),vo=null}catch(o){gt("Error updating sling.settings.json: ",o)}}static getLoginUrl(e){let n=this.getSettings(),i=new URLSearchParams({client:this.CLIENT_NAME,port:String(e.port),localState:e.localState});return e.clientId&&i.set("clientId",e.clientId),`${n[t.BASE_URL]}${this.LOGIN_PATH}?${i.toString()}`}static getExchangeUrl(){return`${this.getSettings()[t.BASE_URL]}${this.EXCHANGE_PATH}`}static getRefreshUrl(){let e=this.getSettings(),n=new URLSearchParams({client:this.REFRESH_CLIENT_NAME});return`${e[t.BASE_URL]}${this.REFRESH_PATH}?${n.toString()}`}static getApiBaseUrl(){return`${this.getSettings()[t.BASE_URL]}${this.API_BASE_PATH}`}static getSageEventsUrl(){return`${this.getSettings()[t.ANALYTICS_DOMAIN]}${this.SAGE_EVENTS_PATH}`}static getSlingshotRAGMCPUrl(){return`${this.getSettings()[t.ANALYTICS_DOMAIN]}${this.SLINGSHOT_RAG_MCP}`}static getTokenExpiryBuffer(){return this.TOKEN_EXPIRY_BUFFER_MS}static getDefaultProjectId(){let e=this.getSettings();return process.env.SLINGSHOT_PROJECT_ID||e[t.PROJECT_ID]}static getDefaultWorkspaceId(){let e=this.getSettings();return process.env.SLINGSHOT_WORKSPACE_ID||e[t.WORKSPACE_ID]}static getDefaultClientId(){let e=this.getSettings();return process.env.CLIENT_ID||e[t.CLIENT_ID]}static getUserActivityUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users/activity`}static getUserUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users`}static getModelsUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/ai/models`}static getAppTokenUrl(){return`${this.getSettings()[t.BASE_URL]}${this.APP_TOKEN_PATH}`}static getConfigServiceUrl(e){let n=this.getSettings(),i=this.getDefaultClientId(),r=new URLSearchParams({keys:e});return`${n[t.BASE_URL]}${this.CONFIG_SERVICE_PATH}/${i}?${r.toString()}`}static getAppTokenRefreshBuffer(){return this.APP_TOKEN_REFRESH_BUFFER_MS}};function yp(t){try{let e=t.split(".");if(e.length!==3)return 0;let n=JSON.parse(atob(e[1]));return n.exp?n.exp*1e3:0}catch{return 0}}function uO(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}var Zv="Xq7Wm2zR9pLkVbN4cD8fH3jT6yG1sA5",EQ=BigInt(Zv.length);function _Q(t){if(t.length===0)return"";let e=0n;for(let i of t){let r=Zv.indexOf(i);if(r===-1)throw new Error(`Cannot decode app_key: character "${i}" is not in the expected alphabet`);e=e*EQ+BigInt(r)}let n=[];for(;e>0n;)n.unshift(Number(e&0xffn)),e>>=8n;for(let i of t)if(i===Zv[0])n.unshift(0);else break;return new TextDecoder().decode(new Uint8Array(n))}var ey=new Map,ig=new Map;async function OQ(t,e){let n=oe.getConfigServiceUrl(t);Ne(`sling-config: fetching ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e}`}})}catch(s){let a=s instanceof Error?s.message:String(s);throw new Error(`Cannot reach config service: ${a}`)}if(!i.ok){let s=`${i.status} ${i.statusText}`;try{let a=await i.json();a.message?s=String(a.message):a.error&&(s=String(a.error))}catch{}throw new Error(`Config service request failed: ${s}`)}let o=(await i.json())?.data?.config;if(!o||typeof o!="object")throw new Error("Config service response missing data.config");return o}async function pO(t,e){let n=ey.get(t);if(n)return n;let i=ig.get(t);if(i)return i;if(!e)throw new Error("Cannot reach config service: no Slingshot user token provided");let r=OQ(t,e).then(o=>(ey.set(t,o),o)).finally(()=>{ig.delete(t)});return ig.set(t,r),r}var oc=class{static async getSlingcliConfig(e){let n=await pO("slingcli",e),i=n.slingcli;if(!i||typeof i.app_id!="string"||typeof i.app_key!="string"||!i.app_id||!i.app_key)throw gt("sling-config: missing slingcli block",n),new Error("Config service did not return slingcli.app_id / slingcli.app_key for this client");return{app_id:i.app_id,app_key:_Q(i.app_key)}}static async getRemoteConfig(e,n){return pO(e,n)}static clearCache(){ey.clear(),ig=new Map}};import dO from"node:path";import yo from"node:fs";var LQ="sling.app-creds.json";function ty(){return dO.resolve(Ee(),LQ)}function mO(){let t=ty();if(!yo.existsSync(t))return null;try{let e=yo.readFileSync(t,"utf-8"),n=JSON.parse(e);return typeof n.app_id!="string"||typeof n.app_key!="string"||!n.app_id||!n.app_key?(gt("app-creds-store: invalid creds file, ignoring",n),null):{app_id:n.app_id,app_key:n.app_key}}catch(e){return gt("app-creds-store: failed to read creds file",e),null}}function ny(t){let e=ty(),n=dO.dirname(e);try{yo.existsSync(n)||yo.mkdirSync(n,{recursive:!0});let i={...t,savedAt:Date.now()};yo.writeFileSync(e,JSON.stringify(i,null,2),{encoding:"utf-8",mode:384});try{yo.chmodSync(e,384)}catch{}Ne(`app-creds-store: persisted to ${e}`)}catch(i){gt("app-creds-store: failed to persist creds",i)}}function hO(){let t=ty();try{yo.existsSync(t)&&(yo.unlinkSync(t),Ne(`app-creds-store: cleared ${t}`))}catch(e){gt("app-creds-store: failed to clear creds file",e)}}var og=class extends Error{constructor(n,i){super(i);this.status=n;this.name="AppTokenHttpError"}},wp=null,Sp=null,rg=null,sc=null;function gO(t){process.env[oe.SLINGSHOT_APP_TOKEN_ENV]=`Bearer ${t}`}function WQ(t){sc&&(clearTimeout(sc),sc=null);let e=t.expiresAt-Date.now();e<=0||(sc=setTimeout(()=>{sc=null,ni().catch(n=>{gt("app-token: scheduled refresh failed",n)})},e),sc.unref?.())}async function fO(t){let e=Buffer.from(`${t.app_id}:${t.app_key}`).toString("base64"),n=oe.getAppTokenUrl();Ne(`app-token: minting from ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Basic ${e}`}})}catch(a){let l=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach app-token service: ${l}`)}if(!i.ok){let a=`${i.status} ${i.statusText}`;try{let l=await i.text()||"";l&&(a=l)}catch{}throw new og(i.status,`App token request failed: ${a}`)}let r=await i.json();if(!r.app_token||typeof r.expires_in!="number")throw new Error("App token response missing app_token or expires_in");let o=oe.getAppTokenRefreshBuffer(),s=Date.now()+r.expires_in*1e3-o;return Ne(`app-token: minted, expires at ${new Date(s).toISOString()}`),{token:r.app_token,expiresAt:s}}async function FQ(){let t=mO();if(t)return{creds:t,fromDisk:!0};if(!Sp)throw new Error("Cannot mint app token: no on-disk app credentials and no Slingshot user token available (please /login slingshot first)");let e=await oc.getSlingcliConfig(Sp);return ny(e),{creds:e,fromDisk:!1}}async function DQ(){let{creds:t,fromDisk:e}=await FQ();try{return await fO(t)}catch(n){let i=n instanceof og&&(n.status===401||n.status===403);if(!e||!i)throw n;if(gt("app-token: disk creds rejected (likely rotated), refetching from config service",{status:n.status}),hO(),!Sp)throw new Error("Cannot rotate app credentials: on-disk creds rejected and no Slingshot user token available (please /login slingshot)");let r=await oc.getSlingcliConfig(Sp);return ny(r),await fO(r)}}async function ni(t){if(t&&(Sp=t),wp&&wp.expiresAt>Date.now())return gO(wp.token),wp.token;if(rg)return(await rg).token;let e=DQ().then(i=>(wp=i,gO(i.token),WQ(i),i)).finally(()=>{rg=null});return rg=e,(await e).token}var Tp=null,iy=null;typeof process<"u"&&process.versions?.node&&(iy=import("node:http").then(t=>{Tp=t.createServer}));async function UQ(){if(Tp||(iy&&await iy,Tp))return Tp;throw new Error("Slingshot OAuth requires Node.js")}async function ry(t){let e=await UQ(),n,i,r,o=!1,s=new Promise((u,p)=>{i=u,r=p}),a=u=>{if(!o){o=!0;try{n.close()}catch{}u()}};n=e((u,p)=>{let d=new URL(u.url||"","http://127.0.0.1"),m=d.searchParams.get("code"),g=d.searchParams.get("state"),h=d.searchParams.get("clientId"),f=d.searchParams.get("error"),b=d.searchParams.get("error_description");if(f){p.writeHead(400,{"Content-Type":"text/html"}),p.end(`<html><body><h1>Login Failed</h1><p>${b||f}</p><p>You can close this window.</p></body></html>`),a(()=>r(new Error(`Login failed: ${b||f}`)));return}if(!m||!g){p.writeHead(400,{"Content-Type":"text/html"}),p.end("<html><body><h1>Login Failed</h1><p>Missing code or state in callback.</p><p>You can close this window.</p></body></html>"),a(()=>r(new Error("Missing code or state in callback")));return}p.writeHead(200,{"Content-Type":"text/html"}),p.end("<html><body><h1>Login Successful</h1><p>You can close this window and return to your terminal.</p><script>setTimeout(()=>window.close(),3000)</script></body></html>"),a(()=>i({code:m,state:g,clientId:h||""}))}),n.on("error",u=>{a(()=>r(u))});let l=setTimeout(()=>{a(()=>r(new Error("Login timeout - no callback received within 5 minutes")))},300*1e3);return n.on("close",()=>clearTimeout(l)),t&&t.addEventListener("abort",()=>{a(()=>r(new Error("Login cancelled")))}),{port:await new Promise((u,p)=>{n.once("error",p),n.listen(0,"127.0.0.1",()=>{let d=n.address();d&&typeof d=="object"?u(d.port):p(new Error("Failed to obtain loopback server port"))})}),result:s}}async function oy(t,e){if(!t)throw new Error("Missing exchange code");if(!e)throw new Error("Missing clientId for exchange");let n=oe.getExchangeUrl(),i;try{i=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",accept:"application/json"},body:JSON.stringify({code:t,clientId:e})})}catch(o){let s=o instanceof Error?o.message:String(o);throw new Error(`Cannot reach Studio Auth: ${s}`)}if(!i.ok){let o,s=`${i.status} ${i.statusText}`;try{let a=await i.json();o=a.error?.code,a.error?.message?s=a.error.message:a.message?s=a.message:o&&(s=o)}catch{}throw o==="INVALID_CALLBACK"?new Error("Login failed: exchange code is expired, already used, or bound to a different tenant. Please log in again."):new Error(`Code exchange failed: ${s}`)}let r=await i.json();if(!r.accessToken||!r.refreshToken)throw new Error("Exchange response missing accessToken or refreshToken");return r}function NQ(){return $Q(16).toString("hex")}function BQ(t){let e=new URL(t),n=e.searchParams.get("code"),i=e.searchParams.get("state"),r=e.searchParams.get("clientId");if(!n||!i)throw new Error("Pasted URL is missing code or state");return{code:n,state:i,clientId:r||""}}async function sy(t){let e=process.env.SLINGSHOT_TOKEN;if(e){let u=yp(e);return Ne("Using Slingshot token from SLINGSHOT_TOKEN environment variable"),await ni(e),{refresh:"",access:e,expires:u>0?u-oe.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:oe.getDefaultProjectId(),workspaceId:oe.getDefaultWorkspaceId()}}let{port:n,result:i}=await ry(t.signal),r=NQ(),o=oe.getDefaultClientId(),s=oe.getLoginUrl({port:n,localState:r,clientId:o||void 0});t.onAuth({url:s});let a;if(t.onManualCodeInput){let u=t.onManualCodeInput().then(BQ);a=await Promise.race([i,u])}else a=await i;if(a.state!==r)throw new Error("CSRF check failed - state does not match localState");if(!a.clientId)throw new Error("Login callback did not include clientId");let l=await oy(a.code,a.clientId),c=yp(l.accessToken);return await ni(l.accessToken),{refresh:l.refreshToken,access:l.accessToken,expires:c>0?c-oe.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:oe.getDefaultProjectId(),workspaceId:oe.getDefaultWorkspaceId()}}import{randomUUID as jQ}from"node:crypto";async function ay(t){if(!t.refresh)throw new Error("No refresh token available. Please login again.");let e;try{e=await ni()}catch(a){throw gt("auth/refresh: app token unavailable for refresh call",a),new Error(`Cannot refresh Slingshot token: app token unavailable (${a instanceof Error?a.message:String(a)}). Please /login slingshot.`)}let n=jQ(),i={accept:"application/json",rt:t.refresh,"trace-id":n,Authorization:`Bearer ${e}`},r;try{let a=oe.getRefreshUrl();r=await fetch(a,{headers:i})}catch(a){let l=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach Slingshot server: ${l}`)}if(!r.ok){let a=`${r.status} ${r.statusText}`;try{let l=await r.json();l.message?a=String(l.message):l.error&&(a=String(l.error))}catch{}throw new Error(`Token refresh failed: ${a}`)}let o=await r.json();if(!o.accessToken)throw new Error("No access token in refresh response");let s=yp(o.accessToken);try{await ni(o.accessToken)}catch(a){throw gt("auth/refresh: app token refresh failed",a),a}return{refresh:o.refreshToken||t.refresh,access:o.accessToken,expires:s>0?s-oe.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:t.projectId,workspaceId:t.workspaceId}}var sg=[{id:"gpt-5.4-nano",name:"GPT-5.4 nano",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:.2,output:1.25,cacheRead:.02,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-4.1",name:"GPT-4.1",baseUrl:"",reasoning:!1,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:1047576,maxTokens:32768,provider:"slingshot",api:"openai-completions"},{id:"gpt-5",name:"GPT-5",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.125,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5-mini",name:"GPT-5 Mini",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:.25,output:2,cacheRead:.025,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5-nano",name:"GPT-5 Nano",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:.05,output:.4,cacheRead:.005,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5.1",name:"GPT-5.1",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.13,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5.2",name:"GPT-5.2",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5.4-mini",name:"GPT-5.4 mini",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:.75,output:4.5,cacheRead:.075,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.4",name:"GPT-5.4",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:2.5,output:15,cacheRead:.25,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.5",name:"GPT-5.5",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:5,output:30,cacheRead:.5,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.6-luna",name:"GPT-5.6 Luna",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:.96,output:5.76,cacheRead:.096,cacheWrite:0},contextWindow:105e4,maxTokens:5e5,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.6-terra",name:"GPT-5.6 Terra",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:2.4,output:14.4,cacheRead:.24,cacheWrite:0},contextWindow:105e4,maxTokens:5e5,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.6-sol",name:"GPT-5.6 Sol",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:4.8,output:28.8,cacheRead:.48,cacheWrite:0},contextWindow:105e4,maxTokens:5e5,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.3-codex",name:"GPT-5.3 Codex",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"claude-opus-4@20250514",name:"Claude Opus 4",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:15,output:75,cacheRead:1.5,cacheWrite:18.75},contextWindow:2e5,maxTokens:32e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4@20250514",name:"Claude Sonnet 4",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-5@20250929",name:"Claude Sonnet 4.5",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:1e6,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-opus-4-6",name:"Claude Opus 4.6",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:5,output:25,cacheRead:.5,cacheWrite:6.25},contextWindow:1e6,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-5",name:"Claude Sonnet 5",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:1e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"Qwen/Qwen3.6-27B-FP8",name:"Qwen 3.6 27B FP8",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.2,output:3.6,cacheRead:.3,cacheWrite:3.75},contextWindow:64e3,maxTokens:56e3,provider:"slingshot",api:"openai-completions"},{id:"o3",name:"O3",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o3-mini",name:"o3-mini",baseUrl:"",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.55,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o4-mini",name:"o4-mini",baseUrl:"",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.28,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"gemini-3.1-flash-lite",name:"Gemini 3.1 Flash Lite",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:.44,output:1.32,cacheRead:.075,cacheWrite:0},contextWindow:1e6,maxTokens:5e5,provider:"slingshot",api:"openai-completions"},{id:"gemini-3.1-pro-preview",name:"Gemini 3.1 Pro Preview",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.76,output:10.56,cacheRead:.075,cacheWrite:0},contextWindow:1e6,maxTokens:5e5,provider:"slingshot",api:"openai-completions"}];var ag=t=>Math.round((t??0)*1e3*1e6)/1e6,qQ=32768,GQ=new Map(sg.map(t=>[t.id,t.maxTokens]));async function bO(t,e){let n=await fetch(t,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json"}});if(!n.ok)throw new Error(`Slingshot models fetch failed: ${n.status}`);let i=await n.json();return KQ(Array.isArray(i)?i:i?.data??[])}function KQ(t){return t.filter(e=>e.model_type==="chat").map(e=>{let n=e.metadata??{},i=n.context_length??0,r=(n.supported_modalities??["text"]).filter(o=>o==="text"||o==="image");return{id:e.id,name:n.name||e.id,baseUrl:"",reasoning:!!n.reasoning,input:r,cost:{input:ag(e.inputCostPer1KTokens),output:ag(e.outputCostPer1KTokens),cacheRead:ag(e.cacheCostPer1KTokens?.read),cacheWrite:ag(e.cacheCostPer1KTokens?.write)},contextWindow:i,maxTokens:Math.min(i,GQ.get(e.id)??qQ),provider:"slingshot",api:e.supported_apis?.includes("responses")?"openai-responses":"openai-completions"}}).sort((e,n)=>e.id.localeCompare(n.id))}import xO from"node:fs";function vO(t,e,n){try{xO.writeFileSync(t,JSON.stringify({baseUrl:e,fetchedAt:new Date().toISOString(),models:n}))}catch{}}function yO(t,e){try{let n=JSON.parse(xO.readFileSync(t,"utf-8"));return n?.baseUrl!==e||!Array.isArray(n.models)||n.models.length===0?null:n.models}catch{return null}}var lg={name:"slingshot.cli",private:!0,type:"module",workspaces:["packages/*","packages/web-ui/example","packages/coding-agent/examples/extensions/with-deps","packages/coding-agent/examples/extensions/custom-provider-anthropic","packages/coding-agent/examples/extensions/custom-provider-gitlab-duo"],scripts:{clean:"npm run clean --workspaces",build:"cd packages/tui && npm run build && cd ../ai && npm run build && cd ../agent && npm run build && cd ../storage/sqlite-node && npm run build && cd ../../coding-agent && npm run build && cd ../server && npm run build","build:offline":"cd packages/tui && npm run build && cd ../ai && npm run build:offline && cd ../agent && npm run build && cd ../storage/sqlite-node && npm run build && cd ../../coding-agent && npm run build && cd ../server && npm run build",dev:'concurrently --names "ai,agent,coding-agent,web-ui,tui" --prefix-colors "cyan,yellow,red,white,green,magenta" "cd packages/ai && npm run dev" "cd packages/agent && npm run dev" "cd packages/coding-agent && npm run dev" "cd packages/server && npm run dev" "cd packages/tui && npm run dev"',"dev:tsc":'concurrently --names "ai,web-ui" --prefix-colors "cyan,green" "cd packages/ai && npm run dev:tsc" "cd packages/web-ui && npm run dev:tsc"',check:"","check:browser-smoke":"","test:models":"node scripts/test-models.mjs","profile:tui":"node scripts/profile-coding-agent-node.mjs --mode tui","profile:rpc":"node scripts/profile-coding-agent-node.mjs --mode rpc",test:"npm run test --workspaces --if-present","version:patch":"npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:minor":"npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:major":"npm version major -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:set":"npm version -ws",prepublishOnly:"npm run clean && npm run build && npm run check",publish:"npm run prepublishOnly && npm publish -ws --access public","publish:dry":"npm run prepublishOnly && npm publish -ws --access public --dry-run","release:patch":"node scripts/release.mjs patch","release:minor":"node scripts/release.mjs minor","release:major":"node scripts/release.mjs major",prepare:"husky"},devDependencies:{"@anthropic-ai/sandbox-runtime":"0.0.57","@biomejs/biome":"2.3.15","@types/better-sqlite3":"^7.6.13","@types/lodash.mergewith":"^4.6.9","@types/node":"24.13.2","@types/turndown":"^5.0.6","@typescript/native-preview":"7.0.0-dev.20260120.1",concurrently:"^9.2.3",esbuild:"0.28.1","fast-xml-parser":"^5.9.3",husky:"9.1.7",jiti:"2.7.0",psadk:"^1.5.1",shx:"0.4.0",tsx:"4.22.4",turbo:"^2.9.18",typescript:"5.9.3",vitest:"^4.1.9"},engines:{node:">=20.0.0"},slingVersion:"3.0.20260810-3",overrides:{rimraf:"6.1.2",gaxios:{rimraf:"6.1.2"},postcss:"8.5.14",next:{postcss:"8.5.14"},"ip-address":"^10.1.1","@modelcontextprotocol/sdk":"^1.29.0",ai:">=5.0.52","fast-xml-parser":"^5.9.3","@aws-sdk/xml-builder":{"fast-xml-parser":"^5.9.3"},"adaptivecards-templating":{"adaptive-expressions":{"fast-xml-parser":"^5.5.8"}},picomatch:"^4.0.4","path-to-regexp":"8.4.1",router:{"path-to-regexp":"8.4.1"},minimatch:"^10.2.3",tar:"7.5.11",react:"19.1.1","react-dom":"19.1.1","@types/react":"19","@types/react-dom":"19",tailwindcss:"4.1.12",lightningcss:"1.30.2",glob:{".":"11.1.0",minimatch:"10.2.3"},prismjs:"^1.30.0",qs:"^6.15.0","@hono/node-server":"1.19.14",protobufjs:"^8.2.0","@opentelemetry/otlp-transformer":{protobufjs:"^8.2.0"},langchain:{langsmith:">=0.7.0"},hono:"4.12.18",fsevents:"^2.3.3",swiper:"^12.1.2",lodash:"^4.18.0","lodash-es":"^4.18.1",axios:"^1.15.0","ibm-cloud-sdk-core":"^5.4.11",dompurify:">=3.4.0","react-markdown-mermaid":{mermaid:"10.9.6"}},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0","@mozilla/readability":"^0.6.0","better-sqlite3":"^12.11.1","compound-engineering-pi":"^0.2.4","get-east-asian-width":"^1.4.0",linkedom:"^0.18.12",turndown:"^7.2.4",unpdf:"^1.6.2"}};import kp from"chalk";function wO(t,e){return{render(n){let i=` \u26AC _______. __ __ .__ __. _______
|
|
404
|
+
`;xo.appendFileSync(kr,i)}catch{}}var vo=null;function cO(t){if(!t)return;let e=t.trim();if(e)return e.replace(/\/+$/,"")}var oe=class t{static{this.BASE_URL="base_url"}static{this.ANALYTICS_DOMAIN="analytics_domain"}static{this.CLIENT_ID="client_id"}static{this.PROJECT_ID="project_id"}static{this.WORKSPACE_ID="workspace_id"}static{this.PROJECT_NAME="project_name"}static{this.WORKSPACE_NAME="workspace_name"}static{this.defaultValues={[t.BASE_URL]:"https://sapientaiproducts.com",[t.ANALYTICS_DOMAIN]:"https://slingshot.sapientaiproducts.com",[t.CLIENT_ID]:"b97fbef7-cad9-4e56-9850-39e86c8fdf61",[t.PROJECT_ID]:"fa8121c4-e2fc-48f1-9478-8949c04e13cc",[t.WORKSPACE_ID]:"6e5756eb-d7e2-4d80-ad07-9d7a51600d85"}}static{this.LOGIN_PATH="/web/v1/studio-auth/login"}static{this.EXCHANGE_PATH="/api/v1/studio-auth/auth/desktop/exchange"}static{this.REFRESH_PATH="/api/v3/auth/refreshtoken"}static{this.API_BASE_PATH="/api/v1/llm"}static{this.SAGE_EVENTS_PATH="/api/v1/ai-portal/sage_events"}static{this.APP_TOKEN_PATH="/api/v3/auth/app-token"}static{this.CONFIG_SERVICE_PATH="/api/v2/configservice/client"}static{this.SLINGSHOT_RAG_MCP="/api/v1/ai-prompt-lib/mcp/"}static{this.SAPI="/save/api/v1"}static{this.REFRESH_CLIENT_NAME="machine"}static{this.SLINGSHOT_APP_TOKEN_ENV="SLINGSHOT_APP_TOKEN_HEADER"}static{this.APP_TOKEN_REFRESH_BUFFER_MS=60*1e3}static{this.TOKEN_EXPIRY_BUFFER_MS=300*1e3}static{this.CLIENT_NAME="desktop"}static defaults(e){return this.defaultValues[e]}static getLocalSettingsPath(){return ng.resolve(process.cwd(),".sling","sling.settings.json")}static getGlobalSettingsPath(){return ng.resolve(Ee(),"sling.settings.json")}static getSettingsPath(e){if(e==="local")return this.getLocalSettingsPath();if(e==="global")return this.getGlobalSettingsPath();let n=this.getLocalSettingsPath();return wi.existsSync(n)?n:this.getGlobalSettingsPath()}static getSettings(){if(!vo){let i=this.getSettingsPath();try{if(wi.existsSync(i)){let r=wi.readFileSync(i,"utf-8"),o=JSON.parse(r)||{};vo={...this.defaultValues,...o}}else{let r=ng.dirname(i);wi.existsSync(r)||wi.mkdirSync(r,{recursive:!0}),wi.writeFileSync(i,JSON.stringify(this.defaultValues,null,2),"utf-8"),vo={...this.defaultValues}}}catch(r){gt("Error reading/writing sling.settings.json: ",r),vo={...this.defaultValues}}}let e=cO(process.env.SLINGSHOT_API_DOMAIN),n=cO(process.env.SLINGSHOT_ANALYTICS_DOMAIN);return{...vo,[t.BASE_URL]:e||vo[t.BASE_URL],[t.ANALYTICS_DOMAIN]:n||vo[t.ANALYTICS_DOMAIN]}}static updateSettings(e,n){let i=n?.scope??"global",r=this.getSettingsPath(i);try{let o={};if(wi.existsSync(r)){let l=wi.readFileSync(r,"utf-8");o=JSON.parse(l)||{}}let s={...this.defaultValues,...o,...e},a=ng.dirname(r);wi.existsSync(a)||wi.mkdirSync(a,{recursive:!0}),wi.writeFileSync(r,JSON.stringify(s,null,2),"utf-8"),vo=null}catch(o){gt("Error updating sling.settings.json: ",o)}}static getLoginUrl(e){let n=this.getSettings(),i=new URLSearchParams({client:this.CLIENT_NAME,port:String(e.port),localState:e.localState});return e.clientId&&i.set("clientId",e.clientId),`${n[t.BASE_URL]}${this.LOGIN_PATH}?${i.toString()}`}static getExchangeUrl(){return`${this.getSettings()[t.BASE_URL]}${this.EXCHANGE_PATH}`}static getRefreshUrl(){let e=this.getSettings(),n=new URLSearchParams({client:this.REFRESH_CLIENT_NAME});return`${e[t.BASE_URL]}${this.REFRESH_PATH}?${n.toString()}`}static getApiBaseUrl(){return`${this.getSettings()[t.BASE_URL]}${this.API_BASE_PATH}`}static getSageEventsUrl(){return`${this.getSettings()[t.ANALYTICS_DOMAIN]}${this.SAGE_EVENTS_PATH}`}static getSlingshotRAGMCPUrl(){return`${this.getSettings()[t.ANALYTICS_DOMAIN]}${this.SLINGSHOT_RAG_MCP}`}static getTokenExpiryBuffer(){return this.TOKEN_EXPIRY_BUFFER_MS}static getDefaultProjectId(){let e=this.getSettings();return process.env.SLINGSHOT_PROJECT_ID||e[t.PROJECT_ID]}static getDefaultWorkspaceId(){let e=this.getSettings();return process.env.SLINGSHOT_WORKSPACE_ID||e[t.WORKSPACE_ID]}static getDefaultClientId(){let e=this.getSettings();return process.env.CLIENT_ID||e[t.CLIENT_ID]}static getUserActivityUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users/activity`}static getUserUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/users`}static getModelsUrl(){return`${this.getSettings()[t.BASE_URL]}${this.SAPI}/ai/models`}static getAppTokenUrl(){return`${this.getSettings()[t.BASE_URL]}${this.APP_TOKEN_PATH}`}static getConfigServiceUrl(e){let n=this.getSettings(),i=this.getDefaultClientId(),r=new URLSearchParams({keys:e});return`${n[t.BASE_URL]}${this.CONFIG_SERVICE_PATH}/${i}?${r.toString()}`}static getAppTokenRefreshBuffer(){return this.APP_TOKEN_REFRESH_BUFFER_MS}};function yp(t){try{let e=t.split(".");if(e.length!==3)return 0;let n=JSON.parse(atob(e[1]));return n.exp?n.exp*1e3:0}catch{return 0}}function uO(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return(t==="x"?e:e&3|8).toString(16)})}var Zv="Xq7Wm2zR9pLkVbN4cD8fH3jT6yG1sA5",EQ=BigInt(Zv.length);function _Q(t){if(t.length===0)return"";let e=0n;for(let i of t){let r=Zv.indexOf(i);if(r===-1)throw new Error(`Cannot decode app_key: character "${i}" is not in the expected alphabet`);e=e*EQ+BigInt(r)}let n=[];for(;e>0n;)n.unshift(Number(e&0xffn)),e>>=8n;for(let i of t)if(i===Zv[0])n.unshift(0);else break;return new TextDecoder().decode(new Uint8Array(n))}var ey=new Map,ig=new Map;async function OQ(t,e){let n=oe.getConfigServiceUrl(t);Ne(`sling-config: fetching ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Bearer ${e}`}})}catch(s){let a=s instanceof Error?s.message:String(s);throw new Error(`Cannot reach config service: ${a}`)}if(!i.ok){let s=`${i.status} ${i.statusText}`;try{let a=await i.json();a.message?s=String(a.message):a.error&&(s=String(a.error))}catch{}throw new Error(`Config service request failed: ${s}`)}let o=(await i.json())?.data?.config;if(!o||typeof o!="object")throw new Error("Config service response missing data.config");return o}async function pO(t,e){let n=ey.get(t);if(n)return n;let i=ig.get(t);if(i)return i;if(!e)throw new Error("Cannot reach config service: no Slingshot user token provided");let r=OQ(t,e).then(o=>(ey.set(t,o),o)).finally(()=>{ig.delete(t)});return ig.set(t,r),r}var oc=class{static async getSlingcliConfig(e){let n=await pO("slingcli",e),i=n.slingcli;if(!i||typeof i.app_id!="string"||typeof i.app_key!="string"||!i.app_id||!i.app_key)throw gt("sling-config: missing slingcli block",n),new Error("Config service did not return slingcli.app_id / slingcli.app_key for this client");return{app_id:i.app_id,app_key:_Q(i.app_key)}}static async getRemoteConfig(e,n){return pO(e,n)}static clearCache(){ey.clear(),ig=new Map}};import dO from"node:path";import yo from"node:fs";var LQ="sling.app-creds.json";function ty(){return dO.resolve(Ee(),LQ)}function mO(){let t=ty();if(!yo.existsSync(t))return null;try{let e=yo.readFileSync(t,"utf-8"),n=JSON.parse(e);return typeof n.app_id!="string"||typeof n.app_key!="string"||!n.app_id||!n.app_key?(gt("app-creds-store: invalid creds file, ignoring",n),null):{app_id:n.app_id,app_key:n.app_key}}catch(e){return gt("app-creds-store: failed to read creds file",e),null}}function ny(t){let e=ty(),n=dO.dirname(e);try{yo.existsSync(n)||yo.mkdirSync(n,{recursive:!0});let i={...t,savedAt:Date.now()};yo.writeFileSync(e,JSON.stringify(i,null,2),{encoding:"utf-8",mode:384});try{yo.chmodSync(e,384)}catch{}Ne(`app-creds-store: persisted to ${e}`)}catch(i){gt("app-creds-store: failed to persist creds",i)}}function hO(){let t=ty();try{yo.existsSync(t)&&(yo.unlinkSync(t),Ne(`app-creds-store: cleared ${t}`))}catch(e){gt("app-creds-store: failed to clear creds file",e)}}var og=class extends Error{constructor(n,i){super(i);this.status=n;this.name="AppTokenHttpError"}},wp=null,Sp=null,rg=null,sc=null;function gO(t){process.env[oe.SLINGSHOT_APP_TOKEN_ENV]=`Bearer ${t}`}function WQ(t){sc&&(clearTimeout(sc),sc=null);let e=t.expiresAt-Date.now();e<=0||(sc=setTimeout(()=>{sc=null,ni().catch(n=>{gt("app-token: scheduled refresh failed",n)})},e),sc.unref?.())}async function fO(t){let e=Buffer.from(`${t.app_id}:${t.app_key}`).toString("base64"),n=oe.getAppTokenUrl();Ne(`app-token: minting from ${n}`);let i;try{i=await fetch(n,{method:"GET",headers:{Accept:"application/json",Authorization:`Basic ${e}`}})}catch(a){let l=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach app-token service: ${l}`)}if(!i.ok){let a=`${i.status} ${i.statusText}`;try{let l=await i.text()||"";l&&(a=l)}catch{}throw new og(i.status,`App token request failed: ${a}`)}let r=await i.json();if(!r.app_token||typeof r.expires_in!="number")throw new Error("App token response missing app_token or expires_in");let o=oe.getAppTokenRefreshBuffer(),s=Date.now()+r.expires_in*1e3-o;return Ne(`app-token: minted, expires at ${new Date(s).toISOString()}`),{token:r.app_token,expiresAt:s}}async function FQ(){let t=mO();if(t)return{creds:t,fromDisk:!0};if(!Sp)throw new Error("Cannot mint app token: no on-disk app credentials and no Slingshot user token available (please /login slingshot first)");let e=await oc.getSlingcliConfig(Sp);return ny(e),{creds:e,fromDisk:!1}}async function DQ(){let{creds:t,fromDisk:e}=await FQ();try{return await fO(t)}catch(n){let i=n instanceof og&&(n.status===401||n.status===403);if(!e||!i)throw n;if(gt("app-token: disk creds rejected (likely rotated), refetching from config service",{status:n.status}),hO(),!Sp)throw new Error("Cannot rotate app credentials: on-disk creds rejected and no Slingshot user token available (please /login slingshot)");let r=await oc.getSlingcliConfig(Sp);return ny(r),await fO(r)}}async function ni(t){if(t&&(Sp=t),wp&&wp.expiresAt>Date.now())return gO(wp.token),wp.token;if(rg)return(await rg).token;let e=DQ().then(i=>(wp=i,gO(i.token),WQ(i),i)).finally(()=>{rg=null});return rg=e,(await e).token}var Tp=null,iy=null;typeof process<"u"&&process.versions?.node&&(iy=import("node:http").then(t=>{Tp=t.createServer}));async function UQ(){if(Tp||(iy&&await iy,Tp))return Tp;throw new Error("Slingshot OAuth requires Node.js")}async function ry(t){let e=await UQ(),n,i,r,o=!1,s=new Promise((u,p)=>{i=u,r=p}),a=u=>{if(!o){o=!0;try{n.close()}catch{}u()}};n=e((u,p)=>{let d=new URL(u.url||"","http://127.0.0.1"),m=d.searchParams.get("code"),g=d.searchParams.get("state"),h=d.searchParams.get("clientId"),f=d.searchParams.get("error"),b=d.searchParams.get("error_description");if(f){p.writeHead(400,{"Content-Type":"text/html"}),p.end(`<html><body><h1>Login Failed</h1><p>${b||f}</p><p>You can close this window.</p></body></html>`),a(()=>r(new Error(`Login failed: ${b||f}`)));return}if(!m||!g){p.writeHead(400,{"Content-Type":"text/html"}),p.end("<html><body><h1>Login Failed</h1><p>Missing code or state in callback.</p><p>You can close this window.</p></body></html>"),a(()=>r(new Error("Missing code or state in callback")));return}p.writeHead(200,{"Content-Type":"text/html"}),p.end("<html><body><h1>Login Successful</h1><p>You can close this window and return to your terminal.</p><script>setTimeout(()=>window.close(),3000)</script></body></html>"),a(()=>i({code:m,state:g,clientId:h||""}))}),n.on("error",u=>{a(()=>r(u))});let l=setTimeout(()=>{a(()=>r(new Error("Login timeout - no callback received within 5 minutes")))},300*1e3);return n.on("close",()=>clearTimeout(l)),t&&t.addEventListener("abort",()=>{a(()=>r(new Error("Login cancelled")))}),{port:await new Promise((u,p)=>{n.once("error",p),n.listen(0,"127.0.0.1",()=>{let d=n.address();d&&typeof d=="object"?u(d.port):p(new Error("Failed to obtain loopback server port"))})}),result:s}}async function oy(t,e){if(!t)throw new Error("Missing exchange code");if(!e)throw new Error("Missing clientId for exchange");let n=oe.getExchangeUrl(),i;try{i=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",accept:"application/json"},body:JSON.stringify({code:t,clientId:e})})}catch(o){let s=o instanceof Error?o.message:String(o);throw new Error(`Cannot reach Studio Auth: ${s}`)}if(!i.ok){let o,s=`${i.status} ${i.statusText}`;try{let a=await i.json();o=a.error?.code,a.error?.message?s=a.error.message:a.message?s=a.message:o&&(s=o)}catch{}throw o==="INVALID_CALLBACK"?new Error("Login failed: exchange code is expired, already used, or bound to a different tenant. Please log in again."):new Error(`Code exchange failed: ${s}`)}let r=await i.json();if(!r.accessToken||!r.refreshToken)throw new Error("Exchange response missing accessToken or refreshToken");return r}function NQ(){return $Q(16).toString("hex")}function BQ(t){let e=new URL(t),n=e.searchParams.get("code"),i=e.searchParams.get("state"),r=e.searchParams.get("clientId");if(!n||!i)throw new Error("Pasted URL is missing code or state");return{code:n,state:i,clientId:r||""}}async function sy(t){let e=process.env.SLINGSHOT_TOKEN;if(e){let u=yp(e);return Ne("Using Slingshot token from SLINGSHOT_TOKEN environment variable"),await ni(e),{refresh:"",access:e,expires:u>0?u-oe.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:oe.getDefaultProjectId(),workspaceId:oe.getDefaultWorkspaceId()}}let{port:n,result:i}=await ry(t.signal),r=NQ(),o=oe.getDefaultClientId(),s=oe.getLoginUrl({port:n,localState:r,clientId:o||void 0});t.onAuth({url:s});let a;if(t.onManualCodeInput){let u=t.onManualCodeInput().then(BQ);a=await Promise.race([i,u])}else a=await i;if(a.state!==r)throw new Error("CSRF check failed - state does not match localState");if(!a.clientId)throw new Error("Login callback did not include clientId");let l=await oy(a.code,a.clientId),c=yp(l.accessToken);return await ni(l.accessToken),{refresh:l.refreshToken,access:l.accessToken,expires:c>0?c-oe.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:oe.getDefaultProjectId(),workspaceId:oe.getDefaultWorkspaceId()}}import{randomUUID as jQ}from"node:crypto";async function ay(t){if(!t.refresh)throw new Error("No refresh token available. Please login again.");let e;try{e=await ni()}catch(a){throw gt("auth/refresh: app token unavailable for refresh call",a),new Error(`Cannot refresh Slingshot token: app token unavailable (${a instanceof Error?a.message:String(a)}). Please /login slingshot.`)}let n=jQ(),i={accept:"application/json",rt:t.refresh,"trace-id":n,Authorization:`Bearer ${e}`},r;try{let a=oe.getRefreshUrl();r=await fetch(a,{headers:i})}catch(a){let l=a instanceof Error?a.message:String(a);throw new Error(`Cannot reach Slingshot server: ${l}`)}if(!r.ok){let a=`${r.status} ${r.statusText}`;try{let l=await r.json();l.message?a=String(l.message):l.error&&(a=String(l.error))}catch{}throw new Error(`Token refresh failed: ${a}`)}let o=await r.json();if(!o.accessToken)throw new Error("No access token in refresh response");let s=yp(o.accessToken);try{await ni(o.accessToken)}catch(a){throw gt("auth/refresh: app token refresh failed",a),a}return{refresh:o.refreshToken||t.refresh,access:o.accessToken,expires:s>0?s-oe.getTokenExpiryBuffer():Date.now()+10800*1e3,projectId:t.projectId,workspaceId:t.workspaceId}}var sg=[{id:"gpt-5.4-nano",name:"GPT-5.4 nano",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:.2,output:1.25,cacheRead:.02,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-4.1",name:"GPT-4.1",baseUrl:"",reasoning:!1,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:1047576,maxTokens:32768,provider:"slingshot",api:"openai-completions"},{id:"gpt-5",name:"GPT-5",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.125,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5-mini",name:"GPT-5 Mini",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:.25,output:2,cacheRead:.025,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5-nano",name:"GPT-5 Nano",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:.05,output:.4,cacheRead:.005,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5.1",name:"GPT-5.1",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.25,output:10,cacheRead:.13,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5.2",name:"GPT-5.2",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"gpt-5.4-mini",name:"GPT-5.4 mini",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:.75,output:4.5,cacheRead:.075,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.4",name:"GPT-5.4",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:2.5,output:15,cacheRead:.25,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.5",name:"GPT-5.5",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:5,output:30,cacheRead:.5,cacheWrite:0},contextWindow:272e3,maxTokens:128e3,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.6-luna",name:"GPT-5.6 Luna",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:.96,output:5.76,cacheRead:.096,cacheWrite:0},contextWindow:105e4,maxTokens:5e5,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.6-terra",name:"GPT-5.6 Terra",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:2.4,output:14.4,cacheRead:.24,cacheWrite:0},contextWindow:105e4,maxTokens:5e5,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.6-sol",name:"GPT-5.6 Sol",baseUrl:"",reasoning:!0,thinkingLevelMap:{xhigh:"xhigh"},input:["text","image"],cost:{input:4.8,output:28.8,cacheRead:.48,cacheWrite:0},contextWindow:105e4,maxTokens:5e5,api:"openai-responses",provider:"slingshot"},{id:"gpt-5.3-codex",name:"GPT-5.3 Codex",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.75,output:14,cacheRead:.175,cacheWrite:0},contextWindow:4e5,maxTokens:128e3,provider:"slingshot",api:"openai-responses"},{id:"claude-opus-4@20250514",name:"Claude Opus 4",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:15,output:75,cacheRead:1.5,cacheWrite:18.75},contextWindow:2e5,maxTokens:32e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4@20250514",name:"Claude Sonnet 4",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-5@20250929",name:"Claude Sonnet 4.5",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:2e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:1e6,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"claude-opus-4-6",name:"Claude Opus 4.6",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:5,output:25,cacheRead:.5,cacheWrite:6.25},contextWindow:1e6,maxTokens:128e3,provider:"slingshot",api:"openai-completions"},{id:"claude-sonnet-5",name:"Claude Sonnet 5",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:3,output:15,cacheRead:.3,cacheWrite:3.75},contextWindow:1e5,maxTokens:64e3,provider:"slingshot",api:"openai-completions"},{id:"Qwen/Qwen3.6-27B-FP8",name:"Qwen 3.6 27B FP8",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.2,output:3.6,cacheRead:.3,cacheWrite:3.75},contextWindow:64e3,maxTokens:56e3,provider:"slingshot",api:"openai-completions"},{id:"o3",name:"O3",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:2,output:8,cacheRead:.5,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o3-mini",name:"o3-mini",baseUrl:"",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.55,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"o4-mini",name:"o4-mini",baseUrl:"",reasoning:!0,input:["text"],cost:{input:1.1,output:4.4,cacheRead:.28,cacheWrite:0},contextWindow:2e5,maxTokens:1e5,provider:"slingshot",api:"openai-completions"},{id:"gemini-3.1-flash-lite",name:"Gemini 3.1 Flash Lite",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:.44,output:1.32,cacheRead:.075,cacheWrite:0},contextWindow:1e6,maxTokens:5e5,provider:"slingshot",api:"openai-completions"},{id:"gemini-3.1-pro-preview",name:"Gemini 3.1 Pro Preview",baseUrl:"",reasoning:!0,input:["text","image"],cost:{input:1.76,output:10.56,cacheRead:.075,cacheWrite:0},contextWindow:1e6,maxTokens:5e5,provider:"slingshot",api:"openai-completions"}];var ag=t=>Math.round((t??0)*1e3*1e6)/1e6,qQ=32768,GQ=new Map(sg.map(t=>[t.id,t.maxTokens]));async function bO(t,e){let n=await fetch(t,{headers:{Authorization:`Bearer ${e}`,Accept:"application/json"}});if(!n.ok)throw new Error(`Slingshot models fetch failed: ${n.status}`);let i=await n.json();return KQ(Array.isArray(i)?i:i?.data??[])}function KQ(t){return t.filter(e=>e.model_type==="chat").map(e=>{let n=e.metadata??{},i=n.context_length??0,r=(n.supported_modalities??["text"]).filter(o=>o==="text"||o==="image");return{id:e.id,name:n.name||e.id,baseUrl:"",reasoning:!!n.reasoning,input:r,cost:{input:ag(e.inputCostPer1KTokens),output:ag(e.outputCostPer1KTokens),cacheRead:ag(e.cacheCostPer1KTokens?.read),cacheWrite:ag(e.cacheCostPer1KTokens?.write)},contextWindow:i,maxTokens:Math.min(i,GQ.get(e.id)??qQ),provider:"slingshot",api:e.supported_apis?.includes("responses")?"openai-responses":"openai-completions"}}).sort((e,n)=>e.id.localeCompare(n.id))}import xO from"node:fs";function vO(t,e,n){try{xO.writeFileSync(t,JSON.stringify({baseUrl:e,fetchedAt:new Date().toISOString(),models:n}))}catch{}}function yO(t,e){try{let n=JSON.parse(xO.readFileSync(t,"utf-8"));return n?.baseUrl!==e||!Array.isArray(n.models)||n.models.length===0?null:n.models}catch{return null}}var lg={name:"slingshot.cli",private:!0,type:"module",workspaces:["packages/*","packages/web-ui/example","packages/coding-agent/examples/extensions/with-deps","packages/coding-agent/examples/extensions/custom-provider-anthropic","packages/coding-agent/examples/extensions/custom-provider-gitlab-duo"],scripts:{clean:"npm run clean --workspaces",build:"cd packages/tui && npm run build && cd ../ai && npm run build && cd ../agent && npm run build && cd ../storage/sqlite-node && npm run build && cd ../../coding-agent && npm run build && cd ../server && npm run build","build:offline":"cd packages/tui && npm run build && cd ../ai && npm run build:offline && cd ../agent && npm run build && cd ../storage/sqlite-node && npm run build && cd ../../coding-agent && npm run build && cd ../server && npm run build",dev:'concurrently --names "ai,agent,coding-agent,web-ui,tui" --prefix-colors "cyan,yellow,red,white,green,magenta" "cd packages/ai && npm run dev" "cd packages/agent && npm run dev" "cd packages/coding-agent && npm run dev" "cd packages/server && npm run dev" "cd packages/tui && npm run dev"',"dev:tsc":'concurrently --names "ai,web-ui" --prefix-colors "cyan,green" "cd packages/ai && npm run dev:tsc" "cd packages/web-ui && npm run dev:tsc"',check:"","check:browser-smoke":"","test:models":"node scripts/test-models.mjs","profile:tui":"node scripts/profile-coding-agent-node.mjs --mode tui","profile:rpc":"node scripts/profile-coding-agent-node.mjs --mode rpc",test:"npm run test --workspaces --if-present","version:patch":"npm version patch -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:minor":"npm version minor -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:major":"npm version major -ws --no-git-tag-version && node scripts/sync-versions.js && shx rm -rf node_modules packages/*/node_modules package-lock.json && npm install","version:set":"npm version -ws",prepublishOnly:"npm run clean && npm run build && npm run check",publish:"npm run prepublishOnly && npm publish -ws --access public","publish:dry":"npm run prepublishOnly && npm publish -ws --access public --dry-run","release:patch":"node scripts/release.mjs patch","release:minor":"node scripts/release.mjs minor","release:major":"node scripts/release.mjs major",prepare:"husky"},devDependencies:{"@anthropic-ai/sandbox-runtime":"0.0.57","@biomejs/biome":"2.3.15","@types/better-sqlite3":"^7.6.13","@types/lodash.mergewith":"^4.6.9","@types/node":"24.13.2","@types/turndown":"^5.0.6","@typescript/native-preview":"7.0.0-dev.20260120.1",concurrently:"^9.2.3",esbuild:"0.28.1","fast-xml-parser":"^5.9.3",husky:"9.1.7",jiti:"2.7.0",psadk:"^1.5.1",shx:"0.4.0",tsx:"4.22.4",turbo:"^2.9.18",typescript:"5.9.3",vitest:"^4.1.9"},engines:{node:">=20.0.0"},slingVersion:"3.0.20260811-1",overrides:{rimraf:"6.1.2",gaxios:{rimraf:"6.1.2"},postcss:"8.5.14",next:{postcss:"8.5.14"},"ip-address":"^10.1.1","@modelcontextprotocol/sdk":"^1.29.0",ai:">=5.0.52","fast-xml-parser":"^5.9.3","@aws-sdk/xml-builder":{"fast-xml-parser":"^5.9.3"},"adaptivecards-templating":{"adaptive-expressions":{"fast-xml-parser":"^5.5.8"}},picomatch:"^4.0.4","path-to-regexp":"8.4.1",router:{"path-to-regexp":"8.4.1"},minimatch:"^10.2.3",tar:"7.5.11",react:"19.1.1","react-dom":"19.1.1","@types/react":"19","@types/react-dom":"19",tailwindcss:"4.1.12",lightningcss:"1.30.2",glob:{".":"11.1.0",minimatch:"10.2.3"},prismjs:"^1.30.0",qs:"^6.15.0","@hono/node-server":"1.19.14",protobufjs:"^8.2.0","@opentelemetry/otlp-transformer":{protobufjs:"^8.2.0"},langchain:{langsmith:">=0.7.0"},hono:"4.12.18",fsevents:"^2.3.3",swiper:"^12.1.2",lodash:"^4.18.0","lodash-es":"^4.18.1",axios:"^1.15.0","ibm-cloud-sdk-core":"^5.4.11",dompurify:">=3.4.0","react-markdown-mermaid":{mermaid:"10.9.6"}},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0","@mozilla/readability":"^0.6.0","better-sqlite3":"^12.11.1","compound-engineering-pi":"^0.2.4","get-east-asian-width":"^1.4.0",linkedom:"^0.18.12",turndown:"^7.2.4",unpdf:"^1.6.2"}};import kp from"chalk";function wO(t,e){return{render(n){let i=` \u26AC _______. __ __ .__ __. _______
|
|
405
405
|
\u274D \xB7 \u274D / || | | | | \\ | | / _____|
|
|
406
406
|
\u2726 \u26AC \u2726 | (----\`| | | | | \\| | | | __
|
|
407
407
|
\u26AC \xB7 \u26AC \u26AC \xB7 \u26AC \\ \\ | | | | | . \` | | | |_ |
|
|
@@ -500,7 +500,9 @@ Coordinate with other local sling sessions on related codebases. Use \`/skill:pi
|
|
|
500
500
|
</pi-intercom>`;function oxe(t){let e=new WeakSet,n="",i={},r=uO(),o=new Date,s="";t.unregisterProvider("Anthropic"),t.unregisterProvider("GitHub Copilot"),t.unregisterProvider("OpenAI"),t.unregisterProvider("OpenAI Codex"),t.unregisterProvider("XAI"),Xv(),RO(t),hk(t),MO(t,()=>Sk),ew(t),fU(t),bU(t),MU(t),yk(t);function a(){let u=t.getFlag("profile")||"default",p="";if(u.endsWith(".md")){n=xd.readFileSync(u,"utf-8"),t.sendMessage({customType:"slingshot-profile",content:`Loaded Profile: ${u}`,display:!0});return}if(p=ui.resolve(".sling","profiles",`./${u}.md`),xd.existsSync(p)||(p=ui.resolve(Ee(),"profiles",`./${u}.md`)),xd.existsSync(p))try{n=xd.readFileSync(p,"utf-8"),t.sendMessage({customType:"slingshot-profile",content:`Loaded Profile: ${u}`,display:!0});return}catch{}t.sendMessage({customType:"slingshot-profile",content:`Profile Not found: ${u}`,display:!0})}t.registerFlag("profile",{type:"string",description:"Set a profile to use for this session (the profiles are stored in .sling/profiles/*). Usage: --profile=work or --profile=personal. This is useful to switch between different personas in the system prompts for different contexts (e.g. work vs personal).",default:"default"}),t.on("resources_discover",async u=>{let p=ui.join(wk(),".pi","agent"),d=ui.join(wk(),".agents"),m=ui.join(wk(),".slingshot"),h=[ui.join(u.cwd,".sling","agent"),d,p],f=[],b=[],v=[];for(let y of h){let R=ui.join(y,"skills");l0(R)&&f.push(R);let T=ui.join(y,"prompts");l0(T)&&b.push(T);let k=ui.join(y,"themes");l0(k)&&v.push(k)}return{skillPaths:f,promptPaths:b,themePaths:v}}),t.on("session_start",async(u,p)=>{In.initialize(p),p.hasUI&&p.ui.setHeader(wO);try{let d=await p.modelRegistry.getApiKeyForProvider("slingshot"),m=d?await ni(d):void 0;m||Ne("session_start: no Slingshot token found in modelRegistry"),d&&c(d),p.hasUI&&(m?p.ui.notify("Slingshot initialized successfully.","info"):p.ui.notify("Slingshot not authorized. Please use /login slingshot to authenticate.","warning")),await In.refreshAndUpdate(p,{force:!0,logErrors:!0})}catch(d){Ne(`session_start: app-token fetch failed: ${d instanceof Error?d.message:String(d)}`)}});let l=ui.join(Ee(),"slingshot-models.cache.json");async function c(u){try{let p=await bO(oe.getModelsUrl(),u);if(!p.length){Ne("refreshModels: API returned no chat models, keeping current list");return}vO(l,oe.getApiBaseUrl(),p),t.registerProvider("slingshot",{baseUrl:oe.getApiBaseUrl(),api:"openai-completions",apiKey:"$SLINGSHOT_API_KEY",models:p.map(d=>({...d,baseUrl:oe.getApiBaseUrl()}))}),Ne(`refreshModels: registered ${p.length} models from API`)}catch(p){Ne(`refreshModels: failed, keeping current list: ${p instanceof Error?p.message:String(p)}`)}}t.registerProvider("slingshot",{baseUrl:oe.getApiBaseUrl(),api:"openai-completions",apiKey:"$SLINGSHOT_API_KEY",models:(yO(l,oe.getApiBaseUrl())??sg).map(u=>({...u,baseUrl:oe.getApiBaseUrl()})),oauth:{name:"Slingshot",login:async u=>{let p=await sy(u);return Sk=p,c(p.access),p},refreshToken:ay,getApiKey:u=>(Sk=u,u.access)}}),t.on("before_provider_headers",async(u,p)=>{if(p.model?.provider!=="slingshot")return;let d=await p.modelRegistry.getApiKeyForProvider("slingshot");if(!d)throw new Error("Slingshot user token unavailable while preparing request headers");let m=await ni(d);u.headers["X-App-Authorization"]=`Bearer ${m}`}),t.registerCommand("s:settings",{description:"Edit Slingshot settings (base URL, analytics domain, and IDs)",handler:async(u,p)=>{let d=oe.getSettings();if(!p.hasUI){t.sendMessage({customType:"slingshot-settings",content:JSON.stringify(d,null,2),display:!0});return}let m=oe.getLocalSettingsPath(),g=oe.getGlobalSettingsPath(),h=await p.ui.editor("Slingshot settings (JSON)",JSON.stringify(d,null,2));if(!h){p.ui.notify("Cancelled","info");return}let f;try{let T=JSON.parse(h);if(!T||typeof T!="object"||Array.isArray(T))throw new Error("Expected a JSON object");f=T}catch(T){p.ui.notify(`Invalid JSON: ${T instanceof Error?T.message:String(T)}`,"error");return}let b=await p.ui.select("Save location",[`Local (${m})`,`Global (${g})`]);if(!b){p.ui.notify("Cancelled","info");return}let v=b.startsWith("Local")?"local":"global";oe.updateSettings(f,{scope:v});let y=v==="local"?m:g;p.ui.notify(`Settings saved to ${y}`,"info");let R=oe.getSettings();t.sendMessage({customType:"slingshot-settings",content:JSON.stringify(R,null,2),display:!0})}}),t.registerCommand("s:debug",{description:"Toggle Slingshot debug logging",handler:async(u,p)=>{let d=!vp();if(aO(d),d){let m="Slingshot Debug: ENABLED \u2705",g=lO();g&&(m+=`
|
|
501
501
|
|
|
502
502
|
Log file:
|
|
503
|
-
${g}`),t.sendMessage({customType:"slingshot-debug-status",content:m,display:!0})}else t.sendMessage({customType:"slingshot-debug-status",content:"Slingshot Debug: DISABLED \u274C",display:!0})}}),t.on("before_agent_start",async(u,p)=>{try{if(In.startStreaming(p),await In.refreshAndUpdate(p,{force:!0,logErrors:!0})<=0){p.hasUI&&(p.ui.notify("You do not have enough credits remaining. Please recharge to continue using the slingcli.","warning"),p.ui.notify("For more information on credits, visit: https://sapientaiproducts.com/help/credits","info")),p.abort();return}i={},o=new Date,CU(p),wo(p),uy(p,"random");let m=!u.systemPrompt.includes("<pi-intercom>");if(m||n)
|
|
503
|
+
${g}`),t.sendMessage({customType:"slingshot-debug-status",content:m,display:!0})}else t.sendMessage({customType:"slingshot-debug-status",content:"Slingshot Debug: DISABLED \u274C",display:!0})}}),t.on("before_agent_start",async(u,p)=>{try{if(In.startStreaming(p),await In.refreshAndUpdate(p,{force:!0,logErrors:!0})<=0){p.hasUI&&(p.ui.notify("You do not have enough credits remaining. Please recharge to continue using the slingcli.","warning"),p.ui.notify("For more information on credits, visit: https://sapientaiproducts.com/help/credits","info")),p.abort();return}i={},o=new Date,CU(p),wo(p),uy(p,"random");let m=!u.systemPrompt.includes("<pi-intercom>");if(m||n){let g=m?u.systemPrompt+rxe+n:u.systemPrompt+n;return Ne(`before_agent_start: updated system prompt:
|
|
504
|
+
${g}`),{systemPrompt:g}}else Ne(`before_agent_start: system prompt:
|
|
505
|
+
${u.systemPrompt}`)}catch(d){vp()&&(Ne(`CRITICAL ERROR in event handler: ${d?.message||d}`),d?.stack&&Ne(d.stack))}}),t.on("agent_start",async(u,p)=>{try{if(In.startStreaming(p),await In.refreshAndUpdate(p,{logErrors:!0})<=0){p.hasUI&&(p.ui.notify("You do not have enough credits remaining. Please recharge to continue using the slingcli.","warning"),p.ui.notify("For more information on credits, visit: https://sapientaiproducts.com/help/credits","info")),p.abort();return}}catch(d){Ne(`agent_start: failed to refresh credits: ${d instanceof Error?d.message:String(d)}`)}}),t.on("tool_result",async(u,p)=>{if(wo(p),u.toolName==="write"||u.toolName==="edit")try{if(u.isError)return;let m=(u.input.path+"").split(".").pop()||"",g=m,h="",f=0,b=0;u.toolName==="write"?(h=u.input.content+"",f=h.split(`
|
|
504
506
|
`).length):u.toolName==="edit"&&(h=(u.details?.diff+"").split(`
|
|
505
507
|
`).filter(y=>{let R=y.startsWith("+"),T=y.startsWith("-");return R&&f++,T&&b++,T||R}).join(`
|
|
506
508
|
`));let v=f+b;i[m]=i[m]||0,i[m]+=v}catch(d){t.sendMessage({customType:"slingshot-analytics-error",content:"[Slingshot] Analytics error. Run /slingshot-debug for details.",display:!0}),vp()&&(Ne(`CRITICAL ERROR in event handler: ${d?.message||d}`),d?.stack&&Ne(d.stack))}}),t.on("tool_execution_end",async(u,p)=>{wo(p),In.onProgress(p)}),t.on("message_start",async(u,p)=>{wo(p),In.onProgress(p)}),t.on("message_update",async(u,p)=>{wo(p),In.onMessageUpdate(p,u.message)}),t.on("message_end",async(u,p)=>{wo(p),In.onMessageEnd(p,u.message)}),t.on("agent_end",async(u,p)=>{try{In.stopStreaming(p);let d=await In.refreshAndUpdate(p,{force:!0,logErrors:!0});xk(p);let m=0,g=0,h=0;for(let b of p.sessionManager.getEntries())b.type==="message"&&b.message.role==="assistant"&&(m+=b.message.usage.input,g+=b.message.usage.output,h+=b.message.usage.cost.total);try{let b=ui.join(p.cwd,".git");l0(b)&&(s=await xd.promises.readFile(ui.join(b,"config"),"utf-8").then(v=>{let y=v.match(/\[remote "origin"\][\s\S]*?url\s*=\s*(.+)/);return y?y[1]:""}))}catch(b){Ne(`Failed to read git config for analytics: ${b instanceof Error?b.message:String(b)}`)}let f=await gk({activity_type:"slingcli:agent:execute",activity_entity_id:r,activity_entity_type:"coding_agent",total_tokens:m+g,activity_startdate:o,activity_enddate:new Date,credits_used:0,metadata:{type:"analytics",correlation_id:r,cost:h,model:p.model?.id,folder:p.cwd,giturl:s,filechanges:i}},p);p.hasUI&&(f.credits_used&&p.ui.notify(`Credits used: ${f.credits_used.toFixed(4)}`,"info"),typeof f.remainingCredits=="number"&&In.setCreditsFromServer(p,f.remainingCredits))}catch(d){t.sendMessage({customType:"slingshot-analytics-error",content:"[Slingshot] Analytics error. Run /slingshot-debug for details.",display:!0}),vp()&&(Ne(`CRITICAL ERROR in event handler: ${d?.message||d}`),d?.stack&&Ne(d.stack))}}),t.on("tool_execution_start",async(u,p)=>{wo(p),In.onProgress(p)})}export{oxe as default};
|