@x-otto/cli 0.0.1-alpha.5 → 0.0.1-alpha.6

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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{A as e,B as t,C as n,D as r,E as i,F as a,G as o,H as s,I as c,J as l,K as u,L as d,M as f,N as p,O as m,P as h,R as g,S as _,T as v,U as y,V as b,W as x,_ as ee,b as S,c as te,d as C,f as w,g as ne,h as T,i as E,j as D,k as re,l as ie,m as O,n as ae,o as k,p as A,q as j,r as M,s as N,t as oe,u as se,v as ce,w as P,x as F,y as le,z as ue}from"./command-dispatcher-BVGddstc.js";import{t as de}from"./version-C0qM-qJM.js";import{n as fe,t as pe}from"./parse-cli-cYMjnAum.js";import{t as I}from"./discover-with-bundled-CznLjkkw.js";import{n as me,r as he}from"./model-auth-BlaZzUUK.js";import{n as L}from"./proxy-evg7ZvoD.js";import{r as ge}from"./registry-D0NONjLv.js";import{homedir as R}from"node:os";import{execFile as _e,spawn as ve}from"node:child_process";import{SANDBOX_ESCALATION_MARKER as z,apiCredentialId as ye,buildPluginCliRegistry as be,collectPluginThemePresets as xe,createApp as B,evaluatePluginTrust as Se,evaluateWorkspaceTrustPrompt as Ce,expandCommandBody as we,findPluginCliNameConflict as Te,globalAgentJobRegistry as V,globalAgentObservability as H,globalProcessRegistry as U,readTaskOutputTail as Ee,resolvePluginCliBin as W,resolveSessionTitle as De,spawnPluginCli as G,trustProject as K}from"@x-otto/coding";import{globalAgentJobRegistry as q,globalProcessRuntime as Oe,installExitReaper as J}from"@x-otto/runtime";import{buildAllowedEnv as ke,checkShellCommand as Y,createLogger as Ae,markStartupPhase as je,rankCandidates as X,setLogLevel as Me,traceStartupPhase as Ne,traceStartupPhaseSync as Pe}from"@x-otto/shared";import{BUILD_ID as Fe,OTTO_HOME as Ie,OTTO_SESSIONS_DIR as Le,SDK_VERSION as Re,flushEnvWarnings as ze,isShadowModeEnabled as Be,loadUserIdentity as Ve}from"@x-otto/env";import{dirname as He,join as Z,resolve as Ue}from"node:path";import{existsSync as We}from"node:fs";import{fileURLToPath as Ge}from"node:url";import{BASH_HISTFILE_SOURCE as Ke,COMPACTING_SENTINEL as qe,FISH_HISTFILE_SOURCE as Je,ZSH_HISTFILE_SOURCE as Ye,createBuiltinThemeRegistry as Xe,entriesToCommands as Ze,formatAgentDiagnosticsText as Qe,formatTranscriptText as $e,formatTurnTimeline as et,i18next as Q,isUsingOverage as tt,observationLiveFields as nt,observationRow as rt,parseBashHistory as it,parseFishHistory as at,parseZshHistory as ot,promptParentWorkspaceChoice as st,promptWorkspaceTrust as ct,setMarkdownThemeUserOverrides as lt,subagentEntryStatus as ut}from"@x-otto/tui";import{access as dt,mkdir as ft,readFile as pt,rename as mt,unlink as ht,writeFile as gt}from"node:fs/promises";import{createModelUsabilityGate as _t}from"@x-otto/ai";import{SESSION_RESUME_WINDOW_MESSAGES as vt,createProjectorState as yt,projectSessionEvent as bt,resolveChoiceAnswer as xt,resolveTextAnswer as St,sandboxBypassCommand as Ct,shouldShowPulseSurvey as wt}from"@x-otto/session-contract";import{ScheduleRegistry as Tt,SchedulerService as Et,createLocalFireOwnership as Dt,createRemoteFireOwnership as Ot,createRemoteScheduleStore as kt,createScheduleStore as At,parseCron as jt}from"@x-otto/schedule";function Mt(e=process.stdout){if(process.env.OTTO_TUI_SCOPED_VIEWPORT===`0`&&process.env.OTTO_TUI_CLEAR_ON_EXIT!==`0`&&e.isTTY)try{e.write(`\x1B[2J\x1B[3J\x1B[H`)}catch{}}async function Nt(e,t){let n=e;for(;n.type===`response`&&n.endReason===`max-tool-turns`&&n.notice;){if(!await t.askBudgetContinue()){t.onBudgetStopped();return}t.beforeContinuationTurn();let e=await t.runTurn(`Continue with the remaining work until the task is complete.`);if(t.onTurnResult(e)===`exit`)return;n=e}}function Pt(e,t){return e||t}function Ft(e){let t=[],n=0,r=``,i=()=>{r&&=(t.push(r),``)};for(;n<e.length;){let t=e[n];if(t===` `||t===` `){i(),n++;continue}if(t===`\\`){n++,n<e.length&&(r+=e[n]),n++;continue}if(t===`"`){n++;let t=It(e,n,`"`);r+=t.value,n=t.next;continue}if(t===`'`){n++;let t=It(e,n,`'`,!1);r+=t.value,n=t.next;continue}r+=t,n++}return i(),{tokens:t}}function It(e,t,n,r=!0){let i=``,a=t;for(;a<e.length;){let t=e[a];if(r&&t===`\\`){a++,a<e.length&&(i+=e[a]),a++;continue}if(t===n)return a++,{value:i,next:a};i+=t,a++}return{value:i,next:a}}function Lt(e){let t=e.trim();if(!t.startsWith(`/`)||t===`/`||t.startsWith(`//`))return{isCommand:!1,text:t};let{tokens:n}=Ft(t.slice(1));if(n.length===0)return{isCommand:!1,text:t};let[r,...i]=n;return{isCommand:!0,command:r,args:i}}function Rt(e,t){return e===`pin`&&t?`unpin`:e}function zt(e,t){return e===`pause`&&t?`continue`:e}function Bt(e,t,n){let r=e.list().sort((e,t)=>e.name.localeCompare(t.name)),i=r.map(e=>` /${Rt(e.name,t)}${e.aliases?.length?` (${e.aliases.join(`, `)})`:``}`),a=Math.max(...i.map(e=>e.length)),o=[];for(let e=0;e<r.length;e++){let s=r[e],c=n[Rt(s.name,t)]??n[s.name]??s.description;o.push(`${i[e].padEnd(a)} — ${c}`)}return o.push(``,`Prefixes: !<cmd> run shell | @<file> read file`),o}function Vt(e,t,n,r,i=!1,a=!1){return e.list().filter(e=>e.name===`pause`?t||a:!0).map(e=>{let o=zt(Rt(e.name,i),a);return{name:o,description:r?.[o]??r?.[e.name]??e.description,disabled:t&&!n.has(e.name)&&e.name!==`abort`,sortKey:e.name}})}function Ht(e){for(let t of E)t.tuiHidden||t.envGate&&process.env[t.envGate]!==`1`||(e.has(t.name)&&e.unregister(t.name),e.register({name:t.name,description:t.description??t.name,aliases:t.aliases,type:`action`,source:`builtin`,execute:()=>``}))}var Ut=class{estimate;intervalMs;now;text=``;measuredTokens=0;measuredChars=0;measuredAt=-1/0;constructor(e){this.estimate=e.estimate,this.intervalMs=e.intervalMs??250,this.now=e.now??(()=>Date.now())}reset(){this.text=``,this.measuredTokens=0,this.measuredChars=0,this.measuredAt=-1/0}push(e){if(!e)return;this.text+=e;let t=this.now();t-this.measuredAt>=this.intervalMs&&this.measure(t)}flush(){this.measure(this.now())}tokens(){let e=this.text.length-this.measuredChars;if(e<=0)return this.measuredTokens;let t=this.measuredChars>0?this.measuredTokens/this.measuredChars:.25;return this.measuredTokens+Math.ceil(e*t)}measure(e){this.measuredTokens=this.text?this.estimate(this.text):0,this.measuredChars=this.text.length,this.measuredAt=e}};function Wt(e,t){if(/^(bash|shell|run_command|execute|exec)$/i.test(e)){let e=t?.command;if(e)return e}return JSON.stringify(t??{}).slice(0,300)}async function Gt(e,t){let n=[`● ${t.header} — ${t.askedBy} asks:`,t.background?`\n${t.background}`:``,Q.t(`cmd.grillRecommendation`,{rec:t.recommendation}),t.evidence?.length?Q.t(`cmd.grillEvidence`,{joined:t.evidence.map(e=>` · ${e}`).join(`
2
+ import{A as e,B as t,C as n,D as r,E as i,F as a,G as o,H as s,I as c,J as l,K as u,L as d,M as f,N as p,O as m,P as h,R as g,S as _,T as v,U as y,V as b,W as x,_ as ee,b as S,c as te,d as C,f as w,g as ne,h as T,i as E,j as D,k as re,l as ie,m as O,n as ae,o as k,p as A,q as j,r as M,s as N,t as oe,u as se,v as ce,w as P,x as F,y as le,z as ue}from"./command-dispatcher-BVGddstc.js";import{t as de}from"./version-C0qM-qJM.js";import{n as fe,t as pe}from"./parse-cli-C6cLzKhy.js";import{t as I}from"./discover-with-bundled-CznLjkkw.js";import{n as me,r as he}from"./model-auth-BlaZzUUK.js";import{n as L}from"./proxy-evg7ZvoD.js";import{r as ge}from"./registry-D0NONjLv.js";import{homedir as R}from"node:os";import{execFile as _e,spawn as ve}from"node:child_process";import{SANDBOX_ESCALATION_MARKER as z,apiCredentialId as ye,buildPluginCliRegistry as be,collectPluginThemePresets as xe,createApp as B,evaluatePluginTrust as Se,evaluateWorkspaceTrustPrompt as Ce,expandCommandBody as we,findPluginCliNameConflict as Te,globalAgentJobRegistry as V,globalAgentObservability as H,globalProcessRegistry as U,readTaskOutputTail as Ee,resolvePluginCliBin as W,resolveSessionTitle as De,spawnPluginCli as G,trustProject as K}from"@x-otto/coding";import{globalAgentJobRegistry as q,globalProcessRuntime as Oe,installExitReaper as J}from"@x-otto/runtime";import{buildAllowedEnv as ke,checkShellCommand as Y,createLogger as Ae,markStartupPhase as je,rankCandidates as X,setLogLevel as Me,traceStartupPhase as Ne,traceStartupPhaseSync as Pe}from"@x-otto/shared";import{BUILD_ID as Fe,OTTO_HOME as Ie,OTTO_SESSIONS_DIR as Le,SDK_VERSION as Re,flushEnvWarnings as ze,isShadowModeEnabled as Be,loadUserIdentity as Ve}from"@x-otto/env";import{dirname as He,join as Z,resolve as Ue}from"node:path";import{existsSync as We}from"node:fs";import{fileURLToPath as Ge}from"node:url";import{BASH_HISTFILE_SOURCE as Ke,COMPACTING_SENTINEL as qe,FISH_HISTFILE_SOURCE as Je,ZSH_HISTFILE_SOURCE as Ye,createBuiltinThemeRegistry as Xe,entriesToCommands as Ze,formatAgentDiagnosticsText as Qe,formatTranscriptText as $e,formatTurnTimeline as et,i18next as Q,isUsingOverage as tt,observationLiveFields as nt,observationRow as rt,parseBashHistory as it,parseFishHistory as at,parseZshHistory as ot,promptParentWorkspaceChoice as st,promptWorkspaceTrust as ct,setMarkdownThemeUserOverrides as lt,subagentEntryStatus as ut}from"@x-otto/tui";import{access as dt,mkdir as ft,readFile as pt,rename as mt,unlink as ht,writeFile as gt}from"node:fs/promises";import{createModelUsabilityGate as _t}from"@x-otto/ai";import{SESSION_RESUME_WINDOW_MESSAGES as vt,createProjectorState as yt,projectSessionEvent as bt,resolveChoiceAnswer as xt,resolveTextAnswer as St,sandboxBypassCommand as Ct,shouldShowPulseSurvey as wt}from"@x-otto/session-contract";import{ScheduleRegistry as Tt,SchedulerService as Et,createLocalFireOwnership as Dt,createRemoteFireOwnership as Ot,createRemoteScheduleStore as kt,createScheduleStore as At,parseCron as jt}from"@x-otto/schedule";function Mt(e=process.stdout){if(process.env.OTTO_TUI_SCOPED_VIEWPORT===`0`&&process.env.OTTO_TUI_CLEAR_ON_EXIT!==`0`&&e.isTTY)try{e.write(`\x1B[2J\x1B[3J\x1B[H`)}catch{}}async function Nt(e,t){let n=e;for(;n.type===`response`&&n.endReason===`max-tool-turns`&&n.notice;){if(!await t.askBudgetContinue()){t.onBudgetStopped();return}t.beforeContinuationTurn();let e=await t.runTurn(`Continue with the remaining work until the task is complete.`);if(t.onTurnResult(e)===`exit`)return;n=e}}function Pt(e,t){return e||t}function Ft(e){let t=[],n=0,r=``,i=()=>{r&&=(t.push(r),``)};for(;n<e.length;){let t=e[n];if(t===` `||t===` `){i(),n++;continue}if(t===`\\`){n++,n<e.length&&(r+=e[n]),n++;continue}if(t===`"`){n++;let t=It(e,n,`"`);r+=t.value,n=t.next;continue}if(t===`'`){n++;let t=It(e,n,`'`,!1);r+=t.value,n=t.next;continue}r+=t,n++}return i(),{tokens:t}}function It(e,t,n,r=!0){let i=``,a=t;for(;a<e.length;){let t=e[a];if(r&&t===`\\`){a++,a<e.length&&(i+=e[a]),a++;continue}if(t===n)return a++,{value:i,next:a};i+=t,a++}return{value:i,next:a}}function Lt(e){let t=e.trim();if(!t.startsWith(`/`)||t===`/`||t.startsWith(`//`))return{isCommand:!1,text:t};let{tokens:n}=Ft(t.slice(1));if(n.length===0)return{isCommand:!1,text:t};let[r,...i]=n;return{isCommand:!0,command:r,args:i}}function Rt(e,t){return e===`pin`&&t?`unpin`:e}function zt(e,t){return e===`pause`&&t?`continue`:e}function Bt(e,t,n){let r=e.list().sort((e,t)=>e.name.localeCompare(t.name)),i=r.map(e=>` /${Rt(e.name,t)}${e.aliases?.length?` (${e.aliases.join(`, `)})`:``}`),a=Math.max(...i.map(e=>e.length)),o=[];for(let e=0;e<r.length;e++){let s=r[e],c=n[Rt(s.name,t)]??n[s.name]??s.description;o.push(`${i[e].padEnd(a)} — ${c}`)}return o.push(``,`Prefixes: !<cmd> run shell | @<file> read file`),o}function Vt(e,t,n,r,i=!1,a=!1){return e.list().filter(e=>e.name===`pause`?t||a:!0).map(e=>{let o=zt(Rt(e.name,i),a);return{name:o,description:r?.[o]??r?.[e.name]??e.description,disabled:t&&!n.has(e.name)&&e.name!==`abort`,sortKey:e.name}})}function Ht(e){for(let t of E)t.tuiHidden||t.envGate&&process.env[t.envGate]!==`1`||(e.has(t.name)&&e.unregister(t.name),e.register({name:t.name,description:t.description??t.name,aliases:t.aliases,type:`action`,source:`builtin`,execute:()=>``}))}var Ut=class{estimate;intervalMs;now;text=``;measuredTokens=0;measuredChars=0;measuredAt=-1/0;constructor(e){this.estimate=e.estimate,this.intervalMs=e.intervalMs??250,this.now=e.now??(()=>Date.now())}reset(){this.text=``,this.measuredTokens=0,this.measuredChars=0,this.measuredAt=-1/0}push(e){if(!e)return;this.text+=e;let t=this.now();t-this.measuredAt>=this.intervalMs&&this.measure(t)}flush(){this.measure(this.now())}tokens(){let e=this.text.length-this.measuredChars;if(e<=0)return this.measuredTokens;let t=this.measuredChars>0?this.measuredTokens/this.measuredChars:.25;return this.measuredTokens+Math.ceil(e*t)}measure(e){this.measuredTokens=this.text?this.estimate(this.text):0,this.measuredChars=this.text.length,this.measuredAt=e}};function Wt(e,t){if(/^(bash|shell|run_command|execute|exec)$/i.test(e)){let e=t?.command;if(e)return e}return JSON.stringify(t??{}).slice(0,300)}async function Gt(e,t){let n=[`● ${t.header} — ${t.askedBy} asks:`,t.background?`\n${t.background}`:``,Q.t(`cmd.grillRecommendation`,{rec:t.recommendation}),t.evidence?.length?Q.t(`cmd.grillEvidence`,{joined:t.evidence.map(e=>` · ${e}`).join(`
3
3
  `)}):``].join(``);e.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:n}]});let r=t.options??[];if(r.length>0){if(r.length<=2&&!t.multiSelect&&t.allowFreeform===!1){let n=await new Promise(n=>{e.modal.openModal({kind:`confirm`,title:t.question,message:r.map(e=>`${e.label}${e.recommended?` (recommended)`:``}: ${e.rationale}`).join(`
4
4
  `),confirmLabel:r[0]?.label??Q.t(`cmd.grillOptionYes`),cancelLabel:r[1]?.label??Q.t(`cmd.grillOptionNo`),onConfirm:()=>n(!0),onCancel:()=>n(!1)})})?r[0]?.label:r[1]?.label;return xt(t,n?[n]:[])}let n=await e.modal.openModal({kind:`questions`,title:t.question,questions:[{header:t.header,question:t.question,multiSelect:!!t.multiSelect,freeformInput:t.allowFreeform!==!1,freeformPlaceholder:Q.t(`cmd.grillFreeformPlaceholder`),options:r.map(e=>({label:e.recommended?`${e.label} ★`:e.label,description:e.rationale}))}]});return xt(t,(n?.answers?.[t.header]??[]).map(e=>e.replace(/\s*★$/,``)),n?.freeformText)}return St(t,await e.modal.openModal({kind:`input`,title:t.header,description:[t.question],placeholder:Q.t(`cmd.grillAnswerPlaceholder`)}))}function Kt(t){let{getSession:n,app:r,tui:i,projState:a,redState:o,recomputeBudget:c,persistEditedFiles:l,persistSubagents:u,persistTurnCount:d,onContextCompacted:f,markStreamed:p}=t,h=null,g=!1,_=!1,v=null,y=null,b=e=>{let t=n(),i=t.session.getTurnCount();w({traceStore:r.storage.traceStore,sessionId:t.id,...i===void 0?{}:{turn:i}},e,`session-event`)},x=e=>{n().session.append({role:`system`,subtype:e,content:e,level:`info`,timestamp:Date.now()})},ee=!1,S,te={currentModel:()=>n().model.id,cacheHitRatio:()=>n().getLastCacheHitRatio(),turnTokens:()=>{let e=n().session.messages(),t=0;for(let n of e)n.role===`assistant`&&n.usage&&(t+=(n.usage.inputTokens??0)+(n.usage.outputTokens??0)+(n.usage.cacheReadTokens??0)+(n.usage.cacheWriteTokens??0));let r=S;if(S=t,!(r==null||t<=r))return t-r}},C,ne=!1,T=0,E=0,D=0,re=new Ut({estimate:s}),ie=()=>{E=0,D=0,T=0,re.reset()},O=()=>{c(E+D+re.tokens())},ae=0,k={},A=e=>{let t=0,n=0;for(let r of e.split(`
5
5
  `))r.startsWith(`+`)&&!r.startsWith(`+++`)?t++:r.startsWith(`-`)&&!r.startsWith(`---`)&&n++;return`+${t}/-${n}`},j=()=>{let e=U.listForSession(n().id).map(e=>({id:e.id,command:e.command,type:`process`,origin:`main`,status:e.status===`running`?`running`:e.status===`exited`?`exited`:`killed`,port:e.port,startedAt:e.startedAt,exitCode:e.exitCode,detectedService:e.detectedService})),t=new Map(H.list().map(e=>[e.id,e])),r=e=>{let n=t.get(e);return n?nt(n):{}},a=V.listForSession(n().id).map(e=>({id:e.id,command:e.title,type:`agent-session`,origin:e.origin,status:e.status===`running`||e.status===`ready`||e.status===`needs_input`?`running`:e.status===`applied`?`exited`:e.status===`failed`?`failed`:`killed`,agentStatus:e.status,diffStat:e.diff?A(e.diff):void 0,startedAt:e.startedAt,...r(e.id)})),o=new Set(a.map(e=>e.id)),s=H.list().filter(e=>!o.has(e.id)).map(rt),c=[...e,...a,...s];i.stores.tasks.setBackgroundTasks([...c.filter(e=>e.origin===`user`),...c.filter(e=>e.origin!==`user`)])},M=null,N=()=>{M===null&&(M=setTimeout(()=>{M=null,j()},30))},oe=()=>{M!==null&&(clearTimeout(M),M=null),j()},se=[U.onSpawn(N),U.onExit(oe),V.onSpawn(N),V.onUpdate(N),V.onExit(oe),V.onRemove(oe),H.subscribe(N)];j();let ce;return{bgUnsubs:se,attachSessionHandler:()=>{ce?.(),g=!1,ce=n().subscribe(t=>{for(let s of bt(t,a,te)){if(s.kind===`prompt.end`){let e=m(s,o),t={turn:a.currentTurn,completedAt:Date.now(),...e},r=n().session.getTurnSummaries()??[];n().session.setTurnSummaries([...r.filter(e=>e.turn!==t.turn),t])}e(s,{pushMessage:i.messages.pushMessage,echoUserInput:i.messages.echoUserInput,pushEngineEvent:i.engine.pushEngineEvent,getNotifyStats:i.info.getNotifyStats,setTasks:(e,t)=>i.stores.tasks.setTasks(e,t),addTurnBoundary:e=>i.stores.tasks.addTurnBoundary(e)},o),s.kind===`tasks.update`&&(n().session.setTodoList(a.todoList),r.sessionManager.save(n().id).catch(()=>{}))}if(t.type===`stream.event`&&t.event?.type===`text_delta`){p();let e=t.event?.delta??``;T+=e.length,re.push(e),i.engine.pushEngineEvent({kind:`outputTokensThisTurn`,n:Math.floor(T/4)}),O()}if(t.type===`stream.event`&&t.event?.type===`done`){let e=t.event?.providerUsage;if(e!==void 0){let t=e!==null&&tt(e.status,e.overageStatus);if(e===null||e.status===`rejected`&&!t)i.stores.notification.setProviderUsage(null),h=null;else{let t=n().model.provider;r.authStore.getAuthSource(t).then(r=>{if(n().model.provider!==t)return;let a=r===`oauth`?e:null;i.stores.notification.setProviderUsage(a),h=a}).catch(()=>{})}}}switch(t.type){case`turn.start`:T=0,re.reset(),O(),i.engine.pushEngineEvent({kind:`spinnerMode`,mode:`requesting`});break;case`turn.end`:ie(),c();break;case`streaming.start`:i.engine.pushEngineEvent({kind:`spinnerMode`,mode:`responding`}),i.pending.clearPendingEcho();break;case`streaming.end`:i.engine.pushEngineEvent({kind:`spinnerMode`,mode:null}),i.pending.clearPendingEcho();break;case`prompt.start`:ie(),E=s(t.text),O(),i.info.setTopView({session:n().id}),i.panes.clearEditedFiles(),i.plugins.clearSubagents(),ae=o.messageIndex,i.info.addContextTurn({turnIndex:a.currentTurn,role:`assistant`,messageCount:0,estimatedTokens:0,compacted:!1,truncated:!1,pruned:!1});break;case`compaction.start`:C=t.messageCount,i.engine.pushEngineEvent({kind:`activeTool`,name:qe});break;case`compaction.end`:{let e=C??t.retainedCount,n=t.retainedCount;i.engine.pushEngineEvent({kind:`activeTool`,name:null}),n<e&&(i.messages.pushMessage({role:`compact_boundary`,before:e,after:n}),i.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`compact`,before:e,after:n,summary:t.summary}),f()),C=void 0,c(void 0,{before:e,after:n});break}case`compaction.reactive.notice`:{let{messagesBefore:e,messagesAfter:n}=t;n<e&&(i.messages.pushMessage({role:`compact_boundary`,before:e,after:n}),i.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`compact`,before:e,after:n,summary:t.summary}),f()),c(void 0,{before:e,after:n});break}case`image.degradation.notice`:t.degradedCount>0&&i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.imageDegradationNotice`,{count:t.degradedCount,context:t.trigger===`image-constraint`?`image-constraint`:`other`}));break;case`session.history-capped`:i.messages.pushMessage({role:`history_capped`,removedCount:t.removedCount,trigger:t.trigger,...t.lossy?{lossy:!0}:{}}),i.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`history_capped`,removedCount:t.removedCount});break;case`session.write-lease-denied`:g=!0,i.messages.pushMessage({role:`write_lease_denied`}),i.info.showToast(Q.t(`lease.deniedToastTitle`),Q.t(`lease.deniedToastBody`));break;case`session.write-lease-restored`:g=!1,i.messages.pushMessage({role:`write_lease_restored`}),i.info.showToast(Q.t(`lease.restoredToastTitle`),Q.t(`lease.restoredToastBody`));break;case`session.crash-gap-detected`:i.info.showToast(Q.t(`crashGap.toastTitle`),Q.t(`crashGap.toastBody`,{lostTurns:t.lostTurns}));break;case`run.pause_requested`:_=!0,v={at:Date.now(),toolCount:0},b(`requested`),i.engine.setPauseDialog?.({phase:`requested`,requestedAt:Date.now(),toolCount:0,onCancel:()=>{},onDismiss:()=>{i.engine.setPauseDialog?.(null)}}),y&&clearInterval(y),y=setInterval(()=>{if(!v){clearInterval(y),y=null;return}let e=Math.floor((Date.now()-v.at)/1e3);i.stores.notification.setPausePending({elapsedSec:e,toolCount:v.toolCount})},1e3);break;case`tool.call.end`:{let e=typeof t.resultTokensEstimate==`number`?t.resultTokensEstimate:t.resultText?s(t.resultText):0;e>0&&(D+=e,O()),v&&(v.toolCount++,i.engine.setPauseDialog?.({phase:`requested`,requestedAt:v.at,toolCount:v.toolCount,onCancel:()=>{},onDismiss:()=>{i.engine.setPauseDialog?.(null)}})),(async()=>{try{let e={role:`tool_result`,name:t.toolCall.name,toolCallId:t.toolCall.id,content:[{type:`text`,text:t.resultText??``}],details:t.details},n=await r.resolveA2uiRendererPayload(e);n&&n.length>0&&i.messages.pushMessage({role:`assistant`,content:[{type:`a2ui`,components:n}]})}catch{}})();break}case`run.paused`:b(`paused`),v?(i.engine.setPauseDialog?.({phase:`active`,requestedAt:v.at,toolCount:v.toolCount,totalToolCount:v.toolCount}),i.messages.pushMessage({role:`run_paused`,toolCount:v.toolCount}),x(`run_paused`),y&&=(clearInterval(y),null),i.stores.notification.setPausePending(null),v=null):(i.messages.pushMessage({role:`run_paused`}),x(`run_paused`)),i.stores.notification.setPaused(!0);break;case`run.pause_cancelled`:b(`cancelled`),i.engine.setPauseDialog?.(null),i.messages.pushMessage({role:`run.pause_cancelled`}),x(`run_pause_cancelled`),y&&=(clearInterval(y),null),i.stores.notification.setPausePending(null),v=null,_=!1;break;case`run.resumed`:b(`resumed`),i.engine.setPauseDialog?.(null),i.messages.pushMessage({role:`run_resumed`}),x(`run_resumed`),y&&=(clearInterval(y),null),i.stores.notification.setPausePending(null),v=null,_=!1,i.stores.notification.setPaused(!1);break;case`steer.consumed`:i.pending.commitPendingSteer(t.id);break;case`image.vision-delegate`:!ee&&t.describedCount>0&&(ee=!0,i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`model.visionDelegateToast`,{count:t.describedCount})));break;case`memory.pruned`:ne||(ne=!0,i.messages.pushMessage({role:`prune_boundary`})),i.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`prune`,tokensSaved:t.tokensSaved,prunedCount:t.prunedCount}),c();break;case`error`:l(),u(),i.pending.withdrawPendingEcho();break;case`prompt.continued`:i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.todoGateContinuing`,{round:t.round,cap:t.maxRounds,left:t.incompleteCount}));break;case`prompt.budget.notice`:t.steered&&i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.promptBudgetExceeded`,{context:t.dimension,used:t.used,budget:t.budget}));break;case`budget.notice`:t.extended?i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.budgetExtended`,{maxTurns:t.maxTurns})):t.steered&&i.info.showToast(Q.t(`cmd.titleInfo`),t.progressDenied?Q.t(`cmd.budgetProgressDenied`):Q.t(`cmd.budgetSteered`,{maxTurns:t.maxTurns}));break;case`progress.stall.notice`:i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.progressStallDetected`,{maxRepeat:t.maxRepeat}));break;case`tool.call.mismatch.notice`:t.outcome===`retry`?i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.toolCallMismatchRetry`,{retryCount:t.retryCount})):i.info.showToast(Q.t(`cmd.titleError`),Q.t(`cmd.toolCallMismatchTerminated`));break;case`session.cost-budget-exceeded`:i.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.sessionCostBudgetExceeded`,{used:t.totalCostUSD.toFixed(2),budget:t.budgetUSD.toFixed(2)}));break;case`prompt.end`:ie(),i.pending.clearPendingSteers(),c(),i.info.markContextTurns({turnIndex:a.currentTurn,messageCount:Math.max(0,o.messageIndex-ae)}),l(),u(),d();{let e=n(),t=De(e.session.metadata().title,e.session.messages(),e.id);i.stores.tasks.setSessionTitle(t),i.lifecycle.setTerminalTitle(t)}if(process.env.OTTO_TUI_DEBUG_NOTIFY_STATS){let e=i.info.getNotifyStats();if(e.coalescedCalls>0){let t=(e.coalescedCalls/Math.max(1,e.coalescedFires)).toFixed(1);console.error(`\x1b[90m\x1b[2m[perf] notify merge ${e.coalescedCalls}→${e.coalescedFires} (${t}x) direct ${e.immediateCalls} flush ${e.flushFires}\x1b[0m`)}}{let e=r.settings.get(`pulse_survey`);r.feedbackRegistry.get()!==void 0&&wt(a.currentTurn,{enabled:e?.enabled??!0,probability:e?.probability??.05,minTurnGap:e?.min_turn_gap??20,forcedUpgradeActive:i.info.isForcedUpgradeActive()},k)&&(k.lastShownTurn=a.currentTurn,i.stores.notification.setPulseSurvey({phase:`rating`,rating:null,selectedIndex:0,commentText:``,commentOffset:0,onSubmit:(e,t)=>{r.feedbackRegistry.get()?.recordPulseSurvey?.({ts:Date.now(),rating:e,comment:t,sdkVersion:Re,modelId:n().model?.id})},onClose:()=>i.stores.notification.setPulseSurvey(null)}))}break;case`ask.user.required`:{let e=t.question,a=t.requestId;(async()=>{let o=r.inquiryCenter;if(!o.enqueue({id:a,origin:{kind:`session`,sessionId:t.sessionId},question:e}).accepted){n().resolveAskUser(a,{answer:``,acceptedRecommendation:!1,resolvedBy:`human`});return}if(!await o.waitForTurn(a)){n().resolveAskUser(a,{answer:``,acceptedRecommendation:!1,resolvedBy:`human`});return}try{let t=await Gt(i,e);n().resolveAskUser(a,t)}finally{o.release(a)}})();break}case`approval.required`:{let e=t.toolName===`bash`&&typeof t.arguments?.command==`string`?t.arguments.command:``,a=e?r.bashAlwaysAllowPrefix(e):null;i.modal.requestPermission({tool:t.toolName,input:Wt(t.toolName,t.arguments),risk:t.risk??`medium`,description:t.description,alwaysAllowLabel:a??void 0}).then(e=>{let i=Ct(t.description,t.arguments,z);e.approved&&i&&r.approveSandboxBypass(i),n().resolveApproval(t.id,e.approved),e.approved&&e.mode===`always`&&(t.toolName===`bash`?a&&r.allowToolAlways(`bash(${a})`,n().id):r.allowToolAlways(t.toolName,n().id))});break}}})},getSessionUnsub:()=>ce,getLastProviderUsage:()=>h,isWriteLeaseReadOnly:()=>g,isRunPaused:()=>_}}function qt(e){let t=new Map;if(e?.role===`assistant`&&Array.isArray(e.content))for(let n of e.content)n.type===`tool_call`&&t.set(n.id,n);return t}async function Jt(e,t,n){let r,i=new Set,a=new Map,o=new Set,s=new Map;if(n){let n=await e.loadTailEntries(t,vt);r=n.length>0?n[0].seq:0;for(let e of n)e.type===`message`&&i.add(e.seq)}else r=await e.getEntryCount(t);return{async loadEarlier(n=500){if(r<=0)return null;let c=await e.loadEntriesBefore(t,r,n);if(c.length===0)return null;let l=new Map,u=new Set;for(let e of c){if(e.type!==`message`)continue;let t=e.data;if(t?.role===`assistant`)for(let[e,n]of qt(t))l.set(e,n);else t?.role===`tool_result`&&typeof t.toolCallId==`string`&&u.add(t.toolCallId)}let d=[],m=(e,t)=>({...e,id:`hist-${t}`,seq:t});for(let e of c){if(e.type===`clear`){r=0,d.length=0;continue}if(e.type!==`message`||i.has(e.seq))continue;let t=e.data;if(!t||typeof t.role!=`string`||t.internal)continue;if(t.role===`tool_result`){let n=a.get(t.toolCallId??``)??l.get(t.toolCallId??``);if(n){let r=n.arguments??{};d.push(m({role:`tool`,name:t.toolName||n.name||`tool`,args:f(r),argsObj:r,result:p(t.content),isError:t.isError},e.seq)),o.add(t.toolCallId)}else s.set(t.toolCallId,{toolName:t.toolName,content:t.content,isError:t.isError});continue}if(t.role===`assistant`){let n=qt(t);if(n.size>0){let r=new Set([...u,...o,...s.keys()]),i=D([t],{resolvedIds:r});for(let t of i)d.push(m(t,e.seq));for(let[t,r]of n){if(u.has(t))continue;let n=s.get(t);if(n){s.delete(t);let i=r.arguments??{};d.push(m({role:`tool`,name:r.name,args:f(i),argsObj:i,result:p(n.content),isError:n.isError??!1},e.seq))}}continue}}let n=D([t]);for(let t of n)d.push(m(t,e.seq))}for(let[e,t]of l)a.set(e,t);return r>0&&(r=c[0].seq),d.length>0?d:null}}}const Yt=[`approaching`,`nearing`,`critical`],Xt={maxReminders:{approaching:1,nearing:3,critical:1},backoffBaseTurns:4,resetMarginPct:10,approachingMarginPct:10};function $(){return{count:0,lastRemindedTurn:void 0,peakPct:0,active:!1}}function Zt(e,t,n,r){return e>=n?`critical`:e>=t?`nearing`:e>=t-r?`approaching`:null}function Qt(e,t,n,r){return e===`critical`?n:e===`nearing`?t:t-r}function $t(e,t){return t<=1?0:e.backoffBaseTurns*2**(t-2)}var en=class{config;zones;suppressed=!1;constructor(e={}){this.config={...Xt,...e},this.zones={approaching:$(),nearing:$(),critical:$()}}check(e){if(this.suppressed)return null;let{contextPercent:t,pruneLinePct:n,compactLinePct:r,currentTurn:i}=e,a=Zt(t,n,r,this.config.approachingMarginPct);for(let e of Yt)e!==a&&this.zones[e].active&&t<Qt(e,n,r,this.config.approachingMarginPct)-this.config.resetMarginPct&&(this.zones[e]=$());if(a===null)return null;let o=this.zones[a];o.lastRemindedTurn!==void 0&&i<o.lastRemindedTurn&&(this.zones[a]=$());let s=this.zones[a];s.active=!0,s.peakPct=Math.max(s.peakPct,t);let c=this.config.maxReminders[a];if(s.count>=c)return null;let l=s.count+1;if(s.lastRemindedTurn!==void 0){let e=$t(this.config,l);if(i-s.lastRemindedTurn<e)return null}return s.count=l,s.lastRemindedTurn=i,{zone:a,pct:Math.round(t)}}onCompacted(){this.zones={approaching:$(),nearing:$(),critical:$()}}suppress(){this.suppressed=!0}snapshot(){return{approaching:{count:this.zones.approaching.count,lastTurn:this.zones.approaching.lastRemindedTurn},nearing:{count:this.zones.nearing.count,lastTurn:this.zones.nearing.lastRemindedTurn},critical:{count:this.zones.critical.count,lastTurn:this.zones.critical.lastRemindedTurn}}}};function tn(e){let{getSession:t,app:n,tui:r,projState:i,contextWindow:a,currentModelId:o}=e,s,c=new en,l={approaching:e=>Q.t(`cmd.contextPressureApproaching`,{pct:e}),nearing:e=>Q.t(`cmd.contextPressureNearing`,{pct:e}),critical:e=>Q.t(`cmd.contextPressureCritical`,{pct:e})},u=()=>{let e=t(),n=e.session.messages(),r=0,i=0,a=0,o=0,s=!1,c=0,l=0;for(let e=n.length-1;e>=0;e--){let t=n[e]?.usage;t&&(s||=(r=t.inputTokens??0,i=t.outputTokens??0,a=t.cacheReadTokens??0,o=t.cacheWriteTokens??0,!0),n[e]?.role===`assistant`&&(c+=t.inputTokens??0,l+=t.outputTokens??0))}return{sessionId:e.session.id,lastIn:r,lastOut:i,lastCacheRead:a,lastCacheWrite:o,totIn:c,totOut:l,messageCount:n.length}},d=(e,d)=>{let f=e!==void 0,p=f&&s&&s.sessionId===t().session.id?s:u();s=p;let m=d?d.before:1,h=d?d.after/m:1,g=e=>h<1?Math.round(e*h):e,_=n.modelRegistry.find(o.value??``)?.cost,v=_?p.totIn*(_.input??0)+p.totOut*(_.output??0):0,y=b({systemPrompt:t().systemPrompt,tools:t().tools,lastIn:g(p.lastIn),lastOut:g(p.lastOut),lastCacheRead:g(p.lastCacheRead),lastCacheWrite:g(p.lastCacheWrite),contextWindow:a.value,modelName:t().model?.name??``,totIn:p.totIn,totOut:p.totOut,cost:v>0?v:void 0,messageCount:p.messageCount,streamingOutputTokens:e});if(r.stores.budget.setBudget(y),r.stores.context.setBudget(y),!f&&y.contextWindow>0){let e=y.pruneLine/y.contextWindow*100,t=y.compactLine/y.contextWindow*100,n=c.check({contextPercent:y.contextPercent,pruneLinePct:e,compactLinePct:t,currentTurn:i.currentTurn});n&&r.info.pushNotification(Q.t(`cmd.titleContextPressure`),l[n.zone](n.pct),`system`,n.zone===`critical`?`warning`:`info`)}},f=()=>{try{t().session.setEditedFiles(r.messages.getEditedFiles().map(e=>({path:e.path,operation:e.operation,addedLines:e.addedLines,removedLines:e.removedLines,timestamp:e.timestamp,toolCallId:e.toolCallId}))),n.sessionManager.save(t().id).catch(()=>{})}catch(e){console.error(`\x1b[90m\x1b[2m[persist] editedFiles skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}};return{recomputeBudget:d,persistEditedFiles:f,persistSubagents:()=>{try{let e=[...r.plugins.getSubagents().values()].map(e=>({id:e.id,name:e.command||e.id,status:ut(e),startedAt:e.startedAt}));t().session.setSubagents(e),n.sessionManager.save(t().id).catch(()=>{})}catch(e){console.error(`\x1b[90m\x1b[2m[persist] subagents skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}},persistTurnCount:()=>{try{t().session.setTurnCount(i.currentTurn)}catch(e){console.error(`\x1b[90m\x1b[2m[persist] turnCount skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}},editFileCallback:e=>{try{r.stores.tasks.addEditedFile({path:e.path,operation:e.operation,oldContent:e.oldContent,newContent:e.newContent,addedLines:e.addedLines,removedLines:e.removedLines,timestamp:e.timestamp,toolCallId:e.toolCallId})}catch(e){console.error(`\x1b[90m\x1b[2m[panel] addEditedFile skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}f()},onContextCompacted:()=>{c.onCompacted()}}}function nn(e){let{app:t,getTui:n}=e,r=[],i=()=>{for(let e of r)e();r=[]},a,o,s,c,l,u=()=>{a&&=(clearInterval(a),void 0),o&&=(V.retain(o,!1),void 0),l=void 0},d=()=>{s&&=(clearInterval(s),void 0),c&&=(H?.unpin(c),V.get(c)&&V.retain(c,!1),void 0)};return{clearBgSubs:i,stopBgOutputPoll:u,stopBgSubagentPoll:d,setBgUnsubs:e=>{r=e},handlers:{onBackgroundKill:e=>{if(V.get(e)){V.cancel(e);return}H.abort(e)||U.kill(e)},onBackgroundApply:e=>{let r=n(),i=e=>r.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:e}]}),a=t.agentJobs.apply(e);if(a.applied){let n=a.forbiddenZone?.length?Q.t(`cmd.bgForbiddenZone`,{count:a.forbiddenZone.length,files:a.forbiddenZone.join(`
@@ -13,7 +13,7 @@ import{A as e,B as t,C as n,D as r,E as i,F as a,G as o,H as s,I as c,J as l,K a
13
13
  `).trim(),modelIds:n}}function sn(e){let{modelReady:t,currentModelId:n,contextWindow:r,tuiRef:i,pushBudgetNow:a,app:o,getSession:s,options:c,fmtDisplayModel:l,onEngineModelAction:u}=e;return async(e,d)=>{let f=s(),p=f.model?.id;c.value&&(c.value.model=e),n.value=e;let m=o.modelRegistry.find(e);if(m&&m.id===`__otto_setup__`)return`Model "${e}" is a setup placeholder — pick a real model with /model first.`;if(d?.persist!==!1)try{let t={model:e},n=o.settings.get(`model_slots`);n&&(t.model_slots={...n,default:e}),m&&(t.recent_models=an(o.settings.get(`recent_models`)??[],e)),await o.settings.persist(t)}catch{}if(m){if(f.model=m,t.value=!0,e!==p&&(o.syncSessionToolsFor(f.id),C({tui:i.value??{messages:{pushMessage:()=>{}}},session:f,traceStore:o.storage.traceStore},{from:p,to:m.id,label:rn(m.id,m.contextWindow,f.thinkingLevel)})),m.api.includes(`:`)&&o.firePluginActivationEvent?.(`onProvider:${m.api}`),u?.({kind:`setModel`,modelId:e}),i.value?.stores.tasks.setModelName(rn(m.id,m.contextWindow,f.thinkingLevel)),i.value?.engine.pushEngineEvent({kind:`maxOutputTokens`,n:m.maxOutputTokens}),o.authStore?.getAuthSource?o.authStore.getAuthSource(m.provider).then(e=>{e!==`oauth`&&i.value?.stores.notification.setProviderUsage(null)}).catch(()=>{i.value?.stores.notification.setProviderUsage(null)}):i.value?.stores.notification.setProviderUsage(null),e!==p&&o.storage.memory?.reconfigure){o.storage.memory.reconfigure({contextWindow:m.contextWindow,maxOutput:m.maxOutputTokens});try{let e=f.session.buildContext(),t=await o.storage.memory.ensureFitsWindow?.(e.messages,f.id);if(t?.compacted&&t.summary&&t.replacement){f.session.recordCompaction(t.summary,t.replacement),u?.({kind:`recordCompaction`,summary:t.summary,replacement:t.replacement});let e=m.contextWindow>=1e6?`${(m.contextWindow/1e6).toFixed(1)}M`:`${Math.round(m.contextWindow/1e3)}k`;i.value?.info.showToast(Q.t(`cmd.titleModel`),Q.t(`cmd.modelCompactedFor`,{window:e}))}}catch(e){console.error(`\x1b[3m\x1b[2m[model-switch] compaction skipped: ${e instanceof Error?e.message:String(e)}\x1b[0m`)}}return r.value=m.contextWindow,a.value?.(),e!==p&&!d?.silent&&i.value?.info.showToast(Q.t(`cmd.titleModel`),Q.t(`model.switchedTo`,{label:l(e)})),`Model → ${e} (active next turn).`}return f.model&&(i.value?.stores.tasks.setModelName(rn(f.model.id,f.model.contextWindow,f.thinkingLevel)),i.value?.engine.pushEngineEvent({kind:`maxOutputTokens`,n:f.model.maxOutputTokens})),`Model "${e}" not in registry — switch NOT applied (still ${f.model?.id??`unset`}). Check the id or /auth the provider.`}}function cn(e){let{getSession:t,app:n,tuiRef:r,options:i,fmtDisplayModel:a,applyModel:o}=e,s=!1,c=_t(n.authStore);return async()=>{if(s)return;s=!0;let l=t().model;if(!l)return;let u=async e=>{try{return(await c(e)).usable}catch{return!1}},d=async e=>{try{return await n.authStore.getAuthSource(e.provider)!==null}catch{return!1}},f=i.value?.model??n.settings.get(`model`);if(typeof f!=`string`||!f)return;let p=n.modelRegistry.find(f);if(p&&await d(p)){p.id!==l.id&&await o(p.id);return}let m=p?Q.t(`model.reasonUnauthenticated`,{provider:p.provider}):Q.t(`model.reasonNotFound`),h=l;if(!await d(l)){let e=n.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`),t;for(let n of e)if(await u(n)){t=n;break}t??=e[0],t&&(h=t)}let g=h.id;r.value?.modal.openModal({kind:`confirm`,title:Q.t(`model.title`),message:[`${a(f)} → ${a(h.id)}`,``,m,``,Q.t(`model.hint`)],confirmLabel:Q.t(`model.permanent`),extraLabel:Q.t(`model.login`),cancelLabel:Q.t(`model.dismiss`),onConfirm:()=>{o(g,{persist:!0})},onExtra:()=>{e.onLogin&&p?.provider?e.onLogin(p.provider):r.value?.info.showToast(Q.t(`model.login`),Q.t(`model.fallbackLoginToast`,{provider:p?.provider??``}))},onCancel:()=>{e.onExitSession?.()}})}}const ln=Ae(`@x-otto/cli:theme-preset-wiring`);function un(e,t){let n={kind:`extension`,extensionId:t.pluginId};return e.register(n,{localId:t.localId,label:t.label,appearance:t.appearance,colors:t.colors,markdown:t.markdown})}function dn(e,t){let n=[];for(let r of t)try{n.push(un(e,r))}catch(e){ln.warn({pluginId:r.pluginId,localId:r.localId,err:String(e)},`theme preset registration failed, skipped`)}return n}function fn(e){let t=Xe();return dn(t,xe(e.activePlugins())),t}function pn(e){return e.startsWith(`backend/`)?e.slice(8):e}function mn(e){let t=()=>({tasks:e.list(),runningTaskIds:[...e.getRunningTaskIds()],isFireOwner:e.isFireOwner(),fireOwnerFailureReason:e.fireOwnerFailureReason()});return{call:async(n,r)=>{let i=pn(n);switch(i){case`schedule.list`:return t();case`schedule.add`:{let t=r,n=e.add({name:t.name,prompt:t.prompt,cronExpression:t.cronExpression,recurring:t.recurring,origin:`user`});return{ok:!0,taskId:n.id,name:n.name}}case`schedule.update`:{let t=r,n={};return t.name!==void 0&&(n.name=t.name),t.prompt!==void 0&&(n.prompt=t.prompt),t.cronExpression!==void 0&&(n.cronExpression=t.cronExpression),t.enabled!==void 0&&(n.enabled=t.enabled),{ok:e.update(t.taskId,n)}}case`schedule.runNow`:{let{taskId:t}=r;return e.runNow(t),{ok:!0}}case`schedule.toggle`:{let{taskId:t,enabled:n}=r;return{ok:e.update(t,{enabled:n})}}case`schedule.cancel`:{let{taskId:t}=r;return e.cancel(t)}case`schedule.remove`:{let{taskId:t}=r;return{ok:e.remove(t)}}case`schedule.readLogs`:{let{taskId:t,limit:n}=r;return{entries:e.readFireLogs(t,n??20)}}case`schedule.parseCron`:{let{expr:e}=r;try{return{ok:!0,next:jt(e).toISOString()}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}default:throw Error(`unknown schedule backend method: ${i}`)}},getSnapshot:t}}function hn(e,t,n,r){let i=e.workspaceRef?.key??`default`,a=new Tt,o,s;if(e.storage.remoteSessionConfigured&&r){let e=async()=>({token:r.sessionToken});o=kt({sessionUrl:r.sessionUrl,getAuth:e,wsKey:i}),s=Ot({sessionUrl:r.sessionUrl,wsKey:i,getAuth:e})}else o=At(i),s=Dt(i);let c=new Et({registry:a,store:o,ownership:s,jobRegistry:q,startJob:t=>({id:e.agentJobs.start({title:t.title,prompt:t.prompt,sessionId:t.sessionId,origin:t.origin}).id}),getSessionId:()=>t.value.id,notifySubscriber:(t,n)=>e.notifyPluginServiceSchedule({pluginId:t.pluginId,serviceId:t.serviceId},n),retryBackoffMs:e.getResilienceConfig().schedule.retryBackoffMs});c.start().catch(e=>{console.error(`\x1b[3m\x1b[2m[schedule] scheduler failed to start: ${e instanceof Error?e.message:String(e)}\x1b[0m`)}),se(c),e.setScheduleService(c);let l=mn(c);e.panelBackendController.registerInProcessBackend(`plugin-schedule`,l.call);let u=setInterval(()=>{if(!n)return;let e=c.list().map(e=>({id:e.id,name:e.name,prompt:e.prompt,cronExpression:e.cronExpression,enabled:e.enabled,recurring:e.recurring,nextFireAt:e.nextFireAt,lastFiredAt:e.lastFiredAt,lastFireFailed:e.lastFireFailed,lastFireError:e.lastFireError,lastFireCancelled:e.lastFireCancelled}));n.stores.tasks.setScheduleTasks(e)},5e3);return u.unref(),{pollInterval:u,scheduler:c}}function gn(e){let{tui:t,app:r,themeRegistry:i,sessionRef:a,interactiveRef:o,regRef:s,slashCommandsRef:c,modelReadyRef:l,currentModelIdRef:u,currentLangRef:d,projState:f,agentProcessingRef:p,modelsRef:m,availableModelIds:h,restartRequestedRef:g,applyModel:_,persistAvailable:v,refreshModelsNow:y,refreshSlashCommands:b,events:x,redState:ee,agentMessagesToChatMessages:S,PROVIDER_DISPLAY_NAMES:te,apiCredentialId:C,onContextCompacted:w}=e;return{tui:t,app:r,state:{get session(){return a.value},set session(e){a.value=e},get interactive(){return o.value},set interactive(e){o.value=e},get reg(){return s.value},set reg(e){s.value=e},get slashCommands(){return c.value},set slashCommands(e){c.value=e},get modelReady(){return l.value},set modelReady(e){l.value=e},get currentModelId(){return u.value},set currentModelId(e){u.value=e},get currentLang(){return d.value},set currentLang(e){d.value=e},get todoList(){return f.todoList},set todoList(e){f.todoList=e},get agentProcessing(){return p.value},set agentProcessing(e){p.value=e},get models(){return m.value},set models(e){m.value=e},get availableModelIds(){return h},get restartRequested(){return g.value},set restartRequested(e){g.value=!!e},themeRegistry:i},callbacks:{applyModel:_,persistAvailable:v,refreshModelsNow:y,registerAllTuiCommands:()=>{Ht(s.value)},refreshSlashCommands:b,attachSessionHandler:()=>x.attachSessionHandler(),restoreSwitchedSession:()=>{f.delegated.clear(),f.todoList=[],f.currentTurn=0,Object.assign(ee,re()),t.stores.tasks.setTasks([],void 0),t.panes.clearEditedFiles(),t.plugins.clearSubagents(),n({session:a.value,projState:f,tui:t}),w()},resetCurrentTurn:()=>{f.currentTurn=0},onContextCompacted:w,sessionUnsub:()=>x.getSessionUnsub(),getLastProviderUsage:()=>x.getLastProviderUsage(),isWriteLeaseReadOnly:()=>x.isWriteLeaseReadOnly(),isRunPaused:()=>x.isRunPaused(),agentMessagesToChatMessages:S,PROVIDER_DISPLAY_NAMES:te,apiCredentialId:C}}}function _n(e){e.setEcosystemSearch(async t=>{try{let{registries:n,warnings:r}=await ge(e).loadAll();return{hits:X(n.flatMap(e=>e.entries.map(t=>({entry:t,registry:e}))).map(e=>({text:e.entry.id,aliases:[e.entry.description,...e.entry.keywords??[]],payload:e})),t.join(` `),{maxResults:8}).map(e=>({id:e.item.payload.entry.id,description:e.item.payload.entry.description,capabilities:e.item.payload.entry.capabilities,sourceName:e.item.payload.registry.sourceName,stale:e.item.payload.registry.stale})),warnings:r}}catch{return}})}function vn(e){let{app:t,tui:n}=e;t.setMcpStartupCallback(e=>{let r=[`HTTP_PROXY`,`HTTPS_PROXY`,`http_proxy`,`https_proxy`].find(e=>process.env[e]),i=r?process.env[r]:void 0,a=t.settings.get(`proxy`);i&&r&&!a?.url&&(L(i,r),n.info.showToast(Q.t(`proxy.title`),Q.t(`proxy.envDetectedToast`,{source:r,value:i})))})}function yn(e){let{app:t,tui:n,session:r}=e;n.plugins.registerArgumentSuggester(`model`,(e,n=20)=>X(t.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`).map(e=>({text:e.id,aliases:[e.name,e.provider],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload.id,description:e.item.payload.name})));let i=De(r.session.metadata().title,r.session.messages(),r.id);n.lifecycle.setTerminalTitle(i),n.stores.tasks.setSessionTitle(i)}function bn(e){let{app:t,tui:n,getScheduler:r}=e;n.plugins.registerArgumentSuggester(`schedule`,(e,t=20)=>{let n=[`remove`,`run`,`enable`,`disable`],i=n.find(t=>e.toLowerCase().startsWith(`${t} `));if(!i)return X([...n,`list`,`add`,`logs`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:t}).map(e=>({name:e.item.payload}));let a=r();if(!a)return[];let o=e.slice(i.length+1);return X(a.list().map(e=>({text:e.id,aliases:[e.name],payload:e})),o,{maxResults:t}).map(e=>({name:`${i} ${e.item.payload.id}`,description:e.item.payload.name}))}),n.plugins.registerArgumentSuggester(`replay`,(e,n=20)=>X(t.listSessions().map(e=>({text:e.id,aliases:e.title?[e.title]:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload.id,description:e.item.payload.title??e.item.payload.id.slice(0,8)}))),n.plugins.registerArgumentSuggester(`session`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`unlock `)?e.slice(7):e;return r===e?X([{text:`unlock`,aliases:[],payload:`unlock`}],e,{maxResults:n}).map(e=>({name:e.item.payload,description:`Write-lease diagnostics/force-unlock`})):X(t.listSessions().map(e=>({text:e.id,aliases:e.title?[e.title]:[],payload:e})),r,{maxResults:n}).map(e=>({name:`unlock ${e.item.payload.id}`,description:e.item.payload.title??e.item.payload.id.slice(0,8)}))}),n.plugins.registerArgumentSuggester(`registry`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`remove `)?e.slice(7):e;return r===e?X([`list`,`add`,`remove`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload})):X(ge(t).listSources().filter(e=>!e.builtin).map(e=>({text:e.name,aliases:[e.url],payload:e})),r,{maxResults:n}).map(e=>({name:`remove ${e.item.payload.name}`,description:e.item.payload.url}))}),n.plugins.registerArgumentSuggester(`trust`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`plugin `)?e.slice(7):e;return r===e?X([`status`,`trust`,`untrust`,`plugin`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload})):X(I({cwd:t.workspaceDir??process.cwd(),homedir:R()}).map(e=>({text:e.id,aliases:[],payload:e})),r,{maxResults:n}).map(e=>({name:`plugin ${e.item.payload.id}`,description:e.item.payload.scope}))})}function xn(e){let t=e[e.length-1];if(t?.type===`message`&&t.message?.role===`user`)return{parentId:t.parentId}}function Sn(e,t){!t||!t.newer||(t.forced?(e.info.pushNotification(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateNotifForced`,{latest:t.latest,current:t.current}),`version`,`error`),e.stores.tasks.setForcedUpgrade(Q.t(`cmd.updateForcedBanner`,{latest:t.latest,current:t.current})),e.stores.notification.setPulseSurvey(null)):(e.info.pushNotification(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateNotifAvailable`,{latest:t.latest,current:t.current}),`version`,`info`),e.info.showToast(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateToast`,{latest:t.latest}))))}async function Cn(e){let{tui:t,options:n,app:r,session:i,projState:a,resumedNote:o,resumed:s,updateCheckPromise:c,bg:l,events:u}=e;if(o&&_({resumedNote:o,isFound:!!s,session:i,projState:a,tui:t}),n.resumePrompt&&s)if(r.memoryGovernor.sample().level===`critical`)t.info.showToast(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureResumeAbortedMessage`));else{let e=xn(i.session.branchEntries());e&&(e.parentId&&i.session.branch(e.parentId),i.prompt(n.resumePrompt).catch(e=>{r.logger.warn({err:e instanceof Error?e.message:String(e)},`[memory-governor] auto-resume prompt failed`),t.info.showToast(Q.t(`cmd.titleError`),Q.t(`cmd.memoryPressureResumeFailedMessage`))}))}c.then(e=>Sn(t,e)),l.setBgUnsubs(u.bgUnsubs),u.attachSessionHandler(),wn(t,r)}function wn(e,t){S(n=>{if(n.status!==`needs-input`)return;let r=n.id.slice(0,8),i=t.listSessions().find(e=>e.id===n.id)?.title??r;e.info.pushNotification(`session needs input`,`Background session '${i}' (${r}) requires your input (/resume ${r})`,`system`,`warning`)}),t.hookRegistry.on(`session.deleted`,`rfc234-background-cleanup`,e=>{F(e.sessionId)})}function Tn(e){let t=e??Ge(import.meta.url);t=He(t);let n=t===`/`?t:`/`;for(;t!==n;){try{if(We(t+`/.git`))return t}catch{}t=He(t)}try{if(We(n+`/.git`))return n}catch{}}var En=class{repoRoot;currentBuildId;checkIntervalMs;onStale;logger;lastNotifiedBuildId=void 0;disposed=!1;timer;activeChild;constructor(e){this.repoRoot=e.repoRoot,this.currentBuildId=e.currentBuildId,this.checkIntervalMs=e.checkIntervalMs??6e5,this.onStale=e.onStale,this.logger=e.logger}start(){this.disposed||this.scheduleNext()}dispose(){if(this.disposed=!0,this.timer&&=(clearTimeout(this.timer),void 0),this.activeChild){try{this.activeChild.kill()}catch{}this.activeChild=void 0}this.lastNotifiedBuildId=void 0}scheduleNext(){this.disposed||(this.timer=setTimeout(()=>{this.timer=void 0,this.performCheck().then(()=>{this.scheduleNext()})},this.checkIntervalMs),this.timer.unref())}performCheck(){return new Promise(e=>{if(this.disposed){e();return}let t=_e(`git`,[`rev-list`,`--count`,`HEAD`],{cwd:this.repoRoot,timeout:5e3},(t,n)=>{if(this.activeChild=void 0,t){this.logger?.warn({err:t instanceof Error?t.message:String(t)},`[stale-build-detector] git rev-list failed`),e();return}let r=n.trim(),i=parseInt(r,10);if(!Number.isFinite(i)){this.logger?.warn({raw:r},`[stale-build-detector] failed to parse git output as number`),e();return}if(i>this.currentBuildId&&i!==this.lastNotifiedBuildId){this.lastNotifiedBuildId=i;try{this.onStale?.(i)}catch(e){this.logger?.warn({err:e instanceof Error?e.message:String(e)},`[stale-build-detector] onStale callback threw`)}}e()});this.activeChild=t,t.on(`error`,()=>{this.activeChild=void 0})})}};function Dn(e){return e.trim().length===0}function On(e){let{tui:t,app:n,submitState:r}=e;return(e,i=`!!`)=>{let a=e.trim();if(!a)return;let o=Y(a);if(!o.safe){t.info.showToast(Q.t(`cmd.titleShell`),Q.t(`cmd.dangerousBlocked`,{reason:o.reason})),t.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`cmd.dangerousBlockedDetail`,{reason:o.reason,cmd:a})}]});return}t.messages.echoUserInput(`${i} ${a}`),t.shell.startShellExecution(a),r.shellChild=ve(a,{shell:!0,cwd:n.workspaceDir,stdio:[`ignore`,`pipe`,`pipe`],env:ke()}),Oe.registerChild({command:a,args:[],owner:{type:`cli-shell`,id:`!!`},category:`shell`,lifecycle:`evictable`,cwd:n.workspaceDir},r.shellChild),r.shellChild.stdout.on(`data`,e=>{t.shell.appendShellOutput(e.toString(`utf-8`))}),r.shellChild.stderr.on(`data`,e=>{t.shell.appendShellOutput(e.toString(`utf-8`))}),r.shellChild.on(`close`,(e,n)=>{r.shellChild=null,n?t.shell.finishShellExecution(null,void 0,!0):t.shell.finishShellExecution(e)}),r.shellChild.on(`error`,e=>{r.shellChild=null,t.shell.finishShellExecution(null,`\nError: ${e.message}`)})}}function kn(e){let{agentProcessingRef:t,tui:n,requestStop:r}=e;return(e,i)=>{let a=Lt(e);return a.isCommand&&a.command.toLowerCase()===`abort`&&i===`send`?(t.value?r(`abort`):n.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.noRunningTask`)),!0):!1}}function An(e){let{app:t,tui:n}=e;return async e=>{let r=e.trim();if(!r)return;if(!t.storage.autoMemory){n.info.showToast(Q.t(`cmd.titleMemory`),Q.t(`cmd.memoryDisabled`));return}let i=await le(r,process.env.OTTO_MEMORY_LLM_NAMING===`1`?t.completeText:void 0);await t.storage.autoMemory.record(i),n.messages.echoUserInput(`# ${r}`),n.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`cmd.memorySaved`,{name:i.name})}]})}}function jn(e){let t=e.terminated===!0?Q.t(`shell.askAiTerminated`):e.exitCode===null?Q.t(`shell.unknownError`):Q.t(`shell.exitCode`,{code:e.exitCode}),n=e.output.length>5e4?`${e.output.slice(0,5e4)}\n${Q.t(`shell.truncated`)}`:e.output;return Q.t(`shell.prompt`,{command:e.command,errorLabel:t,output:n})}function Mn(e,t,n){return e-t<50?`dedup`:n.shellRunning?`kill-shell`:n.busy?n.stopDialogOpen?`escalate-exit`:`open-stop-dialog`:n.idleCtrlCCount+1>=2?`exit-process`:`hint-exit`}function Nn(e){let{getTui:t,getSession:n,dispatchAbort:r,clearTodoLayers:i,markUserAborted:a,resetCtrlCCount:o,markRestartRequested:s,stopTui:c,isBusy:l}=e,u=null,d=()=>u!==null&&t()?.info.getCurrentPath()===`/dialog/confirm`,f=()=>{a(),o(),r(),i()},p=e=>{e&&s(),a(),o();try{r()}catch{}c()},m=e=>{if(e===`abort`)return{title:Q.t(`confirm.abortConfirmTitle`),message:Q.t(`confirm.abortConfirmMessage`),confirmLabel:Q.t(`common.abortButton`),extraLabel:Q.t(`common.pauseButton`),onConfirm:()=>{f(),t()?.info.showToast(Q.t(`cmd.titleAborted`),Q.t(`cmd.runAborted`))}};let n=e===`exit-restart`;return{title:n?Q.t(`confirm.exitRestartConfirmTitle`):Q.t(`confirm.exitConfirmTitle`),message:Q.t(`confirm.exitConfirmMessage`),confirmLabel:n?Q.t(`common.abortAndRestartButton`):Q.t(`common.abortAndExitButton`),extraLabel:void 0,onConfirm:()=>{p(n)}}},h=e=>{let r=t();if(!r)return;let i=m(e);u=e,r.modal.openModal({kind:`confirm`,title:i.title,message:i.message,confirmLabel:i.confirmLabel,confirmColor:`amber`,extraLabel:i.extraLabel,extraColor:`accent`,dangerous:!0,onConfirm:()=>{u=null,i.onConfirm()},onCancel:()=>{u=null},onExtra:i.extraLabel?()=>{u=null,n().pauseRun()?t()?.info.showToast(Q.t(`cmd.titlePaused`),Q.t(`cmd.runWillPauseAfterTurn`)):t()?.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.noRunningTaskToPause`))}:void 0})};return{requestStop:e=>{if(!t()){e===`abort`?f():p(e===`exit-restart`);return}if(e!==`abort`&&!l()){p(e===`exit-restart`);return}h(e)},isStopDialogOpen:d,escalateToExit:()=>{let e=t();!e||!d()||(h(`exit`),e.modal.resolveConfirm(!0))},abortNow:f}}async function Pn(e,t,n){if(n){let n=t.settings.get(`model`);if(typeof n==`string`&&n&&e.model?.id!==n){let r=t.modelRegistry.find(n);r&&await t.providerRegistry.hasCredential(r.provider)&&(e.model=r,t.storage.memory?.reconfigure?.({contextWindow:r.contextWindow,maxOutput:r.maxOutputTokens}))}}{let n=t.settings.get(`thinking_level`),r=[`low`,`medium`,`high`,`xhigh`,`max`],i=n===`minimal`?`low`:n;typeof i==`string`&&r.includes(i)&&(e.thinkingLevel=i)}}var Fn=class{entries=[];filePath;constructor(e,t=Z(Ie,`sessions`)){this.filePath=Z(t,`${e}.history.json`)}list(e){return this.entries.slice(-(e??100))}append(e){e.trim()&&(this.entries.push(e),this.entries.length>100&&(this.entries=this.entries.slice(-100)))}hydrate(e){this.entries=e.slice(-100)}async persist(){if(Be())return;let e=JSON.stringify(this.entries,null,2),t=`${this.filePath}.tmp`;try{await ft(He(this.filePath),{recursive:!0}),await gt(t,e,`utf-8`),await mt(t,this.filePath)}catch(e){throw await ht(t).catch(()=>{}),e}}async load(){try{let e=await pt(this.filePath,`utf-8`),t=JSON.parse(e);return Array.isArray(t)&&t.every(e=>typeof e==`string`)?(this.entries=t.slice(-100),this.entries):[]}catch{return[]}}};const In={[Ye]:e=>ot(e),[Ke]:e=>it(e),[Je]:e=>at(e)};function Ln(){let e=process.env.SHELL??``,t=R(),n=process.env.HISTFILE;return e.includes(`fish`)?[{id:Je,path:Z(t,`.local/share/fish/fish_history`)},{id:Je,path:Z(t,`.config/fish/fish_history`)}]:e.includes(`bash`)?[{id:Ke,path:n?.startsWith(`~`)?Z(t,n.slice(2)):n??Z(t,`.bash_history`)}]:e.includes(`zsh`)||!e?[{id:Ye,path:n?.startsWith(`~`)?Z(t,n.slice(2)):n??Z(t,`.zsh_history`)}]:[]}function Rn(e){let t=e?.sources?.filter(e=>e?.enabled!==!1&&!!e?.id&&!!e?.path);if(t&&t.length>0){let e=R();return t.map(t=>({id:t.id,path:zn(t.path,e)}))}return Ln()}function zn(e,t){return e.startsWith(`~/`)?Z(t,e.slice(2)):e===`~`?t:e}async function Bn(e){try{return await dt(e),!0}catch{return!1}}async function Vn(e,t){let n=In[e.id];if(!n||!await Bn(e.path))return[];try{return n(await pt(e.path,`utf8`)).slice(-t)}catch{return[]}}async function Hn(e){if(e?.enabled!==!0)return[];let t=e.maxEntries??2e3,n=Rn(e),r=new Set,i=[];for(let e of n){if(r.has(e.path))continue;r.add(e.path);let n=await Vn(e,t);i.push(...n)}return i.slice(-t)}async function Un(e,t){let n=new Fn(e.id);return{historyStore:n,inputHistory:await n.load().then(t=>{if(t.length>0)return t;let r=e.session.getInputHistory();return r&&r.length>0?(n.hydrate(r),n.persist().catch(()=>{}),e.session.setInputHistory([]),r):[]}),externalHistoryCommands:t?.enabled===!0?Ze(await Hn(t)):void 0}}function Wn(e){let t=(t,n)=>{e.onError?.(t,n)},n=async n=>{let r=e.gateway(),i=e.bridge();if(!(!r||!i))try{let e=await r.getPaste(n);i.hydratePaste({entries:e.entries,nextId:e.nextId})}catch(e){t(`load`,e);try{i.hydratePaste(null)}catch{}}},r=async n=>{let r=e.gateway(),i=e.bridge();if(!(!r||!i))try{let e=i.exportPaste();if(!e)return;await r.setPaste(n,{sessionId:n,entries:e.entries,nextId:e.nextId})}catch(e){t(`save`,e)}};return{load:n,save:r,async switchTo(e,t){e!==t&&(e!==void 0&&await r(e),await n(t))},async fork(n,r){let i=e.gateway(),a=e.bridge();if(!(!i||!a))try{let e=a.exportPaste()??await i.getPaste(n);await i.setPaste(r,{sessionId:r,entries:e.entries,nextId:e.nextId})}catch(e){t(`fork`,e)}}}}function Gn(e){let{session:t,tui:n,retryAccelerate:r,setRateLimitInfo:i,abortNow:a}=e;t.coreAgent.on(`stream.retry`,({attempt:e,maxRetries:t,delayMs:i,reason:o})=>{n.engine.showRetryDialog(e,t,i,r,()=>{n.engine.clearRetryDialog()},o,()=>{a()})}),t.coreAgent.on(`rate.limit.exhausted`,({limitType:e,resetsAt:t})=>{n.engine.clearRetryDialog(),i({limitType:e,resetsAt:t})}),t.coreAgent.on(`lifecycle.tool.completed.crossBoundary`,({toolName:e,result:t})=>{let r=Q.t(`cmd.titleBackgroundTask`),i=t.isError?Q.t(`cmd.lifecycleCrossBoundaryFailed`,{toolName:e}):Q.t(`cmd.lifecycleCrossBoundaryDone`,{toolName:e});n.info.showToast(r,i)})}function Kn(e,t){let n=e=>`${e.kind}\u0000${e.label}`,r=n(t);return[t,...e.filter(e=>n(e)!==r)].slice(0,5)}function qn(e){return{label:e.label,value:e.value,kind:e.kind,description:e.description}}function Jn(e){return e.map(e=>({label:e.label,value:e.value,kind:e.kind,description:e.description,source:`recent`}))}function Yn(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0?r:t}function Xn(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0&&Number.isInteger(r)?r:t}function Zn(e){let{app:t,tui:n,getSession:r,setRestartResumePrompt:i,setRestartMemoryTriggered:a,handleExit:o,onContextCompacted:s,recomputeBudget:c}=e,l=!1,u=0,d,f=!1,m=0,h=!1,g=Yn(`OTTO_MEMORY_CRITICAL_NOTIFY_INTERVAL_MS`,18e5),_=Xn(`OTTO_MEMORY_CRITICAL_NOTIFY_ESCALATION_CYCLES`,4),v,y=()=>{let e=r();if(e.isBusy){let t=e.session.messages(),n=t[t.length-1];if(n?.role===`user`&&!n.internal){let e=p(n.content);e&&i(e)}}a(!0),o({type:`exit`,restart:!0})},b=()=>{v&&=(clearInterval(v),void 0),m=0,h=!1};t.memoryGovernor.setCallbacks({onWarning:()=>{r().compactNow().then(e=>{e.compacted&&(n.info.showToast(Q.t(`cmd.titleAutoCompact`),Q.t(`compact.edResult`,{before:e.before,after:e.after})),s(),c())}).catch(e=>{let r=e instanceof Error?e.message:String(e);t.logger.warn({err:r},`[memory-governor] compactNow (soft degrade) failed`),n.info.showToast(Q.t(`cmd.titleAutoCompact`),Q.t(`cmd.autoCompactFailed`,{msg:r}))})},onCritical:e=>{if(l){n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),`system`,`info`);return}n.info.isFullScreenPaneActive()&&(u++,d??=Date.now(),u<3&&Date.now()-d<300*1e3)||(u=0,f=!0,n.modal.openModal({kind:`confirm`,title:Q.t(`cmd.titleMemoryPressure`),message:Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),confirmLabel:Q.t(`cmd.memoryPressureRestartNow`),cancelLabel:Q.t(`cmd.memoryPressureRemindLater`),confirmColor:`amber`,extraLabel:Q.t(`cmd.memoryPressureSuppress`),onConfirm:()=>{f=!1,b(),y()},onCancel:()=>{f=!1},onExtra:()=>{f=!1,l=!0}}))},onCriticalDuringGrace:e=>{n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),`system`,`warning`)},onCriticalTimeout:e=>{if(f){f=!1,y();return}let i=()=>{m++,n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:t.memoryGovernor.sample().usedPct.toFixed(0)}),`system`,`warning`),!h&&m>=_&&(h=!0,r().compactNow().catch(e=>{let n=e instanceof Error?e.message:String(e);t.logger.warn({err:n},`[memory-governor] critical-unattended-escalation compactNow failed`)}),t.storage.traceStore?.append(r().id,{ts:Date.now(),sessionId:r().id,kind:`lifecycle`,node:`critical-unattended-escalation`,payload:{usedPct:e.usedPct,cycles:m}}).catch(e=>{t.logger.warn({err:e instanceof Error?e.message:String(e)},`[memory-governor] critical-unattended-escalation trace append failed`)}))};v||(i(),v=setInterval(i,g),v.unref?.())},onLevelChange:e=>{e!==`critical`&&(u=0,d=void 0,b()),n.engine.pushEngineEvent({kind:`perf`,indicatorLevel:e,memory:t.memoryGovernor.sample()})}}),t.fleetMonitor.setCallbacks({onBudgetExceeded:e=>{n.info.pushNotification(Q.t(`cmd.titleFleetBudget`),Q.t(`cmd.fleetBudgetExceeded`,{processCount:e.processCount,totalRssMb:e.totalRssMb}),`system`,`warning`)}})}function Qn(e){let{app:t,getTui:n,getTuiRef:r,getSession:a,getCliCtx:o,historyStore:s}=e;return{onCyclePermissionMode:()=>{let e=n(),r=g(t.getPermissionMode());e.stores.tasks.setPermissionMode(r),e.info.showToast(Q.t(`cmd.titlePermission`),Q.t(`pref.permModeSwitched`,{label:Q.t(`pref.permModeLabel`,{context:r})})),t.setPermissionMode(r)},onHistoryPush:t=>{try{s.hydrate([...t]),s.persist().catch(()=>{})}catch{}e.getPasteBinder?.()?.save(a().id)},onDraftSave:e=>{let n=a(),o=n.session.getDrafts()??[],s=v(void 0,e,o),c=P([...o,s]);n.session.setDrafts(c),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(i(c))},onDraftDelete:e=>{let n=a(),o=(n.session.getDrafts()??[]).filter(t=>t.id!==e);n.session.setDrafts(o),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(i(o))},onDraftDeleteMany:e=>{let n=a(),o=new Set(e),s=(n.session.getDrafts()??[]).filter(e=>!o.has(e.id));n.session.setDrafts(s),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(i(s))},onA2uiAction:(e,t,n)=>{k(`a2ui-action`,n?[e,t,JSON.stringify(n)]:[e,t],o())},onPerfRefresh:()=>{k(`perf`,[],o())},onProxySubmitUrl:e=>{k(`proxy`,[e],o())},onProxyToggleEnabled:()=>{k(`proxy`,[t.settings.get(`proxy`)?.enabled===!1?`on`:`off`],o())},onProxyClear:()=>{k(`proxy`,[`clear`],o())},onProxyTest:()=>{k(`proxy`,[`test`],o())}}}function $n(e){return{...er(e),pluginSource:e.pluginSource,intervalSeconds:e.errorRetryIntervalSeconds}}function er(e){let{msg:t,provider:n,authError:r,isRefreshFailed:i,unsupported:a,rateLimit:o,rateLimitInfo:s,getErrorRetryAttempt:c,incErrorRetryAttempt:l,errorRetryMax:u,retryQueued:d,resetAndRetry:f,cancelRetry:p,switchModelThenRetry:m,goToAuth:h}=e;if(s)return s.resetsAt===void 0?{reason:t,attempt:0,max:u,mode:`manual`,limitType:s.limitType,actions:[{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p}:{reason:t,attempt:0,max:u,mode:`resetsAt`,resetsAt:s.resetsAt,limitType:s.limitType,actions:[{kind:`retryNow`,label:Q.t(`error.retryNow`),run:d},{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m}],onExpired:d,onCancel:p};if(r)return{reason:i?Q.t(`cmd.authRefreshFailed`,{ps:n?` (${n})`:``,ls:n?` ${n}`:``}):Q.t(`cmd.authFailed`,{ps:n?` (${n})`:``,ls:n?` ${n}`:``}),attempt:c(),max:u,mode:`manual`,actions:[{kind:`login`,label:Q.t(`model.goToLoginButton`),run:h},{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p};if(a)return{reason:Q.t(`cmd.modelNotSupported`),attempt:c(),max:u,mode:`manual`,actions:[{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p};let g=l(),_=g>u;return{reason:o?Q.t(`cmd.rateLimitedRetriesExhausted`):Q.t(`cmd.requestFailed`,{msg:t}),attempt:Math.min(g,u),max:u,mode:`auto`,exhausted:_,actions:[{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:_?f:d}],onExpired:_?()=>{}:d,onCancel:p}}function tr(e){let{err:t}=e,n=t instanceof Error?t.message:String(t),r=t?.code===`AGENT_ABORTED`;if(!(e.submitState.userAborted||r)){let r=e.provider,i=t?.code,o=t?.pluginSource,{authError:s,isRefreshFailed:c,unsupported:l,rateLimit:u,pluginSource:d}=a(n,i,o),f=e.rateLimitInfoRef.current;e.rateLimitInfoRef.current=void 0;let p=(()=>{let t=e.cliCtx,n=t?.app?.storage?.traceStore,r=t?.state?.session;if(!n||!r)return null;let i=r.session.getTurnCount();return{traceStore:n,sessionId:r.id,...i===void 0?{}:{turn:i}}})(),m=()=>{p&&O(p,{attempt:e.errorRetryAttemptRef.current+1,max:e.ERROR_RETRY_MAX,mode:f?`resetsAt`:s||l?`manual`:`auto`,reason:n.slice(0,120)}),e.retryModeRef.current=!0;let t=e.latestSubmittedPromptRef?.current,r=e.tui.engine.takeLastQueuedFollowUp?.(),i=t!=null&&t.text!==e.text,a=i?t.text:r?.text??e.text,o=i?t.mode:r?.mode??e.mode;queueMicrotask(()=>e.handleSubmit?.(a,o,`send`))};e.tui.engine.showErrorRetry($n({msg:n,provider:r,authError:s,isRefreshFailed:c,unsupported:l,rateLimit:u,rateLimitInfo:f,pluginSource:d,getErrorRetryAttempt:()=>e.errorRetryAttemptRef.current,incErrorRetryAttempt:()=>++e.errorRetryAttemptRef.current,errorRetryMax:e.ERROR_RETRY_MAX,errorRetryIntervalSeconds:e.ERROR_RETRY_INTERVAL_SECONDS,retryQueued:m,resetAndRetry:()=>{p&&T(p),e.errorRetryAttemptRef.current=0,m()},cancelRetry:()=>{p&&A(p,{attempt:e.errorRetryAttemptRef.current}),e.errorRetryAttemptRef.current=0},switchModelThenRetry:()=>{e.handleModel([],e.cliCtx,{afterSwitch:m})},goToAuth:()=>{e.handleProviderAuth([r??``].filter(Boolean),e.cliCtx)}}))}}async function nr(e,n,a){let s=!1,l=!1,d,f;try{let p=n.settings.get(`permission_mode`);(p===void 0||p===`auto`)&&await n.settings.update({permission_mode:`confirm`});let m=e.continueSession?n.getSession(e.continueSession)??await n.sessionManager.restore(e.continueSession)??void 0:void 0,g=m?m.session.buildContext().messages.filter(e=>{let t=e.role;return t===`user`||t===`assistant`}).length:0,_={value:m?n.sessionManager.consumeCrashGap(m.id):void 0},v=e.continueSession?m?Q.t(`cmd.resumeRestored`,{idShort:e.continueSession.slice(0,8),count:g}):Q.t(`cmd.resumeNotFound`,{id:e.continueSession}):void 0,b=!!(e.continueSession&&m),S=!!(e.model||n.settings.get(`model`)||n.settings.get(`model_slots`)?.default),C={skip:!1},w=await n.hydrateModelCache().catch(()=>new Set),T=!m&&n.modelRegistry.getAll().length===0,E=`__otto_setup__`;T&&n.modelRegistry.register({id:E,name:`Setup required`,provider:`otto`,api:`otto`,baseUrl:``,reasoning:!1,input:[`text`],contextWindow:32e3,maxOutputTokens:4e3});let O=T?!1:S,A=m??await n.createSession({interactive:!0,retryAccelerate:C,...O?{}:{model:n.modelRegistry.getAll()[0]}});await Pn(A,n,!!m);let j=O||b,se={get value(){return j},set value(e){j=e}},P=n.modelRegistry.getAll().filter(e=>e.id!==E).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow})),F=new Set([...w,...n.getSessionAvailableModels(A.id)]),le=()=>n.setSessionAvailableModels(A.id,[...F]);le();let fe=F.size===0,pe=async e=>{let t=await n.refreshModels().catch(()=>[]);P=n.modelRegistry.getAll().filter(e=>e.id!==E).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow}));for(let e of t)if(e.status===`ok`)for(let t of e.availableIds??[])F.add(t);P.length>0&&n.modelRegistry.getAll().some(e=>e.id===E)&&n.modelRegistry.unregister(E),le();let r=F.size===0;if(z?.stores.tasks.setNeedsSetup(r),fe&&!r&&(fe=!1,z?.info.showToast(Q.t(`cmd.titleSetupReady`),Q.t(`cmd.setupReadyMessage`))),e){let n=t.filter(e=>e.status===`ok`);e(n.length>0?Q.t(`cmd.modelsRefreshed`,{summary:n.map(e=>`${e.provider} ${e.total}`).join(` · `)}):Q.t(`cmd.modelsRefreshedEmpty`))}};pe();let I=j?A.model?.id:void 0,L=n.modelRegistry.getAll().filter(e=>e.id!==E).find(e=>e.id===I)?.contextWindow??0,ge={get value(){return L},set value(e){L=e}},R=I,_e={get value(){return R},set value(e){R=e}},ve=e=>c(n,e,A.thinkingLevel),z,be={get value(){return z},set value(e){z=e}},xe,B={get value(){return xe},set value(e){xe=e}},Se={value:void 0},Ce={value:e},Te=e=>{switch(e.kind){case`steer`:A.steer(e.input);break;case`abort`:U.abort();break;case`pauseAfterTurn`:A.pauseRun();break;case`resumeRun`:A.resumeRun();break}},V=sn({modelReady:se,currentModelId:_e,contextWindow:ge,tuiRef:be,pushBudgetNow:B,app:n,getSession:()=>A,options:Ce,fmtDisplayModel:ve,onEngineModelAction:Te}),H=cn({getSession:()=>A,app:n,tuiRef:be,options:Ce,fmtDisplayModel:ve,applyModel:V,onExitSession:()=>Se.value?.()}),U=new u(A,{models:P,currentModel:I,onModelChange:V}),{startTui:Ee}=await import(`@x-otto/tui`),W=U.getRegistry();Ht(W);let De=t(W,n),G={agentProcessing:!1,ctrlCCount:0,lastCtrlCTime:0,userAborted:!1,shellChild:null,streamedText:!1,retryMode:!1,errorRetryAttempt:0,lastRateLimitInfo:void 0,latestSubmittedPrompt:void 0},K=()=>Pt(A.isBusy,G.agentProcessing),q=Vt(W,G.agentProcessing,M,Q.t(`cmdDesc`,{returnObjects:!0}),A.pinned,A.isPaused),Oe=()=>(q=Vt(W,G.agentProcessing,M,Q.t(`cmdDesc`,{returnObjects:!0}),A.pinned,A.isPaused),q);ie(n),te(n,F),N(n);let J=yt(),ke=n.settings.get(`language`)??`auto`,Y=ke===`auto`?x():ke,Ae=fn(n),X=n.settings.get(`theme_preset`),Me=n.settings.get(`keybinding_overrides`);o(Y);let Ne=y({currentVersion:de(),lastCheck:n.settings.get(`last_update_check`),autoCheck:n.settings.get(`auto_update_check`)!==!1,persistLastCheck:()=>n.settings.persist({last_update_check:Date.now()})});if(await new Promise(async t=>{let c,u=n.getResilienceConfig().errorRetry.maxAttempts,p,y=!1,S=()=>{if(!y){y=!0;try{f?.clearBgSubs()}catch{}try{f?.stopBgOutputPoll()}catch{}try{f?.stopBgSubagentPoll()}catch{}try{clearInterval(Pe)}catch{}try{Ie.stop()}catch{}try{p?.dispose()}catch{}t()}};Se.value=S;let te=()=>{setTimeout(S,3e3).unref();try{z?.lifecycle.stop()}catch{S()}},w=Nn({getTui:()=>z??null,getSession:()=>A,dispatchAbort:()=>Te({kind:`abort`}),clearTodoLayers:()=>{J.todoList.length!==0&&(J.todoList=[],z?.stores.tasks.setTasks([]),A.session.setTodoList([]))},markUserAborted:()=>{G.userAborted=!0},resetCtrlCCount:()=>{G.ctrlCCount=0},markRestartRequested:()=>{s=!0},stopTui:te,isBusy:()=>K()}),T=oe,{historyStore:E,inputHistory:ie,externalHistoryCommands:O}=await Un(A,n.settings.get(`history`)?.external),N=nn({app:n,session:A,getTui:()=>B});f=N;let se,de,fe,L,be={value:void 0};je(`startTui() begin`);let B=await Ee({stdin:process.stdin,stdout:process.stdout,modelName:ve(I),needsSetup:F.size===0,commands:q,pluginInput:n.pluginInput,isImmediateCommand:e=>K()?M.has(e):T.has(e),isInterruptCommand:e=>e===`abort`,isAgentBusy:K,isPaused:()=>A.isPaused,initialPath:b&&g>0?`/`:`/home`,shadow:n._shadow,welcome:{cwd:process.cwd(),version:Re,buildId:Fe,nickname:n.settings.get(`nickname`)||void 0,updateAvailable:void 0},onSessionSelect:e=>{k(`resume`,[e],L)},loadHistory:n.sessionRepoRef?.current?await(async()=>{let t=n.sessionRepoRef.current;if(!t)return;let r=await Jt(t,A.id,!!e.continueSession);return e=>r.loadEarlier(e.limit)})():void 0,language:ke,themeRegistry:Ae,presetSelection:X,keybindingOverrides:Me,permissionMode:n.getPermissionMode(),onFocusChange:e=>n.setTerminalFocus(e),...N.handlers,initialHistory:ie,externalHistoryCommands:O,residencyGovernor:n._residencyGovernor,resolveWholeFileDiff:async(e,t)=>{try{return await r(Ue(n.workspaceDir,e),t)}catch(e){return{error:e instanceof Error?e.message:String(e)}}},initialDrafts:i(A.session.getDrafts()??[]),initialRecentMentions:Jn(n.settings.get(`recent_mentions`)??[]),onSigilSelect:e=>{let t=Kn(n.settings.get(`recent_mentions`)??[],qn(e));n.settings.persist({recent_mentions:t}).catch(()=>{}),z?.stores.tasks.setRecentMentions(Jn(t))},...Qn({app:n,getTui:()=>B,getTuiRef:()=>z,getSession:()=>A,getCliCtx:()=>L,historyStore:E,getPasteBinder:()=>L.callbacks.pasteBinder}),onQueueSendNow:(e,t)=>{if(t===`memory`){fe(e);return}if(t===`bash`||t===`bash_async`){se(e,t===`bash`?`!`:`!!`);return}c?.(e,`send`,K()?`steer`:`send`)},onSubmit:c=async(e,t,r)=>{if(G.ctrlCCount=0,de(e,t))return;if(A.isPaused&&A.resumeRun(),r===`steer`&&A.isBusy){G.latestSubmittedPrompt={text:e,mode:t};let{id:n}=A.steer(e);B.pending.setPendingSteer(e,n);return}if(t===`memory`){await fe(e);return}if(t===`bash`||t===`bash_async`){se(e,t===`bash`?`!`:`!!`);return}let i=Lt(e),a=e,o=!1;if(i.isCommand){if(await k(i.command,i.args,L))return;n.firePluginActivationEvent?.(`onCommand:${i.command}`);let e=De.find(e=>e.name===i.command);e&&(o=!0,a=await we(e.body,{args:i.args,workspaceDir:n.workspaceDir}))}let s=i.isCommand&&!o&&ae.has(i.command.toLowerCase());if(!s&&!j&&(!i.isCommand||o)){B.info.showToast(Q.t(`cmd.titleSetupRequired`),Q.t(`cmd.noModelConfigured`));return}if(J.todoList.length>0&&J.todoList.every(e=>e.status===`done`||e.status===`skipped`||e.status===`failed`)&&(J.todoList=[],B.stores.tasks.setTasks([]),A.session.setTodoList([])),K()&&(!i.isCommand||o)){B.engine.enqueueFollowUp(e,t),B.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`queue.dFollowUpToast`));return}s||(await H(),B.engine.pushEngineEvent({kind:`agentProcessing`,value:!0}),G.agentProcessing=!0,B.plugins.setCommands(Oe())),G.userAborted=!1;{let e=on(a);a=e.text;let t=e.modelIds.at(-1);if(t&&t!==A.model?.id){let e=await V(t);e.includes(`not in registry`)&&B.info.showToast(Q.t(`cmd.titleModel`),e)}}if(!Dn(a)){G.latestSubmittedPrompt={text:e,mode:t},G.retryMode||(G.errorRetryAttempt=0),G.retryMode=!1,Ke.lastTasks=J.todoList.slice();try{a=await n.expandSigilChips(a,{skipPrefixes:new Set([`model`])}),(!i.isCommand||o)&&!G.retryMode&&(B.messages.echoUserInput(a,{pending:!0}),B.pending.setPendingEcho(a,t));let e=a;G.streamedText=!1;let r=await U.handleInput(e);if(r.type===`exit`){Le(r);return}if(r.type===`help`){B.modal.openModal({kind:`helpViewer`,title:`Help`,lines:Bt(W,A.pinned,Q.t(`cmdDesc`,{returnObjects:!0})),onDismiss:()=>{}});return}r.type!==`noop`&&r.text&&!G.streamedText&&(r.type===`system`&&r.text.length<=80?B.info.showToast(Q.t(`cmd.titleInfo`),r.text):B.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:r.text}]})),r.type===`response`&&r.endReason&&(B.pending.clearPendingEcho(),r.notice&&B.info.showToast(Q.t(`cmd.titleInfo`),r.notice)),await Nt(r,{runTurn:e=>U.handleInput(e),onTurnResult:e=>e.type===`exit`?(Le(e),`exit`):(e.type!==`noop`&&e.type!==`help`&&e.text&&!G.streamedText&&B.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:e.text}]}),`continue`),askBudgetContinue:()=>new Promise(e=>{B.modal.openModal({kind:`select`,title:Q.t(`budget.exhaustedTitle`),layout:`buttons`,options:[{label:Q.t(`budget.continue`),value:`go`,color:`accent`},{label:Q.t(`budget.stop`),value:`stop`,color:`amber`}],onSelect:t=>e(t===`go`),onCancel:()=>e(!1)})}),onBudgetStopped:()=>{B.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`budget.stoppedNote`)}]})},beforeContinuationTurn:()=>{G.streamedText=!1}})}catch(r){B.pending.withdrawPendingEcho(),tr({err:r,submitState:G,provider:A.model?.provider,rateLimitInfoRef:{get current(){return G.lastRateLimitInfo},set current(e){G.lastRateLimitInfo=e}},retryModeRef:{get current(){return G.retryMode},set current(e){G.retryMode=e}},errorRetryAttemptRef:{get current(){return G.errorRetryAttempt},set current(e){G.errorRetryAttempt=e}},ERROR_RETRY_MAX:u,ERROR_RETRY_INTERVAL_SECONDS:n.getResilienceConfig().errorRetry.intervalMs/1e3,handleSubmit:c,latestSubmittedPromptRef:{get current(){return G.latestSubmittedPrompt},set current(e){G.latestSubmittedPrompt=e}},text:e,mode:t,handleModel:me,handleProviderAuth:he,cliCtx:L,tui:B})}finally{G.agentProcessing=!1,G.userAborted=!1,B.engine.pushEngineEvent({kind:`agentProcessing`,value:!1}),B.plugins.setCommands(Oe())}}},onInterrupt:()=>{let e=Date.now(),t=Mn(e,G.lastCtrlCTime,{shellRunning:!!G.shellChild,busy:K(),stopDialogOpen:w.isStopDialogOpen(),idleCtrlCCount:G.ctrlCCount});if(t!==`dedup`)switch(G.lastCtrlCTime=e,t){case`kill-shell`:G.shellChild.kill(`SIGTERM`),setTimeout(()=>{G.shellChild&&!G.shellChild.killed&&G.shellChild.kill(`SIGKILL`)},3e3);return;case`open-stop-dialog`:w.requestStop(`abort`);return;case`escalate-exit`:w.escalateToExit();return;case`exit-process`:te();return;case`hint-exit`:G.ctrlCCount++,setTimeout(()=>{G.ctrlCCount=0},800).unref(),B.info.showToast(Q.t(`cmd.titleExit`),Q.t(`cmd.pressCtrlCAgain`));return}},onShellAskAi:()=>{let e=z?.shell.getShellExecutionSnapshot();if(!e)return;let t=jn(e);c?.(t,`send`,K()?`steer`:`send`)},onWithdrawPending:(e,t)=>{B.pending.withdrawPendingEcho(),B.pending.restoreInputText(e),G.agentProcessing&&(G.userAborted=!0,Te({kind:`abort`}),B.info.showToast(Q.t(`cmd.titleAborted`),Q.t(`cmd.runAborted`)))},onWithdrawSteer:e=>{A.removeSteer(e)?B.pending.withdrawPendingSteer(e):w.requestStop(`abort`)},onStop:()=>{S()}});z=B,a&&(a.current=(e,t)=>{B.info.showToast(`Memory Conflict`,`Concurrent edit detected for ${e} — saved to ${t}`)}),je(`startTui() ready (first frame mounted)`),n.setUserAskRenderer(e=>Gt(B,e));let Ce=Wn({gateway:()=>n.sessionManager.panelState,bridge:()=>B.pending,onError:(e,t)=>{n.logger?.debug?.({stage:e,error:t},`paste cache binding failed (non-fatal)`)}});vn({app:n,tui:B}),_n(n),n.listAllSessions().then(e=>{let t=A.id,n=e.filter(e=>e.status!==`archived`&&(e.entryCount??e.messageCount)>0&&e.id!==t).slice(0,10).map(e=>({id:e.id,title:e.title??e.id.slice(0,8),status:e.id===t?`busy`:`idle-cold`,lastActivityAt:e.updatedAt?new Date(e.updatedAt).toLocaleString():``,isCurrent:e.id===t,isPinned:e.pinned??!1,isArchived:e.status===`archived`,isReadOnly:e.writeLocked??!1}));B.stores.tasks.setSessionList(n)}).catch(()=>{});let{pollInterval:Pe,scheduler:Ie}=hn(n,{get value(){return A}},B,e.sessionUrl&&e.sessionToken?{sessionUrl:e.sessionUrl,sessionToken:e.sessionToken}:void 0);se=On({tui:B,app:n,submitState:G}),de=kn({agentProcessingRef:{get value(){return G.agentProcessing},set value(e){G.agentProcessing=e}},tui:B,requestStop:e=>w.requestStop(e)}),fe=An({app:n,tui:B}),yn({app:n,tui:B,session:A}),bn({app:n,tui:B,getScheduler:()=>Ie});let Le=e=>{w.requestStop(e.restart?`exit-restart`:`exit`)};e.memoryRestartGrace&&n.memoryGovernor.markRestarted();let ze=e.restartGeneration??0;ze>=3&&B.info.pushNotification(Q.t(`cmd.titleFleetBudget`),Q.t(`cmd.restartChainDeep`,{generation:ze}),`system`,`warning`),B.engine.pushEngineEvent({kind:`perf`,indicatorLevel:n.memoryGovernor.currentLevel,memory:n.memoryGovernor.sample()}),Gn({session:A,tui:B,retryAccelerate:C,setRateLimitInfo:e=>{G.lastRateLimitInfo=e},abortNow:()=>{w.abortNow()}});let Be=tn({getSession:()=>A,app:n,tui:B,projState:J,contextWindow:ge,currentModelId:_e}),{recomputeBudget:Ve,persistEditedFiles:He,persistSubagents:Z,persistTurnCount:We,onContextCompacted:Ge}=Be;xe=Ve,Ve(),n.editFileCallback=Be.editFileCallback,Zn({app:n,tui:B,getSession:()=>A,setRestartResumePrompt:e=>{d=e},setRestartMemoryTriggered:e=>{l=e},handleExit:Le,onContextCompacted:Ge,recomputeBudget:Ve}),n.registerInAppNotificationChannel((e,t,n)=>B.info.pushNotification(e,t,`system`,ue(n))),n.setFollowUpPendingProbe(()=>B.engine.hasQueuedFollowUp());let Ke=re(),qe=Kt({getSession:()=>A,app:n,tui:B,projState:J,redState:Ke,recomputeBudget:Ve,persistEditedFiles:He,persistSubagents:Z,persistTurnCount:We,onContextCompacted:Ge,markStreamed:()=>{G.streamedText=!0}});be.value=qe,L=gn({tui:B,app:n,themeRegistry:Ae,sessionRef:{get value(){return A},set value(e){A=e}},interactiveRef:{get value(){return U},set value(e){U=e}},regRef:{get value(){return W},set value(e){W=e}},slashCommandsRef:{get value(){return q},set value(e){q=e}},modelReadyRef:{get value(){return j},set value(e){j=e}},currentModelIdRef:{get value(){return R},set value(e){R=e}},currentLangRef:{get value(){return Y},set value(e){Y=e}},projState:J,agentProcessingRef:{get value(){return G.agentProcessing},set value(e){G.agentProcessing=e}},modelsRef:{get value(){return P},set value(e){P=e}},availableModelIds:F,restartRequestedRef:{get value(){return s},set value(e){s=!!e}},applyModel:V,persistAvailable:le,refreshModelsNow:pe,refreshSlashCommands:Oe,events:qe,redState:Ke,agentMessagesToChatMessages:D,PROVIDER_DISPLAY_NAMES:h,apiCredentialId:ye,onContextCompacted:Ge}),L.callbacks.pasteBinder=Ce,Ce.load(A.id),B.plugins.setPluginRegistrations(n.getPluginRegistrations());let Je=await new ne(ee({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>A.model?.id,isModelUsable:_t(n.authStore)})).refresh();if(ce(Je)&&ke===`auto`&&!n.settings.get(`has_completed_onboarding`)){let e=await B.modal.openModal({kind:`onboarding`,onLanguagePreview:e=>{let t=e===`auto`?x():e;o(t),B.lifecycle.setLanguage(t),Y=t}});if(e.nickname&&n.settings.persist({nickname:e.nickname}).catch(()=>{}),e.language){let t=e.language===`auto`?x():e.language;o(t),B.lifecycle.setLanguage(t),Y=t,n.settings.persist({language:e.language}).catch(()=>{})}n.settings.persist({has_completed_onboarding:!0}).catch(()=>{})}Je.recommendation.autoOpen&&k(`setup`,[],L);let Ye=Tn();Ye&&(p=new En({repoRoot:Ye,currentBuildId:Fe,logger:n.logger,onStale:e=>{B.info.pushNotification(Q.t(`cmd.titleStaleBuild`),Q.t(`cmd.staleBuildMessage`,{current:Fe,latest:e}),`system`,`info`)}}),p.start()),await Cn({tui:B,options:e,app:n,session:A,projState:J,resumedNote:v,resumed:m,updateCheckPromise:Ne,bg:N,events:qe}),_.value&&B.info.showToast(Q.t(`crashGap.toastTitle`),Q.t(`crashGap.toastBody`,{lostTurns:_.value.lostTurns}))}),n.codingSessionPool.autoPersist&&A.session.messages().length>0){let t=e.sessionUrl?` --session-url ${e.sessionUrl}`:``,n=e.sessionToken?` --session-token ${e.sessionToken}`:``;process.stdout.write(`\n\x1b[2m${Q.t(`cmd.resumeContinueLabel`)}\x1b[0motto --continue ${A.id}${t}${n}\n`)}return{restart:s?{sessionId:A.id,memoryTriggered:l,resumePrompt:d}:void 0}}finally{f?.clearBgSubs(),f?.stopBgOutputPoll(),f?.stopBgSubagentPoll()}}async function rr(e){if(e.hasParentWorkspace()){let t=e.parentWorkspaceExisted,n=await st({parentRoot:t.parentRoot,currentRoot:t.currentRoot,language:e.settings.get(`language`)});n===`exit`&&(process.stdout.write(`
14
14
  `),process.exit(0)),n===`use_parent`?await e.adoptParentWorkspace():await e.createLocalWorkspace()}let t=Ce(e.workspaceDir,{interactive:!0});if(!t.shouldPrompt){e.needsWorkspaceInit()&&await e.confirmWorkspaceInit();return}let n=await ct({root:t.root,language:e.settings.get(`language`)});if(n===`exit`&&(process.stdout.write(`
15
15
  `),process.exit(0)),n===`trust`){K(t.root),await e.settings.reload(),e.needsWorkspaceInit()&&await e.confirmWorkspaceInit();return}await e.settings.update({permission_mode:`readonly`}),e.needsWorkspaceInit()&&await e.confirmWorkspaceInit()}function ir(e){throw e instanceof Error&&e.message.startsWith(`No model configured`)?Error("No model configured. Run `otto` (interactive) to complete setup — it walks you through: install a provider plugin → /auth → /model. Or authenticate directly with `otto auth login`."):e}async function ar(e,t){e.prompt&&await l(await t.createSession().catch(ir),e.prompt,{tui:!0})}async function or(e,t){if(e.prompt){let n=await j(await t.createSession().catch(ir),e.prompt);process.stdout.write(JSON.stringify(n,null,2)+`
16
- `)}}function sr(e){lt(e.settings.get(`theme_overrides`)?.markdown)}je(`cli.ts imports resolved`);const cr=new Map([[`doctor`,async e=>{let{runDoctorCommand:t}=await import(`./doctor-C84-hhEr.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`auth`,async e=>{let{runAuthCommand:t}=await import(`./auth-command-CXAB3_hs.js`);return t(e.args,{bootstrap:{workspaceDir:e.options.projectDir,projectConfigPath:e.options.configPath,verbose:e.options.verbose},stdout:e.stdout,stderr:e.stderr})}],[`serve`,async e=>{let{runServeCommand:t}=await import(`./serve-pVR6UIT9.js`);return t(e.args,{projectDir:e.options.projectDir,configPath:e.options.configPath,modelId:e.options.model,verbose:e.options.verbose})}],[`daemon`,async e=>{let{runDaemonCommand:t}=await import(`./daemon-COESl-zU.js`);return t(e.args,{projectDir:e.options.projectDir,stdout:e.stdout,stderr:e.stderr})}],[`persistenced`,async e=>{let{runPersistencedCommand:t}=await import(`./persistenced-CCwHu1Ww.js`);return t(e.args)}],[`remote-persistence-server`,async e=>{let{runRemotePersistenceServerCommand:t}=await import(`./remote-persistence-server-B_hONoVR.js`);return t(e.args)}],[`observe`,async e=>{let{runObserveCommand:t}=await import(`./observe-CVg-MRM2.js`);return t(e.args)}],[`debug`,async e=>{let{runDebugCommand:t}=await import(`./debug-CiosFwme.js`);return t(e.args)}],[`time-travel`,async e=>{let{runTimeTravelCommand:t}=await import(`./time-travel-ZozuPPI-.js`);return t(e.args)}],[`mcp`,async e=>{let{runMcpCommand:t}=await import(`./mcp-DbTYT7hB.js`);return t(e.args)}],[`config`,async e=>{let{runConfigMigrationCommand:t}=await import(`./config-migration-DatflIxs.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`migrate`,async e=>{let{runMigrateCommand:t}=await import(`./migrate-boDXhEyV.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`extension`,async e=>{let{runExtensionCommand:t}=await import(`./extension-CnON6Xum.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`ps`,async e=>{let{runPsCommand:t}=await import(`./ps-DKrluEuy.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`feedback`,async e=>{let{runFeedbackCommand:t}=await import(`./feedback-BRbLUn9u.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr,projectDir:e.options.projectDir,configPath:e.options.configPath})}]]);async function lr(e,t,n){let r=I({cwd:n.projectDir,homedir:R()}),i=new Set(pe),a=be(r,i).get(e);if(!a){let t=Te(r,i,e);return t?(process.stderr.write(`otto: 命令 "${e}" 被多个插件声明(${t.join(`, `)}),已禁用以避免歧义。\n请重命名其中一个插件的 \`contributes.cli.name\` 后重试(编辑对应插件目录的 otto-plugin.json)。\n`),1):void 0}if(Se(a).gated)return process.stderr.write(`otto: 插件 "${a.id}" 声明了 \`otto ${e}\` 命令但尚未被信任。\n请先在 TUI 内运行 \`/trust plugin ${a.id}\`(或 \`/extension\` 信任该插件)后重试。\n`),1;let o=W(a);if(!o)return process.stderr.write(`otto: 插件 "${a.id}" 声明了 \`contributes.cli\` 但找不到可执行入口,请检查其 manifest 的 bin 字段或重新安装该插件。\n`),1;try{return await G(o,t,a.dir)}catch(e){return process.stderr.write(`otto: 插件 "${a.id}" 的 CLI 命令执行失败:${e instanceof Error?e.message:String(e)}\n`),1}}function ur(e,t){return e.mode===`interactive`&&!e.verbose&&!t?`fatal`:t}function dr(e,t){return e.mode===`interactive`&&!t?`0`:t}function fr(e,t,n={}){let r=[];for(let t=0;t<e.length;t++){if(e[t]===`--continue`){t++;continue}e[t].startsWith(`--restart-generation=`)||r.push(e[t])}return[...n.execArgv??[],...r,`--continue`,t,...n.generation===void 0?[]:[`--restart-generation=${n.generation}`],...n.sessionUrl?[`--session-url`,n.sessionUrl]:[],...n.sessionToken?[`--session-token`,n.sessionToken]:[],...n.memoryRestartGrace?[`--memory-restart-grace`]:[],...n.resumePrompt?[`--resume-prompt`,n.resumePrompt]:[]]}async function pr(){process.stdin.on(`error`,e=>{e.code});let{options:e,subCommand:t,subCommandArgs:n,unresolvedCommandName:r,unresolvedCommandArgs:i}=fe(process.argv);e.shadow&&(process.env.OTTO_SHADOW=`1`);let a=e.verbose?`debug`:e.mode===`interactive`?`fatal`:e.quiet?`error`:`info`;Me(a);let o=ur(e,process.env.OTTO_LOG_LEVEL);o&&(process.env.OTTO_LOG_LEVEL=o);let s=dr(e,process.env.OTTO_LOG_STDERR);s&&(process.env.OTTO_LOG_STDERR=s),process.env.OTTO_LOG_STDERR===`0`?ze(()=>{}):ze(e=>process.stderr.write(`${e}\n`)),process.on(`beforeExit`,()=>{process.env.OTTO_LOG_STDERR!==`0`&&ze(e=>process.stderr.write(`${e}\n`))});let c=n.split(` `).filter(Boolean),l=cr.get(t??``);if(l)return l({args:c,options:e,stdout:e=>process.stdout.write(e),stderr:e=>process.stderr.write(e)});if(r){let t=await lr(r,i??[],e);if(t!==void 0)return t}if(e.showHelp){let{getHelpLines:e}=await import(`./parse-cli-cYMjnAum.js`).then(e=>e.r);return process.stdout.write(e().join(`
16
+ `)}}function sr(e){lt(e.settings.get(`theme_overrides`)?.markdown)}je(`cli.ts imports resolved`);const cr=new Map([[`doctor`,async e=>{let{runDoctorCommand:t}=await import(`./doctor-C84-hhEr.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`auth`,async e=>{let{runAuthCommand:t}=await import(`./auth-command-CXAB3_hs.js`);return t(e.args,{bootstrap:{workspaceDir:e.options.projectDir,projectConfigPath:e.options.configPath,verbose:e.options.verbose},stdout:e.stdout,stderr:e.stderr})}],[`serve`,async e=>{let{runServeCommand:t}=await import(`./serve-pVR6UIT9.js`);return t(e.args,{projectDir:e.options.projectDir,configPath:e.options.configPath,modelId:e.options.model,verbose:e.options.verbose})}],[`daemon`,async e=>{let{runDaemonCommand:t}=await import(`./daemon-COESl-zU.js`);return t(e.args,{projectDir:e.options.projectDir,stdout:e.stdout,stderr:e.stderr})}],[`persistenced`,async e=>{let{runPersistencedCommand:t}=await import(`./persistenced-CCwHu1Ww.js`);return t(e.args)}],[`remote-persistence-server`,async e=>{let{runRemotePersistenceServerCommand:t}=await import(`./remote-persistence-server-B_hONoVR.js`);return t(e.args)}],[`observe`,async e=>{let{runObserveCommand:t}=await import(`./observe-CVg-MRM2.js`);return t(e.args)}],[`debug`,async e=>{let{runDebugCommand:t}=await import(`./debug-CiosFwme.js`);return t(e.args)}],[`time-travel`,async e=>{let{runTimeTravelCommand:t}=await import(`./time-travel-ZozuPPI-.js`);return t(e.args)}],[`mcp`,async e=>{let{runMcpCommand:t}=await import(`./mcp-DbTYT7hB.js`);return t(e.args)}],[`config`,async e=>{let{runConfigMigrationCommand:t}=await import(`./config-migration-DatflIxs.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`migrate`,async e=>{let{runMigrateCommand:t}=await import(`./migrate-boDXhEyV.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`extension`,async e=>{let{runExtensionCommand:t}=await import(`./extension-CnON6Xum.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`ps`,async e=>{let{runPsCommand:t}=await import(`./ps-DKrluEuy.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`feedback`,async e=>{let{runFeedbackCommand:t}=await import(`./feedback-BRbLUn9u.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr,projectDir:e.options.projectDir,configPath:e.options.configPath})}]]);async function lr(e,t,n){let r=I({cwd:n.projectDir,homedir:R()}),i=new Set(pe),a=be(r,i).get(e);if(!a){let t=Te(r,i,e);return t?(process.stderr.write(`otto: 命令 "${e}" 被多个插件声明(${t.join(`, `)}),已禁用以避免歧义。\n请重命名其中一个插件的 \`contributes.cli.name\` 后重试(编辑对应插件目录的 otto-plugin.json)。\n`),1):void 0}if(Se(a).gated)return process.stderr.write(`otto: 插件 "${a.id}" 声明了 \`otto ${e}\` 命令但尚未被信任。\n请先在 TUI 内运行 \`/trust plugin ${a.id}\`(或 \`/extension\` 信任该插件)后重试。\n`),1;let o=W(a);if(!o)return process.stderr.write(`otto: 插件 "${a.id}" 声明了 \`contributes.cli\` 但找不到可执行入口,请检查其 manifest 的 bin 字段或重新安装该插件。\n`),1;try{return await G(o,t,a.dir)}catch(e){return process.stderr.write(`otto: 插件 "${a.id}" 的 CLI 命令执行失败:${e instanceof Error?e.message:String(e)}\n`),1}}function ur(e,t){return e.mode===`interactive`&&!e.verbose&&!t?`fatal`:t}function dr(e,t){return e.mode===`interactive`&&!t?`0`:t}function fr(e,t,n={}){let r=[];for(let t=0;t<e.length;t++){if(e[t]===`--continue`){t++;continue}e[t].startsWith(`--restart-generation=`)||r.push(e[t])}return[...n.execArgv??[],...r,`--continue`,t,...n.generation===void 0?[]:[`--restart-generation=${n.generation}`],...n.sessionUrl?[`--session-url`,n.sessionUrl]:[],...n.sessionToken?[`--session-token`,n.sessionToken]:[],...n.memoryRestartGrace?[`--memory-restart-grace`]:[],...n.resumePrompt?[`--resume-prompt`,n.resumePrompt]:[]]}async function pr(){process.stdin.on(`error`,e=>{e.code});let{options:e,subCommand:t,subCommandArgs:n,unresolvedCommandName:r,unresolvedCommandArgs:i}=fe(process.argv);e.shadow&&(process.env.OTTO_SHADOW=`1`);let a=e.verbose?`debug`:e.mode===`interactive`?`fatal`:e.quiet?`error`:`info`;Me(a);let o=ur(e,process.env.OTTO_LOG_LEVEL);o&&(process.env.OTTO_LOG_LEVEL=o);let s=dr(e,process.env.OTTO_LOG_STDERR);s&&(process.env.OTTO_LOG_STDERR=s),process.env.OTTO_LOG_STDERR===`0`?ze(()=>{}):ze(e=>process.stderr.write(`${e}\n`)),process.on(`beforeExit`,()=>{process.env.OTTO_LOG_STDERR!==`0`&&ze(e=>process.stderr.write(`${e}\n`))});let c=n.split(` `).filter(Boolean),l=cr.get(t??``);if(l)return l({args:c,options:e,stdout:e=>process.stdout.write(e),stderr:e=>process.stderr.write(e)});if(r){let t=await lr(r,i??[],e);if(t!==void 0)return t}if(e.showHelp){let{getHelpLines:e}=await import(`./parse-cli-C6cLzKhy.js`).then(e=>e.r);return process.stdout.write(e().join(`
17
17
  `)+`
18
18
  `),0}if(!e.prompt&&e.mode!==`interactive`)return process.stderr.write(`otto: no prompt provided. Use --help for usage.
19
19
  `),1;let u=await Ve(),d=e.sessionUrl??u?.serviceUrl,f=e.sessionToken??u?.token,p={},m=Pe(`new App() ctor`,()=>B({inspect:e.inspect!==void 0||e.mode===`interactive`,logger:{name:`otto-cli`,level:a,destination:`stderr`},workspaceDir:e.projectDir,workspaceId:e.workspaceId,projectConfigPath:e.configPath,interactive:e.mode===`interactive`,shadow:e.shadow??!1,modelId:e.model,userIdentity:u??void 0,...e.maxToolTurns===void 0?{}:{maxToolTurns:e.maxToolTurns},...e.maxToolTurnExtensions===void 0?{}:{maxToolTurnExtensions:e.maxToolTurnExtensions},...e.promptTokenBudget===void 0?{}:{promptOutputTokenBudget:e.promptTokenBudget},...e.promptTimeBudgetMin===void 0?{}:{promptWallClockBudgetMs:e.promptTimeBudgetMin*6e4},...e.sessionCostBudget===void 0?{}:{sessionCostBudgetUSD:e.sessionCostBudget},...e.noStallDetection?{stallDetection:!1}:e.stallWindowTurns!==void 0&&e.stallRepeatThreshold!==void 0?{stallDetection:{windowTurns:e.stallWindowTurns,repeatThreshold:e.stallRepeatThreshold}}:{},storage:d&&f?{session:{url:d},remote:{getAuth:async()=>({token:f})}}:{session:{dir:Le}},onMemoryConflict:(e,t)=>p.current?.(e,t)}));await Ne(`app.start()`,()=>m.start()),sr(m),J(Oe);let h=!1,g=()=>{h&&process.exit(1),h=!0,Promise.race([m.stop(),new Promise(e=>setTimeout(e,1e4))]).finally(()=>{e.mode===`interactive`&&Mt(),process.exit(1)})};process.on(`SIGTERM`,g),process.on(`SIGHUP`,g);let _,v=!1,y;if(e.attachSession){let t=process.env.OTTO_SERVICE_URL??`http://127.0.0.1:8417`,{runAttach:n}=await import(`./run-attach-Ci5jYyCa.js`);return await n({sessionId:e.attachSession,baseUrl:t,token:process.env.OTTO_SERVICE_TOKEN,forceWriteLease:e.forceWriteLease}),0}try{switch(e.mode){case`print`:await ar(e,m);break;case`json`:await or(e,m);break;case`interactive`:{await rr(m);let t=await nr(e,m,p);_=t.restart?.sessionId,v=!!t.restart?.memoryTriggered,y=t.restart?.resumePrompt;break}}}finally{let t=()=>{};process.on(`SIGINT`,t);let n=setTimeout(()=>{try{process.stdout.write(`\x1B[?25h`)}catch{}e.mode===`interactive`&&Mt(),process.exit(0)},1e4);try{await m.stop()}finally{clearTimeout(n),process.removeListener(`SIGINT`,t)}}if(_){process.removeListener(`SIGTERM`,g),process.removeListener(`SIGHUP`,g);let t=e.sessionUrl,n=e.sessionToken,r=()=>{},i,a=e=>{try{console.error(`\n[otto] 重启陪跑期父进程异常,终止子会话以避免孤儿挂起:${e instanceof Error?e.stack??e.message:String(e)}`)}catch{}try{i?.kill(`SIGTERM`)}catch{}process.exit(1)};return process.on(`SIGINT`,r),process.on(`SIGTERM`,r),process.on(`uncaughtException`,a),process.on(`unhandledRejection`,a),i=ve(process.execPath,fr(process.argv.slice(1),_,{sessionUrl:t,sessionToken:n,memoryRestartGrace:v,resumePrompt:y,execArgv:process.execArgv,generation:(e.restartGeneration??0)+1}),{stdio:`inherit`,env:{...process.env}}),i.on(`exit`,(e,t)=>{process.removeListener(`SIGINT`,r),process.removeListener(`SIGTERM`,r),process.removeListener(`uncaughtException`,a),process.removeListener(`unhandledRejection`,a),process.exit(e??(t?1:0))}),0}return e.mode===`interactive`&&(Mt(),process.exit(process.exitCode??0)),0}pr().then(e=>{e!==0&&(process.exitCode=e)}).catch(e=>{process.stderr.write(`otto: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1});export{pr as runCli};
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{Y as e}from"./command-dispatcher-BVGddstc.js";import{t}from"./version-C0qM-qJM.js";import{resolve as n}from"node:path";var r=e({SUB_COMMAND_NAMES:()=>i,getHelpLines:()=>c,parseCLI:()=>s});const i=new Set([`run`,`serve`,`daemon`,`doctor`,`config`,`migrate`,`auth`,`observe`,`debug`,`time-travel`,`mcp`,`persistenced`,`remote-persistence-server`,`extension`,`ps`,`feedback`]),a=new Map([{flags:[`--print`,`-p`],type:`mode`,value:`print`},{flags:[`--interactive`,`-i`],type:`mode`,value:`interactive`},{flags:[`--json`],type:`mode`,value:`json`},{flags:[`--model`,`-m`],type:`string`,key:`model`},{flags:[`--config`,`-c`],type:`string`,key:`configPath`},{flags:[`--project`,`-d`],type:`path`,key:`projectDir`},{flags:[`--quiet`,`-q`],type:`boolean`,key:`quiet`},{flags:[`--verbose`,`-v`],type:`boolean`,key:`verbose`},{flags:[`--max-tool-turns`],type:`number`,key:`maxToolTurns`},{flags:[`--max-tool-turn-extensions`],type:`number`,key:`maxToolTurnExtensions`},{flags:[`--prompt-token-budget`],type:`number`,key:`promptTokenBudget`},{flags:[`--prompt-time-budget`],type:`number`,key:`promptTimeBudgetMin`},{flags:[`--session-cost-budget`],type:`number`,key:`sessionCostBudget`},{flags:[`--no-stall-detection`],type:`boolean`,key:`noStallDetection`},{flags:[`--stall-window-turns`],type:`number`,key:`stallWindowTurns`},{flags:[`--stall-repeat-threshold`],type:`number`,key:`stallRepeatThreshold`},{flags:[`--continue`],type:`string`,key:`continueSession`},{flags:[`--attach`],type:`string`,key:`attachSession`},{flags:[`--force-write-lease`],type:`boolean`,key:`forceWriteLease`},{flags:[`--memory-restart-grace`],type:`boolean`,key:`memoryRestartGrace`},{flags:[`--resume-prompt`],type:`string`,key:`resumePrompt`},{flags:[`--session-url`],type:`string`,key:`sessionUrl`},{flags:[`--session-token`],type:`string`,key:`sessionToken`},{flags:[`--id`],type:`string`,key:`workspaceId`},{flags:[`--shadow`],type:`boolean`,key:`shadow`},{flags:[`--help`,`-h`],type:`boolean`,key:`showHelp`},{flags:[`--version`],type:`action`,handler:l}].flatMap(e=>e.flags.map(t=>[t,e])));var o=class{i;constructor(e){this.args=e,this.i=0}current(){return this.args[this.i]}next(){return this.args[++this.i]}advance(){this.i++}skip(e){this.i+=e}pos(){return this.i}};function s(e){let t=e.slice(2),r=new o(t),s={mode:`interactive`,projectDir:process.cwd(),verbose:!1,quiet:!1},c=r.current(),l,u=``,d,f;c&&i.has(c)?(l=c,u=t.slice(1).join(` `),r.skip(1),l===`run`&&(s.prompt=t.slice(1).filter(e=>!e.startsWith(`-`)).join(` `),s.mode=`print`)):c&&!c.startsWith(`-`)&&(d=c,f=t.slice(1));let p=s.prompt?[s.prompt]:[];for(;r.current()!==void 0;){let e=r.current();if(e===`--inspect`){s.inspect=!0,r.advance();continue}if(e?.startsWith(`--inspect=`)){let t=Number(e.slice(10));s.inspect=Number.isInteger(t)&&t>0?t:!0,r.advance();continue}if(e?.startsWith(`--restart-generation=`)){let t=Number(e.slice(21));Number.isInteger(t)&&t>0&&(s.restartGeneration=t),r.advance();continue}let t=a.get(e);if(t){switch(r.advance(),t.type){case`boolean`:s[t.key]=!0;break;case`mode`:s.mode=t.value;break;case`string`:s[t.key]=r.current(),r.advance();break;case`number`:s[t.key]=Number(r.current()),r.advance();break;case`path`:s[t.key]=n(r.current()??process.cwd()),r.advance();break;case`action`:t.handler();break}continue}e&&!e.startsWith(`-`)&&!l&&(s.prompt===void 0&&s.mode===`interactive`&&(s.mode=`print`),p.push(e)),r.advance()}return p.length>0&&(s.prompt=p.join(` `)),{options:s,subCommand:l,subCommandArgs:u,unresolvedCommandName:d,unresolvedCommandArgs:f}}function c(){return'(otto - AI 助理命令行工具((用法:( otto [提示词] 使用提示词启动(print 模式)( otto 进入交互式 TUI 模式( otto --json "query" JSON 输出模式((选项:( -i, --interactive Interactive 模式(默认)( -p, --print Print 模式(非交互)( --json JSON 输出模式( -m, --model <id> 指定模型( -c, --config <path> 配置文件路径( -d, --project <dir> 项目目录( -v, --verbose 输出详细日志( -q, --quiet 只输出 error 日志( --shadow 影子模式:otto 自有状态(凭据/会话/记忆/教训/配置/trace/日志)本次会话零磁盘写入(不保证 provider 服务端日志与 shell/OS 层痕迹;RFC-345)( --max-tool-turns <n> 单个用户回合最大工具回合数(默认 120)( --max-tool-turn-extensions <n> 触顶后压缩续跑的扩展次数(默认主会话 3 / 子 agent 0)( --prompt-token-budget <n> 单回合输出 token 预算(配置后轮次上限 ×4 退位安全阀;RFC-104)( --prompt-time-budget <min> 单回合墙钟时间预算(分钟)( --session-cost-budget <usd> 会话累计成本软预算(美元,超过一次性提醒不阻断;RFC-204)( --no-stall-detection 关闭早期停滞检测(默认开启;RFC-203)( --stall-window-turns <n> 停滞检测滑动窗口大小(需与 --stall-repeat-threshold 同时提供,默认 8)( --stall-repeat-threshold <n> 停滞检测同签名重复阈值(需与 --stall-window-turns 同时提供,默认 4)( --continue <id> 继续已有会话( --session-url <url> 远端会话持久化地址(如 http://host:3001/sessions)( --session-token <token> 远端会话持久化 Bearer token( --inspect[=port] 启用 Node.js inspector(默认: 9229)( -h, --help 显示帮助( --version 显示版本((命令:( otto run <prompt> 执行一次性任务( otto serve [--port N] [--inspect] [--static <dir>] [--token <t>] 启动 HTTP/WS service(--static 同源托管前端 SPA,--token 启用鉴权)( otto doctor [--summary|--json] 环境健康检查(环境/配置/存储状态/连通性)( otto auth login <provider> 登录(cursor / anthropic / openai-codex / github-copilot)( otto auth status 查看各 provider 凭据来源( otto auth logout <provider> 注销并清除凭据( otto config export [--project] [-o <path>] 导出配置(RFC-219)( otto config import <file> [--dry-run] [--scope global|project] [--no-plugins] [--plugins-only] [--yes] 导入配置( otto config restore [--list] 撤销最近一次导入( otto migrate export [--no-sessions] [-o <path>] 导出配置+插件清单+会话数据为迁移包(换电脑用)( otto migrate import <archive> [--no-sessions] 导入迁移包(目标已有会话数据时跳过会话部分)( otto observe <action> <id> 观测面板(summary / timeline / spans)( otto debug <action> [...] 调试面板(breakpoints / points / state)( otto time-travel <action> <id> 时间旅行(checkpoints / scrubber / restore / fork / replay)( otto mcp login <name> MCP server OAuth 登录( otto mcp logout <name> 登出 MCP server( otto mcp list 列出已认证的 MCP server( otto extension create <name> 生成插件骨架(命令 + 面板 + manifest,开箱即用)( otto extension install <name> [--yes] 安装首方/自定义插件(anthropic-provider / deepseek-provider / browser-use / …)( otto extension update [name] 检查并重装已过期的已安装 skill/plugin( otto persistenced --dir <path> --token <token> [...flags] 启动独立持久化服务(storage + events + sync)( otto remote-persistence-server [...flags] 启动最小化远程持久化服务(5 REST 端点)( otto ps [--sweep] [--include-weak] [--json] 进程群列表与孤儿清扫(SIGTERM only,RFC-196)((面板命令默认连 `otto serve` 实例(http://127.0.0.1:8417,OTTO_SERVICE_URL/--remote 可覆盖)。'.split(`(`)}function l(){process.stdout.write(`otto ${t()}\n`),process.exit(0)}export{s as n,r,i as t};
3
- //# sourceMappingURL=parse-cli-cYMjnAum.js.map
2
+ import{Y as e}from"./command-dispatcher-BVGddstc.js";import{t}from"./version-C0qM-qJM.js";import{resolve as n}from"node:path";var r=e({SUB_COMMAND_NAMES:()=>i,getHelpLines:()=>c,parseCLI:()=>s});const i=new Set([`run`,`serve`,`daemon`,`doctor`,`config`,`migrate`,`auth`,`observe`,`debug`,`time-travel`,`mcp`,`persistenced`,`remote-persistence-server`,`extension`,`ps`,`feedback`]),a=new Map([{flags:[`--print`,`-p`],type:`mode`,value:`print`},{flags:[`--interactive`,`-i`],type:`mode`,value:`interactive`},{flags:[`--json`],type:`mode`,value:`json`},{flags:[`--model`,`-m`],type:`string`,key:`model`},{flags:[`--config`,`-c`],type:`string`,key:`configPath`},{flags:[`--project`,`-d`],type:`path`,key:`projectDir`},{flags:[`--quiet`,`-q`],type:`boolean`,key:`quiet`},{flags:[`--verbose`],type:`boolean`,key:`verbose`},{flags:[`--max-tool-turns`],type:`number`,key:`maxToolTurns`},{flags:[`--max-tool-turn-extensions`],type:`number`,key:`maxToolTurnExtensions`},{flags:[`--prompt-token-budget`],type:`number`,key:`promptTokenBudget`},{flags:[`--prompt-time-budget`],type:`number`,key:`promptTimeBudgetMin`},{flags:[`--session-cost-budget`],type:`number`,key:`sessionCostBudget`},{flags:[`--no-stall-detection`],type:`boolean`,key:`noStallDetection`},{flags:[`--stall-window-turns`],type:`number`,key:`stallWindowTurns`},{flags:[`--stall-repeat-threshold`],type:`number`,key:`stallRepeatThreshold`},{flags:[`--continue`],type:`string`,key:`continueSession`},{flags:[`--attach`],type:`string`,key:`attachSession`},{flags:[`--force-write-lease`],type:`boolean`,key:`forceWriteLease`},{flags:[`--memory-restart-grace`],type:`boolean`,key:`memoryRestartGrace`},{flags:[`--resume-prompt`],type:`string`,key:`resumePrompt`},{flags:[`--session-url`],type:`string`,key:`sessionUrl`},{flags:[`--session-token`],type:`string`,key:`sessionToken`},{flags:[`--id`],type:`string`,key:`workspaceId`},{flags:[`--shadow`],type:`boolean`,key:`shadow`},{flags:[`--help`,`-h`],type:`boolean`,key:`showHelp`},{flags:[`--version`,`-v`],type:`action`,handler:l}].flatMap(e=>e.flags.map(t=>[t,e])));var o=class{i;constructor(e){this.args=e,this.i=0}current(){return this.args[this.i]}next(){return this.args[++this.i]}advance(){this.i++}skip(e){this.i+=e}pos(){return this.i}};function s(e){let t=e.slice(2),r=new o(t),s={mode:`interactive`,projectDir:process.cwd(),verbose:!1,quiet:!1},c=r.current(),l,u=``,d,f;c&&i.has(c)?(l=c,u=t.slice(1).join(` `),r.skip(1),l===`run`&&(s.prompt=t.slice(1).filter(e=>!e.startsWith(`-`)).join(` `),s.mode=`print`)):c&&!c.startsWith(`-`)&&(d=c,f=t.slice(1));let p=s.prompt?[s.prompt]:[];for(;r.current()!==void 0;){let e=r.current();if(e===`--inspect`){s.inspect=!0,r.advance();continue}if(e?.startsWith(`--inspect=`)){let t=Number(e.slice(10));s.inspect=Number.isInteger(t)&&t>0?t:!0,r.advance();continue}if(e?.startsWith(`--restart-generation=`)){let t=Number(e.slice(21));Number.isInteger(t)&&t>0&&(s.restartGeneration=t),r.advance();continue}let t=a.get(e);if(t){switch(r.advance(),t.type){case`boolean`:s[t.key]=!0;break;case`mode`:s.mode=t.value;break;case`string`:s[t.key]=r.current(),r.advance();break;case`number`:s[t.key]=Number(r.current()),r.advance();break;case`path`:s[t.key]=n(r.current()??process.cwd()),r.advance();break;case`action`:t.handler();break}continue}e&&!e.startsWith(`-`)&&!l&&(s.prompt===void 0&&s.mode===`interactive`&&(s.mode=`print`),p.push(e)),r.advance()}return p.length>0&&(s.prompt=p.join(` `)),{options:s,subCommand:l,subCommandArgs:u,unresolvedCommandName:d,unresolvedCommandArgs:f}}function c(){return'(otto - AI 助理命令行工具((用法:( otto [提示词] 使用提示词启动(print 模式)( otto 进入交互式 TUI 模式( otto --json "query" JSON 输出模式((选项:( -i, --interactive Interactive 模式(默认)( -p, --print Print 模式(非交互)( --json JSON 输出模式( -m, --model <id> 指定模型( -c, --config <path> 配置文件路径( -d, --project <dir> 项目目录( --verbose 输出详细日志( -q, --quiet 只输出 error 日志( --shadow 影子模式:otto 自有状态(凭据/会话/记忆/教训/配置/trace/日志)本次会话零磁盘写入(不保证 provider 服务端日志与 shell/OS 层痕迹;RFC-345)( --max-tool-turns <n> 单个用户回合最大工具回合数(默认 120)( --max-tool-turn-extensions <n> 触顶后压缩续跑的扩展次数(默认主会话 3 / 子 agent 0)( --prompt-token-budget <n> 单回合输出 token 预算(配置后轮次上限 ×4 退位安全阀;RFC-104)( --prompt-time-budget <min> 单回合墙钟时间预算(分钟)( --session-cost-budget <usd> 会话累计成本软预算(美元,超过一次性提醒不阻断;RFC-204)( --no-stall-detection 关闭早期停滞检测(默认开启;RFC-203)( --stall-window-turns <n> 停滞检测滑动窗口大小(需与 --stall-repeat-threshold 同时提供,默认 8)( --stall-repeat-threshold <n> 停滞检测同签名重复阈值(需与 --stall-window-turns 同时提供,默认 4)( --continue <id> 继续已有会话( --session-url <url> 远端会话持久化地址(如 http://host:3001/sessions)( --session-token <token> 远端会话持久化 Bearer token( --inspect[=port] 启用 Node.js inspector(默认: 9229)( -h, --help 显示帮助( --version, -v 显示版本((命令:( otto run <prompt> 执行一次性任务( otto serve [--port N] [--inspect] [--static <dir>] [--token <t>] 启动 HTTP/WS service(--static 同源托管前端 SPA,--token 启用鉴权)( otto doctor [--summary|--json] 环境健康检查(环境/配置/存储状态/连通性)( otto auth login <provider> 登录(cursor / anthropic / openai-codex / github-copilot)( otto auth status 查看各 provider 凭据来源( otto auth logout <provider> 注销并清除凭据( otto config export [--project] [-o <path>] 导出配置(RFC-219)( otto config import <file> [--dry-run] [--scope global|project] [--no-plugins] [--plugins-only] [--yes] 导入配置( otto config restore [--list] 撤销最近一次导入( otto migrate export [--no-sessions] [-o <path>] 导出配置+插件清单+会话数据为迁移包(换电脑用)( otto migrate import <archive> [--no-sessions] 导入迁移包(目标已有会话数据时跳过会话部分)( otto observe <action> <id> 观测面板(summary / timeline / spans)( otto debug <action> [...] 调试面板(breakpoints / points / state)( otto time-travel <action> <id> 时间旅行(checkpoints / scrubber / restore / fork / replay)( otto mcp login <name> MCP server OAuth 登录( otto mcp logout <name> 登出 MCP server( otto mcp list 列出已认证的 MCP server( otto extension create <name> 生成插件骨架(命令 + 面板 + manifest,开箱即用)( otto extension install <name> [--yes] 安装首方/自定义插件(anthropic-provider / deepseek-provider / browser-use / …)( otto extension update [name] 检查并重装已过期的已安装 skill/plugin( otto persistenced --dir <path> --token <token> [...flags] 启动独立持久化服务(storage + events + sync)( otto remote-persistence-server [...flags] 启动最小化远程持久化服务(5 REST 端点)( otto ps [--sweep] [--include-weak] [--json] 进程群列表与孤儿清扫(SIGTERM only,RFC-196)((面板命令默认连 `otto serve` 实例(http://127.0.0.1:8417,OTTO_SERVICE_URL/--remote 可覆盖)。'.split(`(`)}function l(){process.stdout.write(`otto ${t()}\n`),process.exit(0)}export{s as n,r,i as t};
3
+ //# sourceMappingURL=parse-cli-C6cLzKhy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-cli-cYMjnAum.js","names":[],"sources":["../src/parse-cli.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport type { CLIOptions, RunMode } from './types'\nimport { getVersion } from './version'\n\nexport type SubCommand = 'run' | 'serve' | 'daemon' | 'doctor' | 'config' | 'migrate' | 'auth' | 'observe' | 'debug' | 'time-travel' | 'mcp' | 'persistenced' | 'remote-persistence-server' | 'extension' | 'ps' | 'feedback'\n\nexport interface ParsedCLI {\n options: CLIOptions\n /** 未命中任何内建子命令时为 `undefined`(而非 `null` 哨兵——与 SUB_COMMAND_NAMES 的\n * 元素类型保持一致,消费方无需 `.filter(n => n !== null)` 剔除哨兵值)。 */\n subCommand: SubCommand | undefined\n subCommandArgs: string\n /**\n * RFC-112 D2:内建 `SUB_COMMAND_NAMES` 未命中的第一个位置参数(候选插件 CLI 命令名,\n * 如 `otto feishu ...` 里的 `\"feishu\"`)。`undefined` 表示第一个参数已命中内建命令,\n * 或压根没有位置参数。**不改变** `options.prompt`/`subCommand` 的既有构建逻辑——\n * 这两者仍然按\"当作 prompt\"的旧行为完整计算好,供插件命令名查无匹配时零改动回退。\n */\n unresolvedCommandName?: string\n /**\n * 与 `unresolvedCommandName` 配对:该候选名之后的**原始** args(未做 flag 过滤,含 `-h`\n * 等字面量),只在插件命令表命中该名字时使用(透传给插件可执行文件)。\n */\n unresolvedCommandArgs?: string[]\n}\n\n/** RFC-112 D2:导出供 `cli.ts` 构建插件 CLI 命令表时用作保留字集合(插件不得覆盖)。 */\nexport const SUB_COMMAND_NAMES = new Set<SubCommand>([\n 'run', 'serve', 'daemon', 'doctor', 'config', 'migrate', 'auth', 'observe', 'debug', 'time-travel', 'mcp', 'persistenced', 'remote-persistence-server', 'extension', 'ps', 'feedback',\n])\n\ntype OptionEntry =\n | { flags: string[]; type: 'boolean'; key: keyof CLIOptions }\n | { flags: string[]; type: 'mode'; value: RunMode }\n | { flags: string[]; type: 'string'; key: keyof CLIOptions }\n | { flags: string[]; type: 'number'; key: keyof CLIOptions }\n | { flags: string[]; type: 'path'; key: keyof CLIOptions }\n | { flags: string[]; type: 'action'; handler: () => void }\n\nconst OPTIONS: OptionEntry[] = [\n { flags: ['--print', '-p'], type: 'mode', value: 'print' },\n { flags: ['--interactive', '-i'], type: 'mode', value: 'interactive' },\n { flags: ['--json'], type: 'mode', value: 'json' },\n { flags: ['--model', '-m'], type: 'string', key: 'model' },\n { flags: ['--config', '-c'], type: 'string', key: 'configPath' },\n { flags: ['--project', '-d'], type: 'path', key: 'projectDir' },\n { flags: ['--quiet', '-q'], type: 'boolean', key: 'quiet' },\n { flags: ['--verbose', '-v'], type: 'boolean', key: 'verbose' },\n { flags: ['--max-tool-turns'], type: 'number', key: 'maxToolTurns' },\n { flags: ['--max-tool-turn-extensions'], type: 'number', key: 'maxToolTurnExtensions' },\n { flags: ['--prompt-token-budget'], type: 'number', key: 'promptTokenBudget' },\n { flags: ['--prompt-time-budget'], type: 'number', key: 'promptTimeBudgetMin' },\n { flags: ['--session-cost-budget'], type: 'number', key: 'sessionCostBudget' },\n { flags: ['--no-stall-detection'], type: 'boolean', key: 'noStallDetection' },\n { flags: ['--stall-window-turns'], type: 'number', key: 'stallWindowTurns' },\n { flags: ['--stall-repeat-threshold'], type: 'number', key: 'stallRepeatThreshold' },\n { flags: ['--continue'], type: 'string', key: 'continueSession' },\n { flags: ['--attach'], type: 'string', key: 'attachSession' },\n { flags: ['--force-write-lease'], type: 'boolean', key: 'forceWriteLease' },\n // RFC-115 M3(P1-1 修正):仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——\n // 区分\"内存压力触发的自动重启\"与\"用户手动 otto --continue\",前者才应起算 D5 宽限期。\n { flags: ['--memory-restart-grace'], type: 'boolean', key: 'memoryRestartGrace' },\n // RFC-115 M4:仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——重启前\n // 会话正忙时的续跑原文,子进程启动后自动重新提交为续跑轮。\n { flags: ['--resume-prompt'], type: 'string', key: 'resumePrompt' },\n { flags: ['--session-url'], type: 'string', key: 'sessionUrl' },\n { flags: ['--session-token'], type: 'string', key: 'sessionToken' },\n { flags: ['--id'], type: 'string', key: 'workspaceId' },\n { flags: ['--shadow'], type: 'boolean', key: 'shadow' },\n { flags: ['--help', '-h'], type: 'boolean', key: 'showHelp' },\n { flags: ['--version'], type: 'action', handler: printVersion },\n]\n\nconst OPTION_LOOKUP: Map<string, OptionEntry> = new Map(\n OPTIONS.flatMap(e => e.flags.map(f => [f, e] as const)),\n)\n\nclass ArgCursor {\n private i: number\n constructor(private args: string[]) {\n this.i = 0\n }\n current(): string | undefined { return this.args[this.i] }\n next(): string | undefined { return this.args[++this.i] }\n advance(): void { this.i++ }\n skip(count: number): void { this.i += count }\n pos(): number { return this.i }\n}\n\nexport function parseCLI(argv: string[]): ParsedCLI {\n const args = argv.slice(2)\n const cursor = new ArgCursor(args)\n\n const options: CLIOptions = {\n mode: 'interactive',\n projectDir: process.cwd(),\n verbose: false,\n quiet: false,\n }\n\n const first = cursor.current()\n let subCommand: SubCommand | undefined\n let subCommandArgs = ''\n let unresolvedCommandName: string | undefined\n let unresolvedCommandArgs: string[] | undefined\n if (first && SUB_COMMAND_NAMES.has(first as SubCommand)) {\n subCommand = first as SubCommand\n subCommandArgs = args.slice(1).join(' ')\n cursor.skip(1)\n\n if (subCommand === 'run') {\n options.prompt = args.slice(1).filter(a => !a.startsWith('-')).join(' ')\n options.mode = 'print'\n }\n } else if (first && !first.startsWith('-')) {\n // RFC-112 D2:第一个位置参数不是内建命令,也不以 `-` 开头(不是 flag)——\n // 记录为候选插件 CLI 命令名,供 cli.ts 查插件表二次判定;不改变下方现有的\n // \"当作 prompt\" 逻辑(该逻辑仍会照常把 first 纳入 promptParts,回退路径零改动)。\n unresolvedCommandName = first\n unresolvedCommandArgs = args.slice(1)\n }\n\n let promptParts: string[] = options.prompt ? [options.prompt] : []\n\n while (cursor.current() !== undefined) {\n const arg = cursor.current()!\n\n if (arg === '--inspect') {\n options.inspect = true\n cursor.advance()\n continue\n }\n if (arg?.startsWith('--inspect=')) {\n const port = Number(arg.slice('--inspect='.length))\n options.inspect = Number.isInteger(port) && port > 0 ? port : true\n cursor.advance()\n continue\n }\n // RFC-196 M3:重启代际计数(chaperone 重启 spawn 注入,不文档化——内部可观测标记,\n // 供 ≥3 代告警与 otto ps GEN 列展示;不驱动任何行为分支)。\n if (arg?.startsWith('--restart-generation=')) {\n const gen = Number(arg.slice('--restart-generation='.length))\n if (Number.isInteger(gen) && gen > 0) options.restartGeneration = gen\n cursor.advance()\n continue\n }\n\n const entry = OPTION_LOOKUP.get(arg)\n if (entry) {\n cursor.advance()\n switch (entry.type) {\n case 'boolean':\n ;(options as unknown as Record<string, unknown>)[entry.key] = true\n break\n case 'mode':\n options.mode = entry.value\n break\n case 'string':\n ;(options as unknown as Record<string, unknown>)[entry.key] = cursor.current()\n cursor.advance()\n break\n case 'number':\n ;(options as unknown as Record<string, unknown>)[entry.key] = Number(cursor.current())\n cursor.advance()\n break\n case 'path':\n ;(options as unknown as Record<string, unknown>)[entry.key] = resolve(cursor.current() ?? process.cwd())\n cursor.advance()\n break\n case 'action':\n entry.handler()\n break\n }\n continue\n }\n\n if (arg && !arg.startsWith('-') && !subCommand) {\n if (options.prompt === undefined && options.mode === 'interactive') {\n options.mode = 'print'\n }\n promptParts.push(arg)\n }\n cursor.advance()\n }\n\n if (promptParts.length > 0) {\n options.prompt = promptParts.join(' ')\n }\n\n return { options, subCommand, subCommandArgs, unresolvedCommandName, unresolvedCommandArgs }\n}\n\n/** 帮助文本行(供 plain-text printHelp 与 TUI InfoDialog 共用)。 */\nexport function getHelpLines(): string[] {\n return [\n '',\n 'otto - AI 助理命令行工具',\n '',\n '用法:',\n ' otto [提示词] 使用提示词启动(print 模式)',\n ' otto 进入交互式 TUI 模式',\n ' otto --json \"query\" JSON 输出模式',\n '',\n '选项:',\n ' -i, --interactive Interactive 模式(默认)',\n ' -p, --print Print 模式(非交互)',\n ' --json JSON 输出模式',\n ' -m, --model <id> 指定模型',\n ' -c, --config <path> 配置文件路径',\n ' -d, --project <dir> 项目目录',\n ' -v, --verbose 输出详细日志',\n ' -q, --quiet 只输出 error 日志',\n ' --shadow 影子模式:otto 自有状态(凭据/会话/记忆/教训/配置/trace/日志)本次会话零磁盘写入(不保证 provider 服务端日志与 shell/OS 层痕迹;RFC-345)',\n ' --max-tool-turns <n> 单个用户回合最大工具回合数(默认 120)',\n ' --max-tool-turn-extensions <n> 触顶后压缩续跑的扩展次数(默认主会话 3 / 子 agent 0)',\n ' --prompt-token-budget <n> 单回合输出 token 预算(配置后轮次上限 ×4 退位安全阀;RFC-104)',\n ' --prompt-time-budget <min> 单回合墙钟时间预算(分钟)',\n ' --session-cost-budget <usd> 会话累计成本软预算(美元,超过一次性提醒不阻断;RFC-204)',\n ' --no-stall-detection 关闭早期停滞检测(默认开启;RFC-203)',\n ' --stall-window-turns <n> 停滞检测滑动窗口大小(需与 --stall-repeat-threshold 同时提供,默认 8)',\n ' --stall-repeat-threshold <n> 停滞检测同签名重复阈值(需与 --stall-window-turns 同时提供,默认 4)',\n ' --continue <id> 继续已有会话',\n ' --session-url <url> 远端会话持久化地址(如 http://host:3001/sessions)',\n ' --session-token <token> 远端会话持久化 Bearer token',\n ' --inspect[=port] 启用 Node.js inspector(默认: 9229)',\n ' -h, --help 显示帮助',\n ' --version 显示版本',\n '',\n '命令:',\n ' otto run <prompt> 执行一次性任务',\n ' otto serve [--port N] [--inspect] [--static <dir>] [--token <t>] 启动 HTTP/WS service(--static 同源托管前端 SPA,--token 启用鉴权)',\n ' otto doctor [--summary|--json] 环境健康检查(环境/配置/存储状态/连通性)',\n ' otto auth login <provider> 登录(cursor / anthropic / openai-codex / github-copilot)',\n ' otto auth status 查看各 provider 凭据来源',\n ' otto auth logout <provider> 注销并清除凭据',\n ' otto config export [--project] [-o <path>] 导出配置(RFC-219)',\n ' otto config import <file> [--dry-run] [--scope global|project] [--no-plugins] [--plugins-only] [--yes] 导入配置',\n ' otto config restore [--list] 撤销最近一次导入',\n ' otto migrate export [--no-sessions] [-o <path>] 导出配置+插件清单+会话数据为迁移包(换电脑用)',\n ' otto migrate import <archive> [--no-sessions] 导入迁移包(目标已有会话数据时跳过会话部分)',\n ' otto observe <action> <id> 观测面板(summary / timeline / spans)',\n ' otto debug <action> [...] 调试面板(breakpoints / points / state)',\n ' otto time-travel <action> <id> 时间旅行(checkpoints / scrubber / restore / fork / replay)',\n ' otto mcp login <name> MCP server OAuth 登录',\n ' otto mcp logout <name> 登出 MCP server',\n ' otto mcp list 列出已认证的 MCP server',\n ' otto extension create <name> 生成插件骨架(命令 + 面板 + manifest,开箱即用)',\n ' otto extension install <name> [--yes] 安装首方/自定义插件(anthropic-provider / deepseek-provider / browser-use / …)',\n ' otto extension update [name] 检查并重装已过期的已安装 skill/plugin',\n ' otto persistenced --dir <path> --token <token> [...flags] 启动独立持久化服务(storage + events + sync)',\n ' otto remote-persistence-server [...flags] 启动最小化远程持久化服务(5 REST 端点)',\n ' otto ps [--sweep] [--include-weak] [--json] 进程群列表与孤儿清扫(SIGTERM only,RFC-196)',\n '',\n '面板命令默认连 `otto serve` 实例(http://127.0.0.1:8417,OTTO_SERVICE_URL/--remote 可覆盖)。',\n ]\n}\n\nfunction printVersion(): void {\n process.stdout.write(`otto ${getVersion()}\\n`)\n process.exit(0)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parse-cli-C6cLzKhy.js","names":[],"sources":["../src/parse-cli.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport type { CLIOptions, RunMode } from './types'\nimport { getVersion } from './version'\n\nexport type SubCommand = 'run' | 'serve' | 'daemon' | 'doctor' | 'config' | 'migrate' | 'auth' | 'observe' | 'debug' | 'time-travel' | 'mcp' | 'persistenced' | 'remote-persistence-server' | 'extension' | 'ps' | 'feedback'\n\nexport interface ParsedCLI {\n options: CLIOptions\n /** 未命中任何内建子命令时为 `undefined`(而非 `null` 哨兵——与 SUB_COMMAND_NAMES 的\n * 元素类型保持一致,消费方无需 `.filter(n => n !== null)` 剔除哨兵值)。 */\n subCommand: SubCommand | undefined\n subCommandArgs: string\n /**\n * RFC-112 D2:内建 `SUB_COMMAND_NAMES` 未命中的第一个位置参数(候选插件 CLI 命令名,\n * 如 `otto feishu ...` 里的 `\"feishu\"`)。`undefined` 表示第一个参数已命中内建命令,\n * 或压根没有位置参数。**不改变** `options.prompt`/`subCommand` 的既有构建逻辑——\n * 这两者仍然按\"当作 prompt\"的旧行为完整计算好,供插件命令名查无匹配时零改动回退。\n */\n unresolvedCommandName?: string\n /**\n * 与 `unresolvedCommandName` 配对:该候选名之后的**原始** args(未做 flag 过滤,含 `-h`\n * 等字面量),只在插件命令表命中该名字时使用(透传给插件可执行文件)。\n */\n unresolvedCommandArgs?: string[]\n}\n\n/** RFC-112 D2:导出供 `cli.ts` 构建插件 CLI 命令表时用作保留字集合(插件不得覆盖)。 */\nexport const SUB_COMMAND_NAMES = new Set<SubCommand>([\n 'run', 'serve', 'daemon', 'doctor', 'config', 'migrate', 'auth', 'observe', 'debug', 'time-travel', 'mcp', 'persistenced', 'remote-persistence-server', 'extension', 'ps', 'feedback',\n])\n\ntype OptionEntry =\n | { flags: string[]; type: 'boolean'; key: keyof CLIOptions }\n | { flags: string[]; type: 'mode'; value: RunMode }\n | { flags: string[]; type: 'string'; key: keyof CLIOptions }\n | { flags: string[]; type: 'number'; key: keyof CLIOptions }\n | { flags: string[]; type: 'path'; key: keyof CLIOptions }\n | { flags: string[]; type: 'action'; handler: () => void }\n\nconst OPTIONS: OptionEntry[] = [\n { flags: ['--print', '-p'], type: 'mode', value: 'print' },\n { flags: ['--interactive', '-i'], type: 'mode', value: 'interactive' },\n { flags: ['--json'], type: 'mode', value: 'json' },\n { flags: ['--model', '-m'], type: 'string', key: 'model' },\n { flags: ['--config', '-c'], type: 'string', key: 'configPath' },\n { flags: ['--project', '-d'], type: 'path', key: 'projectDir' },\n { flags: ['--quiet', '-q'], type: 'boolean', key: 'quiet' },\n { flags: ['--verbose'], type: 'boolean', key: 'verbose' },\n { flags: ['--max-tool-turns'], type: 'number', key: 'maxToolTurns' },\n { flags: ['--max-tool-turn-extensions'], type: 'number', key: 'maxToolTurnExtensions' },\n { flags: ['--prompt-token-budget'], type: 'number', key: 'promptTokenBudget' },\n { flags: ['--prompt-time-budget'], type: 'number', key: 'promptTimeBudgetMin' },\n { flags: ['--session-cost-budget'], type: 'number', key: 'sessionCostBudget' },\n { flags: ['--no-stall-detection'], type: 'boolean', key: 'noStallDetection' },\n { flags: ['--stall-window-turns'], type: 'number', key: 'stallWindowTurns' },\n { flags: ['--stall-repeat-threshold'], type: 'number', key: 'stallRepeatThreshold' },\n { flags: ['--continue'], type: 'string', key: 'continueSession' },\n { flags: ['--attach'], type: 'string', key: 'attachSession' },\n { flags: ['--force-write-lease'], type: 'boolean', key: 'forceWriteLease' },\n // RFC-115 M3(P1-1 修正):仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——\n // 区分\"内存压力触发的自动重启\"与\"用户手动 otto --continue\",前者才应起算 D5 宽限期。\n { flags: ['--memory-restart-grace'], type: 'boolean', key: 'memoryRestartGrace' },\n // RFC-115 M4:仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——重启前\n // 会话正忙时的续跑原文,子进程启动后自动重新提交为续跑轮。\n { flags: ['--resume-prompt'], type: 'string', key: 'resumePrompt' },\n { flags: ['--session-url'], type: 'string', key: 'sessionUrl' },\n { flags: ['--session-token'], type: 'string', key: 'sessionToken' },\n { flags: ['--id'], type: 'string', key: 'workspaceId' },\n { flags: ['--shadow'], type: 'boolean', key: 'shadow' },\n { flags: ['--help', '-h'], type: 'boolean', key: 'showHelp' },\n { flags: ['--version', '-v'], type: 'action', handler: printVersion },\n]\n\nconst OPTION_LOOKUP: Map<string, OptionEntry> = new Map(\n OPTIONS.flatMap(e => e.flags.map(f => [f, e] as const)),\n)\n\nclass ArgCursor {\n private i: number\n constructor(private args: string[]) {\n this.i = 0\n }\n current(): string | undefined { return this.args[this.i] }\n next(): string | undefined { return this.args[++this.i] }\n advance(): void { this.i++ }\n skip(count: number): void { this.i += count }\n pos(): number { return this.i }\n}\n\nexport function parseCLI(argv: string[]): ParsedCLI {\n const args = argv.slice(2)\n const cursor = new ArgCursor(args)\n\n const options: CLIOptions = {\n mode: 'interactive',\n projectDir: process.cwd(),\n verbose: false,\n quiet: false,\n }\n\n const first = cursor.current()\n let subCommand: SubCommand | undefined\n let subCommandArgs = ''\n let unresolvedCommandName: string | undefined\n let unresolvedCommandArgs: string[] | undefined\n if (first && SUB_COMMAND_NAMES.has(first as SubCommand)) {\n subCommand = first as SubCommand\n subCommandArgs = args.slice(1).join(' ')\n cursor.skip(1)\n\n if (subCommand === 'run') {\n options.prompt = args.slice(1).filter(a => !a.startsWith('-')).join(' ')\n options.mode = 'print'\n }\n } else if (first && !first.startsWith('-')) {\n // RFC-112 D2:第一个位置参数不是内建命令,也不以 `-` 开头(不是 flag)——\n // 记录为候选插件 CLI 命令名,供 cli.ts 查插件表二次判定;不改变下方现有的\n // \"当作 prompt\" 逻辑(该逻辑仍会照常把 first 纳入 promptParts,回退路径零改动)。\n unresolvedCommandName = first\n unresolvedCommandArgs = args.slice(1)\n }\n\n let promptParts: string[] = options.prompt ? [options.prompt] : []\n\n while (cursor.current() !== undefined) {\n const arg = cursor.current()!\n\n if (arg === '--inspect') {\n options.inspect = true\n cursor.advance()\n continue\n }\n if (arg?.startsWith('--inspect=')) {\n const port = Number(arg.slice('--inspect='.length))\n options.inspect = Number.isInteger(port) && port > 0 ? port : true\n cursor.advance()\n continue\n }\n // RFC-196 M3:重启代际计数(chaperone 重启 spawn 注入,不文档化——内部可观测标记,\n // 供 ≥3 代告警与 otto ps GEN 列展示;不驱动任何行为分支)。\n if (arg?.startsWith('--restart-generation=')) {\n const gen = Number(arg.slice('--restart-generation='.length))\n if (Number.isInteger(gen) && gen > 0) options.restartGeneration = gen\n cursor.advance()\n continue\n }\n\n const entry = OPTION_LOOKUP.get(arg)\n if (entry) {\n cursor.advance()\n switch (entry.type) {\n case 'boolean':\n ;(options as unknown as Record<string, unknown>)[entry.key] = true\n break\n case 'mode':\n options.mode = entry.value\n break\n case 'string':\n ;(options as unknown as Record<string, unknown>)[entry.key] = cursor.current()\n cursor.advance()\n break\n case 'number':\n ;(options as unknown as Record<string, unknown>)[entry.key] = Number(cursor.current())\n cursor.advance()\n break\n case 'path':\n ;(options as unknown as Record<string, unknown>)[entry.key] = resolve(cursor.current() ?? process.cwd())\n cursor.advance()\n break\n case 'action':\n entry.handler()\n break\n }\n continue\n }\n\n if (arg && !arg.startsWith('-') && !subCommand) {\n if (options.prompt === undefined && options.mode === 'interactive') {\n options.mode = 'print'\n }\n promptParts.push(arg)\n }\n cursor.advance()\n }\n\n if (promptParts.length > 0) {\n options.prompt = promptParts.join(' ')\n }\n\n return { options, subCommand, subCommandArgs, unresolvedCommandName, unresolvedCommandArgs }\n}\n\n/** 帮助文本行(供 plain-text printHelp 与 TUI InfoDialog 共用)。 */\nexport function getHelpLines(): string[] {\n return [\n '',\n 'otto - AI 助理命令行工具',\n '',\n '用法:',\n ' otto [提示词] 使用提示词启动(print 模式)',\n ' otto 进入交互式 TUI 模式',\n ' otto --json \"query\" JSON 输出模式',\n '',\n '选项:',\n ' -i, --interactive Interactive 模式(默认)',\n ' -p, --print Print 模式(非交互)',\n ' --json JSON 输出模式',\n ' -m, --model <id> 指定模型',\n ' -c, --config <path> 配置文件路径',\n ' -d, --project <dir> 项目目录',\n ' --verbose 输出详细日志',\n ' -q, --quiet 只输出 error 日志',\n ' --shadow 影子模式:otto 自有状态(凭据/会话/记忆/教训/配置/trace/日志)本次会话零磁盘写入(不保证 provider 服务端日志与 shell/OS 层痕迹;RFC-345)',\n ' --max-tool-turns <n> 单个用户回合最大工具回合数(默认 120)',\n ' --max-tool-turn-extensions <n> 触顶后压缩续跑的扩展次数(默认主会话 3 / 子 agent 0)',\n ' --prompt-token-budget <n> 单回合输出 token 预算(配置后轮次上限 ×4 退位安全阀;RFC-104)',\n ' --prompt-time-budget <min> 单回合墙钟时间预算(分钟)',\n ' --session-cost-budget <usd> 会话累计成本软预算(美元,超过一次性提醒不阻断;RFC-204)',\n ' --no-stall-detection 关闭早期停滞检测(默认开启;RFC-203)',\n ' --stall-window-turns <n> 停滞检测滑动窗口大小(需与 --stall-repeat-threshold 同时提供,默认 8)',\n ' --stall-repeat-threshold <n> 停滞检测同签名重复阈值(需与 --stall-window-turns 同时提供,默认 4)',\n ' --continue <id> 继续已有会话',\n ' --session-url <url> 远端会话持久化地址(如 http://host:3001/sessions)',\n ' --session-token <token> 远端会话持久化 Bearer token',\n ' --inspect[=port] 启用 Node.js inspector(默认: 9229)',\n ' -h, --help 显示帮助',\n ' --version, -v 显示版本',\n '',\n '命令:',\n ' otto run <prompt> 执行一次性任务',\n ' otto serve [--port N] [--inspect] [--static <dir>] [--token <t>] 启动 HTTP/WS service(--static 同源托管前端 SPA,--token 启用鉴权)',\n ' otto doctor [--summary|--json] 环境健康检查(环境/配置/存储状态/连通性)',\n ' otto auth login <provider> 登录(cursor / anthropic / openai-codex / github-copilot)',\n ' otto auth status 查看各 provider 凭据来源',\n ' otto auth logout <provider> 注销并清除凭据',\n ' otto config export [--project] [-o <path>] 导出配置(RFC-219)',\n ' otto config import <file> [--dry-run] [--scope global|project] [--no-plugins] [--plugins-only] [--yes] 导入配置',\n ' otto config restore [--list] 撤销最近一次导入',\n ' otto migrate export [--no-sessions] [-o <path>] 导出配置+插件清单+会话数据为迁移包(换电脑用)',\n ' otto migrate import <archive> [--no-sessions] 导入迁移包(目标已有会话数据时跳过会话部分)',\n ' otto observe <action> <id> 观测面板(summary / timeline / spans)',\n ' otto debug <action> [...] 调试面板(breakpoints / points / state)',\n ' otto time-travel <action> <id> 时间旅行(checkpoints / scrubber / restore / fork / replay)',\n ' otto mcp login <name> MCP server OAuth 登录',\n ' otto mcp logout <name> 登出 MCP server',\n ' otto mcp list 列出已认证的 MCP server',\n ' otto extension create <name> 生成插件骨架(命令 + 面板 + manifest,开箱即用)',\n ' otto extension install <name> [--yes] 安装首方/自定义插件(anthropic-provider / deepseek-provider / browser-use / …)',\n ' otto extension update [name] 检查并重装已过期的已安装 skill/plugin',\n ' otto persistenced --dir <path> --token <token> [...flags] 启动独立持久化服务(storage + events + sync)',\n ' otto remote-persistence-server [...flags] 启动最小化远程持久化服务(5 REST 端点)',\n ' otto ps [--sweep] [--include-weak] [--json] 进程群列表与孤儿清扫(SIGTERM only,RFC-196)',\n '',\n '面板命令默认连 `otto serve` 实例(http://127.0.0.1:8417,OTTO_SERVICE_URL/--remote 可覆盖)。',\n ]\n}\n\nfunction printVersion(): void {\n process.stdout.write(`otto ${getVersion()}\\n`)\n process.exit(0)\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x-otto/cli",
3
- "version": "0.0.1-alpha.5",
3
+ "version": "0.0.1-alpha.6",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",