@x-otto/cli 0.0.1-alpha.6 → 0.0.1-alpha.7
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/build-id-DMyumG97.js +3 -0
- package/dist/build-id-DMyumG97.js.map +1 -0
- package/dist/command-dispatcher-8fY1u4JK.js +13 -0
- package/dist/command-dispatcher-8fY1u4JK.js.map +1 -0
- package/dist/extension-plugin-BjY-x3u8.js +2 -0
- package/dist/{extension-plugin-DB-bWOIf.js → extension-plugin-CmbXorFQ.js} +3 -3
- package/dist/{extension-plugin-DB-bWOIf.js.map → extension-plugin-CmbXorFQ.js.map} +1 -1
- package/dist/{feedback-BES_6ebi.js → feedback-7qQsiabD.js} +2 -2
- package/dist/{feedback-BES_6ebi.js.map → feedback-7qQsiabD.js.map} +1 -1
- package/dist/feedback-Cc1eBsqy.js +2 -0
- package/dist/index.js +2 -2
- package/dist/model-auth-2NUt5hk2.js +2 -0
- package/dist/{model-auth-BlaZzUUK.js → model-auth-BBZiDkoe.js} +2 -2
- package/dist/{model-auth-BlaZzUUK.js.map → model-auth-BBZiDkoe.js.map} +1 -1
- package/dist/{parse-cli-C6cLzKhy.js → parse-cli-OVUmdm5d.js} +2 -2
- package/dist/{parse-cli-C6cLzKhy.js.map → parse-cli-OVUmdm5d.js.map} +1 -1
- package/dist/{version-C0qM-qJM.js → version-DaMJKLwj.js} +2 -2
- package/dist/{version-C0qM-qJM.js.map → version-DaMJKLwj.js.map} +1 -1
- package/package.json +2 -2
- package/dist/build-id-BX4QHzM0.js +0 -3
- package/dist/build-id-BX4QHzM0.js.map +0 -1
- package/dist/command-dispatcher-BVGddstc.js +0 -13
- package/dist/command-dispatcher-BVGddstc.js.map +0 -1
- package/dist/extension-plugin-DoKKFxRC.js +0 -2
- package/dist/feedback-BRbLUn9u.js +0 -2
- package/dist/model-auth-B95mFA-O.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-id-DMyumG97.js","names":[],"sources":["../src/build-id.ts"],"sourcesContent":["// auto-generated by scripts/gen-build-id.mjs — DO NOT EDIT\nexport const BUILD_ID = 4570\nexport const BUILD_BRANCH = 'dev'\nexport const BUILD_HASH = 'e60abd89a'\n"],"mappings":";AACA,MAAa,EAAW,KAEX,EAAa"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{t as e}from"./build-id-DMyumG97.js";import{t}from"./version-DaMJKLwj.js";import{t as n}from"./discover-with-bundled-CznLjkkw.js";import{n as r,r as i,t as a}from"./service-client-BLNeugM9.js";import{n as o}from"./extension-BKXIr86F.js";import{a as s,i as c,r as l,s as u}from"./extension-plugin-CmbXorFQ.js";import{n as d,r as f,t as p}from"./model-auth-BBZiDkoe.js";import{t as m}from"./proxy-evg7ZvoD.js";import{i as h}from"./install-DlVJRHRT.js";import{n as g,t as _}from"./registry-D0NONjLv.js";import{n as ee,t as v}from"./feedback-7qQsiabD.js";import{createRequire as te}from"node:module";import{arch as ne,cpus as re,freemem as ie,homedir as ae,platform as oe,release as y,totalmem as b}from"node:os";import{execFile as se,execSync as ce,spawn as le,spawnSync as ue}from"node:child_process";import{DEFAULT_WORKSPACE_KEY as de,INDUCTOR_PLUGIN_ID as x,PLUGIN_MANIFEST_FILENAME as fe,checkUpgrades as pe,collectPluginPerfMetrics as me,detectProjectConfigGating as he,discoverFileCommands as ge,evaluateClaudeTrust as _e,evaluatePluginTrust as ve,findWorkspaceRoot as ye,getLastAssistantText as S,parsePluginManifest as be,readSkillLoopStatus as xe,resolvePackageDir as Se,resolveSessionTitle as Ce,scanInstalledVersions as we,trustProject as Te,untrustPlugin as Ee,untrustProject as De}from"@x-otto/coding";import{checkShellCommand as Oe,openBrowser as ke,readFileCapped as Ae}from"@x-otto/shared";import{BUILD_ID as je,OTTO_HOME as Me,SDK_VERSION as Ne}from"@x-otto/env";import{dirname as C,join as w,relative as Pe,resolve as T}from"node:path";import{closeSync as Fe,existsSync as E,openSync as Ie,readFileSync as Le,readSync as Re,readdirSync as ze,statSync as D}from"node:fs";import{FIGURES as O,buildTurnSummary as Be,createBuiltinThemeRegistry as Ve,createReducerState as He,deriveTurnBoundaries as Ue,detectLanguage as We,formatProviderUsageLimitTypeFull as Ge,i18next as k,initI18n as Ke,insertTurnSummaries as qe,reduceToTui as Je}from"@x-otto/tui";import{createBuiltinCommands as Ye}from"@x-otto/tui/compat";import{MaxToolTurnsError as Xe,PromptBudgetExceededError as A}from"@x-otto/agent";import{readFile as Ze,stat as Qe,unlink as $e}from"node:fs/promises";import{DEFAULT_COMPACTION_CONFIG as et,DEFAULT_PRUNE_CONFIG as tt,estimateTokensHeuristic as nt,resolveContextSize as rt}from"@x-otto/memory";import{classifyAuthErrorType as it,computeCacheHitRatio as at,createModelUsabilityGate as ot,getToolCallsByAssistantMessage as st,isAuthError as ct}from"@x-otto/ai";import{promisify as lt}from"node:util";var ut=Object.defineProperty,dt=(e,t)=>{let n={};for(var r in e)ut(n,r,{get:e[r],enumerable:!0});return t||ut(n,Symbol.toStringTag,{value:`Module`}),n},j=te(import.meta.url);function ft(e){return`⚠ 已达工具回合上限(${e.extensions>0?`约 ${e.effectiveMaxTurns} 次(含 ${e.extensions} 次自动扩展,每次 ${e.maxTurns})`:`${e.maxTurns} 次`}),提前停止——任务可能未完成。\n 重试可加 --max-tool-turns <n>(每轮预算,实际上限 ≈ n×${1+e.extensions};如 --max-tool-turns ${e.maxTurns*2})。\n 注:配置了 --prompt-token-budget 时轮次窗口自动 ×4(此处报的是放大后的有效值)。`}function pt(e,t){let n=S(e.session.messages())||t.partialText,r=ft(t);return n?`${n}\n${r}`:r}function mt(e){let t=e.dimension===`tokens`?`输出 token 预算 ${e.used}/${e.budget}`:`时间预算 ${Math.round(e.used/1e3)}s/${Math.round(e.budget/1e3)}s`;return`⚠ 已达本回合${e.dimension===`tokens`?`输出 token`:`墙钟时间`}预算(${t}),提前停止——任务可能未完成。\n 重试可加 ${e.dimension===`tokens`?`--prompt-token-budget <n>`:`--prompt-time-budget <分钟>`} 提升预算。`}function ht(e,t){let n=S(e.session.messages())||t.partialText,r=mt(t);return n?`${n}\n${r}`:r}async function M(e,t,n={}){let{writer:r,tui:i=!1,tuiOptions:a,onTurnEnd:o}=typeof n==`function`?{writer:n}:n,s=r??(e=>process.stdout.write(`${e}\n`)),c=Date.now();try{await e.prompt(t)}catch(t){if(t instanceof Xe||t instanceof A){let n=t instanceof A,r=n?mt(t):ft(t);o?.(n?`budget-exceeded`:`max-tool-turns`,r);let l=o?S(e.session.messages())||t.partialText:n?ht(e,t):pt(e,t);if(i){let{printMessages:t}=await import(`@x-otto/tui`);t(e.session.messages(),{...a,startTime:c,contextWindow:0}),s(l)}else s(l);return l}throw t}if(o&&e.budgetSteeredThisPrompt&&o(`max-tool-turns`,`⚠ 已达工具回合上限——已自动收尾本回合(任务可能未全部完成,可继续指示我,或加 --max-tool-turns 提升预算)。`),i){let{printMessages:t}=await import(`@x-otto/tui`),n=e.session.messages();return t(n,{...a,startTime:c,contextWindow:e.model.contextWindow??0}),S(n)}let l=S(e.session.messages());return s(l),l}async function gt(e,t){try{await e.prompt(t)}catch(t){if(t instanceof Xe)return{sessionId:e.id,status:`max_turns`,messageCount:e.session.messages().length,response:S(e.session.messages())||t.partialText};if(t instanceof A)return{sessionId:e.id,status:`budget_exceeded`,messageCount:e.session.messages().length,response:S(e.session.messages())||t.partialText};throw t}return{sessionId:e.id,status:e.status,messageCount:e.session.messages().length,response:S(e.session.messages())}}var N=class{commandRegistry;modelList=[];currentModelId;onModelChange;constructor(e,t={}){this.session=e,this.modelList=t.models??[],this.currentModelId=t.currentModel,this.onModelChange=t.onModelChange,this.commandRegistry=Ye()}getRegistry(){return this.commandRegistry}abort(){this.session.abort()}async handleInput(e){if(this.session.status===`archived`)return{type:`system`,text:`此会话已归档(archived),无法发送新消息。使用 /resume 切换到其他会话。`};let t=e.trim();if(t.length===0)return{type:`noop`};if(t.startsWith(`!`)){let e=t.slice(1).trim();if(!e)return{type:`system`,text:`Usage: !<shell command>`};let n=Oe(e);if(!n.safe)return{type:`system`,text:`Refusing to execute dangerous command (${n.reason}): ${e}\nUse the bash tool via the agent for privileged operations.`};let r,i=!1;try{r=ce(e,{encoding:`utf-8`,timeout:3e4,cwd:this.session.workspaceDir,maxBuffer:1024*1024})}catch(e){let t=e;r=t.stderr||t.stdout||t.message||String(e),i=!0}return r=r.trimEnd(),this.session.session.append({role:`system`,subtype:`local_command`,level:i?`error`:`info`,content:r||`(no output)`,timestamp:Date.now()}),{type:`response`,text:r||`(no output)`}}if(t.startsWith(`@`)){let e=t.slice(1).trim();return e?{type:`response`,text:await M(this.session,`Read and analyze the file: ${e}`,{writer:()=>{}})}:{type:`system`,text:`Usage: @<file-path>`}}if(!t.startsWith(`/`)){let e,n;return{type:`response`,text:await M(this.session,t,{writer:()=>{},onTurnEnd:(t,r)=>{e=t,n=r}}),endReason:e,notice:n}}let[n,...r]=t.slice(1).split(/\s+/);if(!n){let{showCommandPalette:e}=await import(`@x-otto/tui`),t=await e(this.commandRegistry.list(),process.stdin,process.stdout);if(!t.command)return{type:`noop`};let n=this.commandRegistry.get(t.command);if(!n)return{type:`noop`};let r=await n.execute(t.args,{signal:new AbortController().signal,width:process.stdout.columns??80,models:this.modelList,currentModel:this.currentModelId,onModelChange:this.onModelChange});return this._handleCommandResult(r)}let i=r.join(` `),a=this.commandRegistry.find(n);if(!a)return{type:`system`,text:`Unknown command: /${n}. Try /help.`};let o=await a.execute(i,{signal:new AbortController().signal,width:process.stdout.columns??80,models:this.modelList,currentModel:this.currentModelId,onModelChange:this.onModelChange});return this._handleCommandResult(o)}_handleCommandResult(e){if(typeof e==`string`)return{type:`system`,text:e};switch(e.kind){case`exit`:return{type:`exit`,restart:e.restart};case`help`:return{type:`help`};case`clear`:return this.session.clearTurnPanels(),this.session.clearContext(),process.stdout.write(`\x1B[2J\x1B[H`),{type:`noop`};case`abort`:return this.session.abort(),{type:`system`,text:`Aborted current run.`};case`status`:return{type:`system`,text:`Session: ${this.session.id} | Status: ${this.session.status}`};case`copy`:return{type:`system`,text:`Copy not yet available in CLI mode.`};case`model`:return this.onModelChange?(this.onModelChange(e.modelId).then(e=>{process.stdout.write(e+`
|
|
3
|
+
`)}).catch(e=>{process.stdout.write(`Model switch failed: ${e instanceof Error?e.message:String(e)}\n`)}),{type:`system`,text:`Switching to ${e.modelId}...`}):{type:`system`,text:`Model switching not available.`}}}};function _t(){return We()}function vt(e=`auto`){let t=e===`auto`?We():e;return Ke(t),t}async function yt(e){try{let t=new AbortController,n=setTimeout(()=>t.abort(),5e3),r=await fetch(`https://registry.npmjs.org/%40x-otto%2Fcli/latest`,{signal:t.signal});if(clearTimeout(n),!r.ok)return null;let i=(await r.json())?.version??``;return i?{latest:i,current:e,newer:bt(i,e)>0}:null}catch{return null}}function bt(e,t){let n=xt(e),r=xt(t);if(!n||!r)return 0;for(let e=0;e<3;e++)if(n[e]!==r[e])return n[e]-r[e];return 0}function xt(e){let t=/(\d+)\.(\d+)\.(\d+)/.exec(e);return t?[Number(t[1]),Number(t[2]),Number(t[3])]:null}async function St(){return new Promise(e=>{try{let t=le(process.platform===`win32`?`npm.cmd`:`npm`,[`install`,`-g`,`@x-otto/cli@latest`],{stdio:`inherit`,shell:!0});t.on(`error`,t=>{e({ok:!1,error:t.message})}),t.on(`exit`,t=>{if(t!==0){e({ok:!1,error:`npm install exited with code ${t}`});return}e({ok:!0})})}catch(t){e({ok:!1,error:t.message})}})}function Ct(e){return e?Date.now()-e>216e5:!0}async function wt(e){let t=process.env.OTTO_UPGRADE_MOCK;if(t){let e=t===`force`;return{latest:e?`2.0.0`:`0.2.0`,current:`0.0.1`,newer:!0,forced:e}}return!e.autoCheck||!Ct(e.lastCheck)?null:yt(e.currentVersion).then(async t=>t&&(e.persistLastCheck().catch(()=>{}),t.newer)?{...t,forced:!1}:null).catch(()=>null)}const P=nt;let F,Tt;function Et(e){let t=e.map(e=>e.name).sort().join(`,`);if(F!==void 0&&Tt===t)return F;let n=e=>typeof e==`function`?`[fn]`:typeof e==`string`?e:``;return F=P(JSON.stringify(e.map(e=>({name:e.name,description:n(e.description),parameters:e.parameters})))),Tt=t,F}let I,Dt;function Ot(e){return I!==void 0&&Dt===e?I:(I=P(e),Dt=e,I)}function kt(e){let{systemPrompt:t,tools:n,lastIn:r,lastOut:i,lastCacheRead:a,lastCacheWrite:o,contextWindow:s,modelName:c=``,totIn:l=r,totOut:u=i,cost:d,messageCount:f=0,streamingOutputTokens:p=0}=e,m=Ot(t)+Et(n),h=a+o+r+i+p,g=Math.max(0,h-m),_=Math.max(0,s-m-g),ee=rt(tt.trigger,s),v=rt(et.trigger,s);return{modelName:c,contextWindow:s,contextPercent:s>0?h/s*100:0,overheadTokens:m,messageTokens:g,messageCount:f,totalUsed:h,free:_,pruneLine:ee,compactLine:v,lastInput:r,lastOutput:i,totalInput:l,totalOutput:u,cost:d,live:p>0}}const At={openai:`OpenAI`};function jt(e){let t=[`confirm`,`auto`,`bypass`];return t[(t.indexOf(e)+1)%t.length]??`confirm`}function Mt(e){return e===`error`?`error`:e===`approval_required`||e===`input_required`?`warning`:`info`}function Nt(e,t,n){let r=t===void 0?void 0:{code:t},i=r!==void 0&&ct(r),a=i&&it(r)===`refresh-failed`;return{authError:i||/\b401\b|authentication|unauthorized|api[\s_-]?key|invalid.*key/i.test(e),isRefreshFailed:a,unsupported:/model_not_supported|not\s+supported|invalid.*model|model.*invalid/i.test(e),rateLimit:/\b429\b|rate.limit|rate_limit|exceed.*rate/i.test(e),pluginSource:n}}function Pt(e){return e?e.toLowerCase()===`xhigh`?`XHigh`:e.charAt(0).toUpperCase()+e.slice(1):``}function Ft(e,t,n){return e?`${t.on} ${n.on}`:`${t.off} ${n.off}`}function L(e,t,n){if(!t)return`(no model)`;let r=Pt(n),i=r?`${t}·${r}`:t,a=e.modelRegistry.find(t)?.contextWindow;return a?`${i} (${a>=1e6?`${(a/1e6).toFixed(1)}M`:`${Math.round(a/1e3)}K`})`:i}function It(e,t){let n=[...ge(t.workspaceDir,t.activePlugins()),...t.computedPluginCommands()];for(let t of n)e.has(t.name)||e.register({name:t.name,description:t.description??`Project command (.claude/.otto)`,aliases:void 0,type:`action`,source:`builtin`,execute:()=>``});return n}function Lt(e){return{id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}}function Rt(e){return{type:`thinking`,thinking:e.text}}function zt(e){return{type:`text`,text:e.text}}function Bt(e){return{type:`a2ui`,version:e.version,components:e.components}}function Vt(e){let t=[],n=[];for(let r of e)switch(r.type){case`text`:r.text.trim()&&t.push(zt(r));break;case`thinking`:r.text.trim()&&t.push(Rt(r));break;case`tool_call`:n.push(Lt(r));break;case`a2ui`:t.push(Bt(r));break}return{content:t,toolCalls:n}}function Ht(e){return typeof e==`string`?e.trim():e.filter(e=>e.type===`text`).map(e=>e.text).join(``).trim()}function Ut(e){if(Object.keys(e).length===0)return;let t=e.command??e.path??e.file_path??e.pattern??e.query;return typeof t==`string`?t:JSON.stringify(e)}function R(e,t){let n=new Map,r=new Set;if(t?.toolCalls)for(let[e,r]of t.toolCalls)n.set(e,r);if(t?.resolvedIds)for(let e of t.resolvedIds)r.add(e);for(let t of e){let e=t;if(e?.role===`assistant`&&Array.isArray(e.content))for(let t of e.content)t.type===`tool_call`&&n.set(t.id,t);else e?.role===`tool_result`&&r.add(e.toolCallId)}let i=[];for(let t of e){let e=t;if(!(!e||typeof e.role!=`string`)&&!e.internal){if(e.role===`user`){let t=Ht(e.content);t&&i.push({role:`user`,content:t});continue}if(e.role===`assistant`){let{content:t}=Vt(e.content??[]);t.length>0&&i.push({role:`assistant`,content:t});for(let t of e.content??[])t.type===`tool_call`&&!r.has(t.id)&&i.push({role:`tool`,name:t.name,args:Ut(t.arguments),argsObj:t.arguments,result:void 0,isError:!1});continue}if(e.role===`tool_result`){let t=n.get(e.toolCallId),r=t?.arguments??{};i.push({role:`tool`,name:e.toolName||t?.name||`tool`,args:Ut(r),argsObj:r,result:Ht(e.content),isError:e.isError});continue}if(e.role===`system_notification`){let t=e;i.push({role:`tool_completion`,content:t.content,isError:t.isError??!1});continue}if(e.role===`system`){let t=e,n=typeof t.content==`string`?t.content:``;if(t.subtype===`model_switch`){i.push({role:`model_switch`,label:n});continue}if(t.subtype===`effort_switch`){i.push({role:`effort_switch`,label:n});continue}if(t.subtype===`run_paused`||t.subtype===`run_resumed`||t.subtype===`run_pause_cancelled`){i.push({role:t.subtype,label:n});continue}continue}}}return i}const Wt=lt(se);function Gt(e,t,n){for(let r of e){if(r.role!==`assistant`)continue;let e=st(r);for(let r of e){if(r.id!==t)continue;let e=r.arguments;if(n===`edit`)return{oldContent:typeof e.oldContent==`string`?e.oldContent:void 0,newContent:typeof e.newContent==`string`?e.newContent:void 0};if(n===`write`)return{newContent:typeof e.content==`string`?e.content:void 0}}}return{}}function Kt(e,t){let n=C(e),r=e=>{let t=ue(`git`,[...e],{cwd:n,timeout:5e3,encoding:`utf-8`,maxBuffer:10*1024*1024});return t.status===0?t.stdout:null},i;if(t!==`delete`)try{i=Le(e,`utf-8`)}catch{}let a,o=r([`ls-files`,`--full-name`,`--`,e]);if(o&&o.trim()){let e=r([`show`,`HEAD:${o.trim()}`]);e!==null&&(a=e)}return{oldContent:a,newContent:i}}async function qt(e,t){let n=C(e),r=async e=>{try{let{stdout:t}=await Wt(`git`,[...e],{cwd:n,encoding:`utf-8`,maxBuffer:10485760,signal:AbortSignal.timeout(5e3)});return{ok:!0,stdout:t}}catch{return{ok:!1,stdout:null}}},i;if(t!==`delete`)try{i=await Ze(e,`utf-8`)}catch{}let a,o=await r([`ls-files`,`--full-name`,`--`,e]);if(!o.ok)return t===`edit`?{error:`not a git repository (or git unavailable)`,newContent:i}:{oldContent:a,newContent:i};if(o.stdout&&o.stdout.trim()){let e=await r([`show`,`HEAD:${o.stdout.trim()}`]);e.ok&&e.stdout!==null&&(a=e.stdout)}return{oldContent:a,newContent:i}}function Jt(e){return[...e].sort((e,t)=>t.savedAt-e.savedAt)}function Yt(e,t){if(e!=null&&e.trim().length>0)return e.trim();let n=new Set(t.map(e=>e.name)),r=t.length+1,i=`draft-${r}`;for(;n.has(i);)r++,i=`draft-${r}`;return i}function Xt(e,t,n){let r=Date.now();return{id:`${r.toString(36)}-${Math.random().toString(36).slice(2,6)}`,name:Yt(e,n),text:t,savedAt:r}}function Zt(e){return e.length<=50?[...e]:e.slice(-50)}function z(e){let t=R(e.session.visibleMessages()),n=e.session.getTurnSummaries();return!n||n.length===0?t:qe(t,n,e.session.getTurnCount()??t.filter(e=>e.role===`user`).length)}function Qt(e){let{resumedNote:t,isFound:n,session:r,projState:i,tui:a}=e,o=z(r);a.messages.pushMessages(o),n&&o.length>0&&a.info.setTopView({session:r.id}),a.info.showToast(n?k.t(`cmd.titleSessionResumed`):k.t(`cmd.titleSession`),t.replace(/^↻ /,``)),$t({session:r,projState:i,tui:a,chatMsgs:o})}function $t(e){let{session:t,projState:n,tui:r}=e,i=e.chatMsgs??z(t);try{let e=t.session.getTodoList();e&&e.length>0&&!e.every(e=>e.status===`done`||e.status===`skipped`||e.status===`failed`)?(n.todoList=e.map(e=>({id:e.id,title:e.title,status:e.status,turn:e.turn})),r.stores.tasks.setTasks(e.map(e=>({id:e.id??``,title:e.title??``,status:e.status||`pending`,turn:e.turn})),void 0)):e&&e.length>0&&(t.session.setTodoList([]),r.info.showToast(k.t(`cmd.titleSession`),k.t(`cmd.resumeTodosAllDone`)));{let e=t.session.getTurnCount(),a=i.filter(e=>e.role===`user`).length,o=e??a;o>0&&(r.stores.tasks.setTurnBoundaries(Ue(i,o)),n.currentTurn=o)}let a=t.session.getEditedFiles();if(a&&a.length>0){let e=t.session.messages();r.stores.tasks.setEditedFiles(a.map(t=>{let n=t.operation,r=t.toolCallId?Gt(e,t.toolCallId,n):{};return r.oldContent===void 0&&r.newContent===void 0&&(r=Kt(t.path,n)),{path:t.path,operation:n,addedLines:t.addedLines,removedLines:t.removedLines,timestamp:t.timestamp,turnId:t.turnId,toolCallId:t.toolCallId,oldContent:r.oldContent,newContent:r.newContent}}))}let o=t.session.getSubagents();if(o&&o.length>0)for(let e of o)r.plugins.addSubagent({id:e.id,name:e.name,status:e.status,startedAt:e.startedAt});r.stores.tasks.setDrafts(Jt(t.session.getDrafts()??[]))}catch(e){console.error(`\x1b[90m\x1b[2m[resume] panel state restore skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}}const B=new Map;function en(e){return B.get(e)}function V(e){B.delete(e);let t=U.get(e);t&&(clearTimeout(t),U.delete(e))}function tn(){return[...B.values()]}function H(e,t,n){let r={id:e,transcript:R(t),streaming:``,status:n?`busy`:`idle`,lastActivityAt:Date.now()};return B.set(e,r),r}function nn(e,t){let n=B.get(e);n&&(n.transcript=R(t),n.lastActivityAt=Date.now())}const rn=new Set;function an(e){return rn.add(e),()=>{rn.delete(e)}}const U=new Map;function on(e){let t=U.get(e.id);t&&clearTimeout(t),U.set(e.id,setTimeout(()=>{U.delete(e.id);for(let t of rn)t(e)},300))}function sn(e,t){let n=``,r=t=>{e.status!==t&&(e.status=t,on(e))};return[i=>{if(i.type===`stream.event`&&i.event?.type===`text_delta`){n+=i.event.delta,e.streaming=n,e.lastActivityAt=Date.now();return}if(i.type===`prompt.end`){e.streaming=``,n=``,r(`idle`),nn(e.id,t());return}if(i.type===`error`){e.streaming=``,n=``,r(`idle`),e.lastActivityAt=Date.now();return}if(i.type===`approval.required`||i.type===`ask.user.required`){e.status=`needs-input`,e.pendingGate={type:i.type,id:String(i.id??``),data:i.data??{}},e.lastActivityAt=Date.now(),on(e);return}},()=>e]}function cn(e){let t=[`session ${e.session.id}`,`status ${e.session.status} · ${e.session.messageCount} messages · cursor ${e.cursor}`,`authority host=${e.authority.hostname} pid=${e.authority.pid}`];if(e.session.messages.length>0){t.push(`recent:`);for(let n of e.session.messages.slice(-3))t.push(` · ${typeof n==`object`&&n&&`role`in n?String(n.role):`message`} … ${JSON.stringify(n).slice(0,120)}`)}else t.push(`(无历史消息)`);return t.join(`
|
|
4
|
+
`)}async function ln(e,t){let n=e.join(` `).trim();if(!n){t.tui.info.showToast(`/session inspect`,"Usage: /session inspect <sessionId> —— peek a session running on `otto serve` (read-only snapshot)");return}let o=i(process.env.OTTO_SERVICE_URL??`http://127.0.0.1:8417`,globalThis.fetch,{token:process.env.OTTO_SERVICE_TOKEN}),s;try{s=await o.fetchSnapshot(n)}catch(e){if(e instanceof r){t.tui.info.showToast(`/session inspect`,`无法连接 otto serve:${e.message} —— 先 \`otto serve\`(或指定 --remote/OTTO_SERVICE_URL)`);return}if(e instanceof a){t.tui.info.showToast(`/session inspect`,`拉取 snapshot 失败:${e.message}`);return}t.tui.info.showToast(`/session inspect`,`查看失败:${e instanceof Error?e.message:String(e)}`);return}t.tui.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:`[session inspect]\n${cn(s)}`}]}),t.tui.info.showToast(`/session inspect`,`已查看会话 ${s.session.id}(只读快照;如需实时参与该会话请用 otto --attach ${s.session.id})`)}async function un(e,t){t.state.session.isBusy&&t.tui.info.showToast(`/clear`,`Aborting current task before clearing…`),t.state.todoList=[],t.callbacks.resetCurrentTurn(),t.callbacks.onContextCompacted(),t.state.session.clearTurnPanels(),await t.state.session.clearContext(),t.tui.lifecycle.clearSession();let n=t.state.session.model;n&&t.tui.stores.tasks.setModelName(L(t.app,n.id,t.state.session.thinkingLevel));let r=n?.contextWindow??2e5,i=kt({systemPrompt:t.state.session.systemPrompt,tools:t.state.session.tools,lastIn:0,lastOut:0,lastCacheRead:0,lastCacheWrite:0,contextWindow:r,modelName:n?.name??``,totIn:0,totOut:0});t.tui.stores.budget.setBudget(i),t.tui.stores.context.setBudget(i),t.tui.info.showToast(k.t(`cmd.titleCleared`),k.t(`cmd.clearedDone`))}async function dn(e,t){let n=e.join(` `).replace(/\s+/g,` `).trim();if(!n){t.tui.info.showToast(`/rename`,`Usage: /rename <new title>`);return}t.state.session.renameSession(n),t.tui.lifecycle.setTerminalTitle(n),t.tui.stores.tasks.setSessionTitle(n),t.tui.info.showToast(`✎`,n)}async function fn(e,t){let n,r,i=!1,a=!1;for(let t=0;t<e.length;t++)e[t]===`--workspace`&&t+1<e.length?r=e[++t]:e[t]===`--archived`?i=!0:e[t]===`--all`?a=!0:e[t].startsWith(`--`)||(n=e[t]);let o=r?{workspaceId:r}:void 0,s=await t.app.listAllSessions(o),c=s.filter(e=>e.status===`archived`).length,l=e=>{let t=(e.title??``).trim().toLowerCase();return t===`reply with: ok`||t===`reply with only your model name/identifier, nothing else.`||t.startsWith(`you are a trajectory analyst for an ai coding assistant.`)},u=s.filter(e=>e.status!==`archived`&&l(e)).length,d=n?s:s.filter(e=>i?e.status===`archived`:e.status!==`archived`).filter(e=>a||i||!l(e)).filter(e=>(e.entryCount??e.messageCount)>0),f=(e,t,n)=>e.tui.info.showToast(t,n),p=async e=>{if(e===t.state.session.id){f(t,k.t(`cmd.titleResume`),k.t(`cmd.resumeAlreadyOn`));return}let n=t.app.getSession(e)??await t.app.sessionManager.restore(e);if(!n){f(t,k.t(`cmd.titleResume`),k.t(`cmd.resumeSessionNotFound`,{idShort:e.slice(0,8)}));return}let r=t.state.session;if(t.state.session.isBusy){let[e]=sn(H(r.id,r.session.messages(),!0),()=>r.session.messages()),n=t.state.session.subscribe(t=>{e(t),(t.type===`prompt.end`||t.type===`error`)&&n()})}else H(r.id,r.session.messages(),!1);await t.callbacks.pasteBinder?.switchTo(r.id,n.id),t.callbacks.sessionUnsub?.(),t.state.session=n,t.state.interactive=new N(n,{models:t.state.models,currentModel:n.model?.id,onModelChange:t.callbacks.applyModel}),t.state.reg=t.state.interactive.getRegistry(),t.callbacks.registerAllTuiCommands(),t.state.slashCommands=t.callbacks.refreshSlashCommands(),t.tui.plugins.setCommands(t.state.slashCommands),t.callbacks.attachSessionHandler();let i=n.model?.id;i?(t.state.currentModelId=i,t.state.modelReady=!0,t.tui.stores.tasks.setModelName(L(t.app,i,t.state.session.thinkingLevel))):(t.state.currentModelId=void 0,t.state.modelReady=!1,t.tui.stores.tasks.setModelName(`(no model)`)),t.tui.lifecycle.clearSession();let a=en(n.id);if(a)t.tui.messages.pushMessages(a.transcript),V(n.id);else{let e=z(n);t.tui.messages.pushMessages(e)}t.callbacks.restoreSwitchedSession(),t.tui.info.setTopView({session:n.id}),f(t,k.t(`cmd.titleResume`),k.t(`cmd.resumeSwitched`,{idShort:e.slice(0,8),count:n.session.messages().length}))};if(n){let e=d.find(e=>e.id===n);if(e){await p(e.id);return}let r=d.find(e=>e.id.startsWith(n));if(r){await p(r.id);return}let i=d.find(e=>e.id.includes(n));if(i){await p(i.id);return}f(t,k.t(`cmd.titleResume`),k.t(`cmd.sessionNoMatch`,{arg:n}));return}if(d.length===0){f(t,k.t(`cmd.titleResume`),k.t(`cmd.resumeNoSaved`));return}let m=t.state.session.id,h=d.some(e=>e.pinned);function g(e){if(!e.pinned)return``;let t=e.pinGroup?.trim();return t?`\u0001${t.toLowerCase()}`:`\0`}let _=[...d].sort((e,t)=>{let n=g(e).localeCompare(g(t));if(n!==0)return n;let r=e.updatedAt?.getTime()??e.createdAt.getTime();return(t.updatedAt?.getTime()??t.createdAt.getTime())-r});function ee(e){if(h)return e.pinned?e.pinGroup?.trim()||k.t(`cmd.resumeDefaultPinGroup`):k.t(`cmd.resumeRecentGroup`)}function v(e){if(!e)return``;let t=Math.max(0,Math.floor((Date.now()-e.getTime())/1e3));return t<10?k.t(`cmd.agoJustNow`):t<60?k.t(`cmd.agoSeconds`,{n:t}):t<3600?k.t(`cmd.agoMinutes`,{n:Math.floor(t/60)}):t<86400?k.t(`cmd.agoHours`,{n:Math.floor(t/3600)}):k.t(`cmd.agoDays`,{n:Math.floor(t/86400)})}let te=d[0]?.updatedAt?v(d[0].updatedAt):`—`,ne=d.reduce((e,t)=>e+(t.messageCount??0),0),re=r?` [workspace: ${r}]`:``,ie=[!i&&c>0?k.t(`cmd.resumeArchivedHiddenHint`,{count:c}):``,!i&&!a&&u>0?k.t(`cmd.resumeProbeHiddenHint`,{count:u}):``].filter(Boolean),ae=ie.length>0?` ${ie.join(` `)}`:``,oe=new Map(tn().map(e=>[e.id,e])),y=0,b=0,se=e=>{if(e.id===m)return``;let n=oe.get(e.id);return n?n.status===`busy`?(y++,`● ${k.t(`cmd.resumeStatusBusy`)} · `):n.status===`needs-input`?(b++,`● ${k.t(`cmd.resumeStatusNeedsInput`)} · `):`· ${k.t(`cmd.resumeStatusIdle`)} · `:t.app.getSession(e.id)?.isBusy?(y++,`● ${k.t(`cmd.resumeStatusBusy`)} · `):``},ce=[y>0?`${y} ${k.t(`cmd.resumeStatusBusy`)}`:``,b>0?`${b} ${k.t(`cmd.resumeStatusNeedsInput`)}`:``].filter(Boolean).join(`, `),le=ce?` · ${ce}`:``,ue=k.t(`cmd.resumeSubtitle`,{sessions:d.length,msgs:ne,recent:te})+le+ae,de=i?k.t(`cmd.resumeArchivedOnlyTitle`,{n:d.length}):k.t(`cmd.resumeSelectTitle`,{n:d.length});t.tui.modal.openModal({kind:`select`,title:de+re,subtitle:ue,searchable:!0,maxVisible:13,options:_.map(e=>{let t=e.id===m?`●`:` `,n=e.pinned?k.t(`cmd.resumePinnedPrefix`):``,r=e.title||e.id.slice(0,8),i=e.status===`archived`?k.t(`cmd.resumeArchivedSuffix`):``,a=e.writeLocked?k.t(`cmd.resumeReadOnlySuffix`):``,o=`${n}${r}${i}`,s=v(e.updatedAt),c=[se(e).trim(),s,k.t(`welcome.msgCountLabel`,{count:e.messageCount??0}),a.trim()].filter(Boolean);return{label:`${t} ${o}`,trailingLabel:c.join(` · `),value:e.id,searchText:o,group:ee(e)}}),detailPlacement:`inline`,onSelect:e=>{p(e).catch(e=>f(t,k.t(`cmd.titleResume`),k.t(`cmd.resumeFailed`,{msg:e instanceof Error?e.message:String(e)})))},onCancel:()=>{}})}async function pn(e,t){t.app.reloadCapabilities().then(e=>{t.tui.plugins.setPluginRegistrations(t.app.getPluginRegistrations()),t.tui.info.showToast(k.t(`cmd.titleReload`),k.t(`cmd.reloadDone`,{mcpTools:e.mcpTools,models:e.models,agents:e.agents,teams:e.teams}))},e=>t.tui.messages.pushMessage({role:`command_echo`,command:`/reload`,status:`error`,summary:k.t(`cmd.reloadFailed`,{msg:e instanceof Error?e.message:String(e)})}))}async function mn(e,t){let n=t.app.diagnoser.propose();if(n.length===0){t.tui.info.showToast(k.t(`cmd.titleDiagnose`),k.t(`cmd.diagnoseNone`));return}let r=n.map((e,t)=>k.t(`cmd.diagnoseLine`,{n:t+1,signalKind:e.evidence.signalKind,count:e.evidence.count,directive:e.directive}));t.tui.messages.pushMessage({role:`command_echo`,command:`/diagnose`,status:`warn`,summary:k.t(`cmd.diagnoseSummary`,{count:n.length}),detail:r.join(`
|
|
5
|
+
`)})}async function hn(e,t){let n=e[0];if(n){let e=t.app.listSessions(),r=e.find(e=>e.id===n)??e.find(e=>e.id.startsWith(n))??e.find(e=>e.id.includes(n));if(!r){t.tui.info.showToast(k.t(`cmd.titleArchive`),k.t(`cmd.sessionNoMatch`,{arg:n}));return}if(r.status===`archived`){let e=t.app.getSession(r.id);if(!e){t.tui.info.showToast(k.t(`cmd.titleUnarchive`),k.t(`cmd.unarchiveNotLoaded`,{idShort:r.id.slice(0,8)}));return}e.unarchive(),t.tui.info.showToast(k.t(`cmd.titleUnarchive`),k.t(`cmd.unarchiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}));return}if(!await t.app.archiveSession(r.id)){t.tui.info.showToast(k.t(`cmd.titleArchive`),k.t(`cmd.archiveCannot`,{idShort:r.id.slice(0,8)}));return}t.tui.info.showToast(k.t(`cmd.titleArchive`),k.t(`cmd.archiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}));return}let r=t.state.session;if(r.status===`archived`){r.unarchive(),t.tui.info.showToast(k.t(`cmd.titleUnarchive`),k.t(`cmd.unarchiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}));return}r.archive(),t.tui.info.showToast(k.t(`cmd.titleArchive`),k.t(`cmd.archiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}))}async function gn(e,t){let n,r=[];for(let i=0;i<e.length;i++)if(e[i]===`--group`){let r=e[i+1];if(r===void 0||r.startsWith(`--`)){t.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.pinGroupMissingValue`));return}n=r,i++}else r.push(e[i]);if(r.length===0&&n===void 0){let e=t.state.session;e.pinned?(e.unpin(),t.tui.info.showToast(k.t(`cmd.titleUnpin`),k.t(`cmd.unpinDone`,{idShort:e.id.slice(0,8),title:e.title??``}))):(e.pin(),t.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.pinDone`,{idShort:e.id.slice(0,8),title:e.title??``}))),W(t);return}if(r.length===0){_n(t.state.session.id,n,t),W(t);return}if(r.length===1){_n(r[0],n,t),W(t);return}let i=t.app.listSessions(),a=0,o=[];for(let e of r){let r=i.find(t=>t.id===e)??i.find(t=>t.id.startsWith(e))??i.find(t=>t.id.includes(e));if(!r){o.push(e.slice(0,8));continue}let s=t.app.getSession(r.id);if(!s){o.push(r.id.slice(0,8));continue}s.pin(n),a++}t.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.pinBatchSummary`,{seg:o.length>0?`${a} pinned (${o.length} not found: ${o.join(`, `)})`:`${a} pinned`})),W(t)}function W(e){let t=e.callbacks.refreshSlashCommands();e.tui.plugins.setCommands(t)}function _n(e,t,n){if(e===n.state.session.id){vn(n.state.session,t,n);return}let r=n.app.listSessions(),i=r.find(t=>t.id===e)??r.find(t=>t.id.startsWith(e))??r.find(t=>t.id.includes(e));if(!i){n.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.sessionNoMatch`,{arg:e}));return}let a=n.app.getSession(i.id);if(!a){n.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.pinNotLoaded`,{idShort:i.id.slice(0,8)}));return}vn(a,t,n)}function vn(e,t,n){let r=e.id.slice(0,8),i=e.title??``;if(e.pinned){if(t===void 0||(e.pinGroup??``).toLowerCase()===t.toLowerCase()){e.unpin(),n.tui.info.showToast(k.t(`cmd.titleUnpin`),k.t(`cmd.unpinDone`,{idShort:r,title:i}));return}e.pin(t),n.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.pinGroupDone`,{idShort:r,title:i,group:t}));return}e.pin(t),t===void 0?n.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.pinDone`,{idShort:r,title:i})):n.tui.info.showToast(k.t(`cmd.titlePin`),k.t(`cmd.pinGroupDone`,{idShort:r,title:i,group:t}))}async function yn(e,t){let n=e[0];if(n===`fork`){await bn(e.slice(1),t);return}if(n===`kill`){await Tn(e.slice(1),t);return}if(n===`inspect`){await ln(e.slice(1),t);return}if(n!==`unlock`){t.tui.info.showToast(k.t(`cmd.titleSessionCmd`),`Usage: /session fork | /session unlock <id> [--force] | /session kill <id> | /session inspect <id>`);return}let r=e.slice(1),i=r.includes(`--force`),a=r.find(e=>e!==`--force`);if(!a){t.tui.info.showToast(k.t(`cmd.titleSessionUnlock`),k.t(`cmd.unlockUsage`));return}let o=t.app.sessionManager.inspectSessionWriteLease(a),s=a.slice(0,8);if(!o.locked){t.tui.info.showToast(k.t(`cmd.titleSessionUnlock`),k.t(`cmd.unlockNotLocked`,{idShort:s}));return}let c=o.alive===!0?k.t(`cmd.unlockAliveConfirmed`):o.alive===!1?k.t(`cmd.unlockDeadConfirmed`):k.t(`cmd.unlockUnknownAlive`),l=Math.round((o.mtimeAgoMs??0)/1e3);if(!i){t.tui.messages.pushMessage({role:`command_echo`,command:`/session unlock`,summary:k.t(`cmd.unlockInspect`,{idShort:s,pid:o.pid,hostname:o.hostname,aliveLabel:c,mtimeAgoSec:l})});return}if(o.alive===!0){o.mtimeAgoMs!==void 0&&o.mtimeAgoMs>6e4&&t.tui.messages.pushMessage({role:`command_echo`,command:`/session unlock --force`,status:`warn`,summary:k.t(`cmd.unlockHungWarning`,{idShort:s})}),t.tui.modal.openModal({kind:`confirm`,title:k.t(`cmd.unlockConfirmTitle`),message:k.t(`cmd.unlockConfirmMessage`,{idShort:s,pid:o.pid,hostname:o.hostname}),confirmLabel:k.t(`cmd.unlockConfirmLabel`),cancelLabel:k.t(`cmd.unlockCancelLabel`),dangerous:!0,onConfirm:()=>{t.app.sessionManager.forceReleaseSessionWriteLease(a),t.tui.info.showToast(k.t(`cmd.titleSessionUnlock`),k.t(`cmd.unlockForcedDone`,{idShort:s}))},onCancel:()=>{t.tui.info.showToast(k.t(`cmd.titleSessionUnlock`),k.t(`cmd.unlockCancelled`))}});return}(o.mtimeAgoMs??0)<5e3&&t.tui.messages.pushMessage({role:`command_echo`,command:`/session unlock --force`,status:`warn`,summary:k.t(`cmd.unlockRecentReleaseHint`,{idShort:s})}),t.app.sessionManager.forceReleaseSessionWriteLease(a),t.tui.info.showToast(k.t(`cmd.titleSessionUnlock`),k.t(`cmd.unlockForcedDone`,{idShort:s}))}async function bn(e,t){let n=t.state.session.id,r=await t.app.sessionManager.forkSession(n);if(!r){t.tui.info.showToast(k.t(`cmd.titleSessionFork`),k.t(`cmd.forkFailed`));return}let i=t.state.session;if(t.state.session.isBusy){let[e]=sn(H(i.id,i.session.messages(),!0),()=>i.session.messages()),n=t.state.session.subscribe(t=>{e(t),(t.type===`prompt.end`||t.type===`error`)&&n()})}else H(i.id,i.session.messages(),!1);t.callbacks.sessionUnsub?.(),t.state.session=r,t.state.interactive=new N(r,{models:t.state.models,currentModel:r.model?.id,onModelChange:t.callbacks.applyModel}),t.state.reg=t.state.interactive.getRegistry(),t.callbacks.registerAllTuiCommands(),t.state.slashCommands=t.callbacks.refreshSlashCommands(),t.tui.plugins.setCommands(t.state.slashCommands),t.callbacks.attachSessionHandler();let a=r.model?.id;a?(t.state.currentModelId=a,t.state.modelReady=!0,t.tui.stores.tasks.setModelName(L(t.app,a,t.state.session.thinkingLevel))):(t.state.currentModelId=void 0,t.state.modelReady=!1,t.tui.stores.tasks.setModelName(`(no model)`)),t.tui.lifecycle.clearSession();let o=z(r);t.tui.messages.pushMessages(o),t.callbacks.restoreSwitchedSession(),t.tui.info.setTopView({session:r.id}),t.tui.info.showToast(k.t(`cmd.titleSessionFork`),k.t(`cmd.forkSuccess`,{idShort:r.id.slice(0,8)}))}async function xn(e,t){let n=e[0],r=e[1];if(!n||!r){t.tui.info.showToast(`a2ui`,`Usage: /a2ui-action <componentId> <action> [payload-json]`);return}let i;if(e[2])try{i=JSON.parse(e.slice(2).join(` `))}catch{t.tui.info.showToast(`a2ui`,`Invalid JSON payload`);return}let a=t.state.session;a.session.emit({type:`a2ui.action`,sessionId:a.id,componentId:n,action:r,payload:i});let o=`[a2ui action] component="${n}" action="${r}"${i?` payload=${JSON.stringify(i)}`:``}`;a.session.prompt(o).catch(e=>{t.tui.info.showToast(`a2ui`,`Action failed: ${e instanceof Error?e.message:String(e)}`)})}async function Sn(e,t){let n=90,r=e.indexOf(`--ttl-days`);if(r>=0&&r+1<e.length){let t=parseInt(e[r+1],10);!isNaN(t)&&t>0&&(n=t)}let i=e.find(e=>e.startsWith(`--ttl-days=`));if(i){let e=parseInt(i.split(`=`)[1],10);!isNaN(e)&&e>0&&(n=e)}let a=e.includes(`--apply`),o=t.app.sessionStorageDir;if(!o){t.tui.info.showToast(`trace-gc`,`当前后端不支持 trace 文件管理(非本地磁盘存储)`);return}let s=await t.app.listAllSessions(),c=Date.now()-n*24*60*60*1e3,l=s.filter(e=>!((e.updatedAt?e.updatedAt.getTime():0)>=c||e.status===`archived`||e.pinned)),u=w(o,`trace`),d=[];for(let e of l){let t=w(u,`${encodeURIComponent(e.id)}.jsonl`);try{let n=await Qe(t);d.push({session:e,path:t,size:n.size})}catch{}}if(!a){if(d.length===0){t.tui.info.showToast(`trace-gc`,`TTL ${n} 天:没有符合条件的 trace 文件`);return}let e=d.reduce((e,t)=>e+t.size,0),r=`TTL: ${n} 天 | 候选会话: ${d.length} | 预估回收: ${Cn(e)}`,i=[`会话 ID 大小 最后活跃 标题`,...d.map(e=>` ${e.session.id.slice(0,8)} ${Cn(e.size).padStart(9)} ${e.session.updatedAt?e.session.updatedAt.toISOString().slice(0,10):`未知`} ${(e.session.title??``).slice(0,60)}`),``,`TTL 基于会话最后一次持久化活动时间(agent 引擎产生新内容的时间),`,`可能与你最后一次查看/交互该会话的时间不同。`,``,`添加 --apply 参数以实际删除这些 trace 文件。`];t.tui.messages.pushMessage({role:`command_echo`,command:`/trace-gc --dry-run`,summary:r,detail:i.join(`
|
|
6
|
+
`)});return}if(d.length===0){t.tui.info.showToast(`trace-gc`,`TTL ${n} 天:没有需要清理的 trace 文件`);return}let f=0,p=0,m=[];for(let e of d)try{await $e(e.path),f++,p+=e.size}catch(t){m.push(`${e.session.id.slice(0,8)}: ${t instanceof Error?t.message:String(t)}`)}let h=`已清理 ${f}/${d.length} 个会话的 trace 文件,回收 ${Cn(p)}`;f>0?t.tui.info.showToast(`trace-gc`,h+(m.length>0?`\n失败:${m.join(`; `)}`:``)):m.length>0&&t.tui.messages.pushMessage({role:`command_echo`,command:`/trace-gc --apply`,status:`error`,summary:h,detail:`失败:${m.join(`; `)}`})}function Cn(e){return e>=1073741824?`${(e/1073741824).toFixed(1)} GB`:e>=1048576?`${(e/1048576).toFixed(1)} MB`:e>=1024?`${(e/1024).toFixed(1)} KB`:`${e} B`}async function wn(e,t){let n=e[0];if(!n||n.startsWith(`--`)){t.tui.info.showToast(`archive-export`,`用法: /session-archive-export <sessionId> [--out <path>] [--and-delete]`);return}let r=e.includes(`--and-delete`),i,a=e.indexOf(`--out`);if(a>=0&&a+1<e.length){let t=e[a+1];t.startsWith(`--`)||(i=t)}let o=(await t.app.listAllSessions()).find(e=>e.id.startsWith(n)&&e.status!==`archived`);if(!o){t.tui.info.showToast(`archive-export`,`找不到 ID 前缀为 "${n}" 的活跃会话`);return}let s=o.id,c=s.slice(0,8),l=o.title??c,u=t.app.sessionStorageDir;if(!i&&!u){t.tui.info.showToast(`archive-export`,`当前后端不支持自动选择导出路径,请提供 --out <path>`);return}let d=i??w(u,`archives`,`${s}.json`),f;try{f=await t.app.exportSessionArchive(s,d)}catch(e){let n=e instanceof Error?e.message:String(e);t.tui.messages.pushMessage({role:`command_echo`,command:`/session-archive-export`,status:`error`,summary:`导出失败:${n}`});return}if(!r){t.tui.info.showToast(`archive-export`,`已导出 ${l}(${f.entryCount} entries, sha256=${f.checksum.slice(0,12)})→ ${f.path}`);return}let p=t.app.sessionManager.inspectSessionWriteLease(s);if(p.locked&&p.alive!==!1){let e=p.alive===!0?`(确认存活)`:`(无法判断存活)`,n=p.pid==null?``:`(pid=${p.pid},hostname=${p.hostname??`?`}${e})`;t.tui.messages.pushMessage({role:`command_echo`,command:`/session-archive-export --and-delete`,status:`error`,summary:`会话 ${c} 仍被其他 otto 进程占用${n},无法归档删除`,detail:`仅导出请去掉 --and-delete。`});return}t.tui.modal.openModal({kind:`confirm`,title:`确认删除会话`,message:`确认删除会话「${l}」(${c})?此操作不可逆,且会同步清理 trace/checkpoint。`,confirmLabel:`确认删除`,cancelLabel:`取消`,dangerous:!0,onConfirm:async()=>{try{await t.app.removeSession(s),t.tui.info.showToast(`archive-export`,`已归档并删除 ${l}(${f.entryCount} entries)→ ${f.path}`)}catch(e){let n=e instanceof Error?e.message:String(e);t.tui.messages.pushMessage({role:`command_echo`,command:`/session-archive-export --and-delete`,status:`error`,summary:`删除失败:${n}`,detail:`导出文件仍保存于 ${f.path}`})}},onCancel:()=>{t.tui.info.showToast(`archive-export`,`已取消删除。导出文件仍保存于 ${f.path}`)}})}async function Tn(e,t){let n=e[0];if(!n){t.tui.info.showToast(`session kill`,`Usage: /session kill <session-id>`);return}let r=t.app.listSessions(),i=r.find(e=>e.id===n)??r.find(e=>e.id.startsWith(n))??r.find(e=>e.id.includes(n));if(!i){t.tui.info.showToast(`session kill`,k.t(`cmd.sessionNoMatch`,{arg:n}));return}if(i.id===t.state.session.id){t.tui.info.showToast(`session kill`,`Cannot kill the current foreground session. /resume to another session first.`);return}let a=t.app.getSession(i.id);if(!a){V(i.id),t.tui.info.showToast(`session kill`,`Removed stale session ${i.id.slice(0,8)} from background.`);return}a.abort(),V(i.id),await t.app.removeSession(i.id),t.tui.info.showToast(`session kill`,`Killed session ${i.id.slice(0,8)}${i.title?` (${i.title})`:``}.`)}async function En(e,t){let n=t.state.session.id,r=t.state.session.session.metadata().title?.trim()||n.slice(0,8),i=await t.app.sessionManager.forkSession(n);if(!i){t.tui.info.showToast(k.t(`cmd.titleSessionFork`),k.t(`cmd.forkFailed`));return}let a=`${r} (fork)`,o=(await t.tui.modal.openModal({kind:`input`,title:k.t(`cmd.forkNameTitle`),placeholder:a,defaultValue:a})??``).trim()||a;i.renameSession(o);let s=t.state.session;if(t.state.session.isBusy){let[e]=sn(H(s.id,s.session.messages(),!0),()=>s.session.messages()),n=t.state.session.subscribe(t=>{e(t),(t.type===`prompt.end`||t.type===`error`)&&n()})}else H(s.id,s.session.messages(),!1);await t.callbacks.pasteBinder?.fork(s.id,i.id),t.callbacks.sessionUnsub?.(),t.state.session=i,t.state.interactive=new N(i,{models:t.state.models,currentModel:i.model?.id,onModelChange:t.callbacks.applyModel}),t.state.reg=t.state.interactive.getRegistry(),t.callbacks.registerAllTuiCommands(),t.state.slashCommands=t.callbacks.refreshSlashCommands(),t.tui.plugins.setCommands(t.state.slashCommands),t.callbacks.attachSessionHandler();let c=i.model?.id;c?(t.state.currentModelId=c,t.state.modelReady=!0,t.tui.stores.tasks.setModelName(L(t.app,c,t.state.session.thinkingLevel))):(t.state.currentModelId=void 0,t.state.modelReady=!1,t.tui.stores.tasks.setModelName(`(no model)`)),t.tui.lifecycle.clearSession();let l=z(i);t.tui.messages.pushMessages(l),t.callbacks.restoreSwitchedSession(),t.tui.info.setTopView({session:i.id}),t.tui.stores.tasks.setSessionTitle(o),t.tui.lifecycle.setTerminalTitle(o),t.tui.info.showToast(k.t(`cmd.titleSessionFork`),k.t(`cmd.forkSuccessNamed`,{title:o}))}async function Dn(e,t){let n=t.state.session,r=n.session,i=r.messages(),a=0;for(let e=i.length-1;e>=0;e--){let t=i[e]?.usage;if(i[e]?.role===`assistant`&&t){a=(t.cacheReadTokens??0)+(t.cacheWriteTokens??0)+(t.inputTokens??0)+(t.outputTokens??0);break}}let o=n.model?.contextWindow,s=o&&o>0?Math.round(a/o*100):void 0,c=i.reduce((e,t)=>e+(t.usage?.outputTokens??0),0),l=Ce(r.metadata().title,r.messages(),n.id),u=t.callbacks.isWriteLeaseReadOnly(),d=[{kind:`row`,label:k.t(`cmd.statusRowTitle`),value:l},{kind:`row`,label:k.t(`cmd.statusRowSessionId`),value:n.id.slice(0,8)},{kind:`row`,label:k.t(`cmd.statusRowModel`),value:n.model?.id??k.t(`cmd.statusModelUnset`)},{kind:`row`,label:k.t(`cmd.statusRowMsgs`),value:String(i.length)},{kind:`row`,label:k.t(`cmd.statusRowOccupancy`),value:k.t(`cmd.statusValueOccupancy`,{occ:a.toLocaleString(),window:o?.toLocaleString()??`N/A`,seg:s===void 0?``:` (${s}%)`})},{kind:`row`,label:k.t(`cmd.statusRowCumOutput`),value:c.toLocaleString()},{kind:`row`,label:k.t(`cmd.statusRowWriteAccess`),value:u?k.t(`cmd.statusValueWriteLeaseReadOnly`):k.t(`cmd.statusValueWriteLeaseOk`),tone:u?`warning`:void 0}];t.callbacks.isRunPaused()&&d.push({kind:`blank`},{kind:`text`,value:k.t(`cmd.statusLineRunPaused`),tone:`warning`}),t.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleStatus`),lines:[],dataListEntries:d})}async function On(e,t){let n=t.state.session,r=n.model,i=r?.contextWindow??2e5,a=n.session.messages(),o=0,s=0,c=0,l=0,u=0,d=0,f=!1;for(let e=a.length-1;e>=0;e--){if(a[e]?.role!==`assistant`||!a[e]?.usage)continue;let t=a[e].usage;u+=t.inputTokens??0,d+=t.outputTokens??0,f||=(o=t.inputTokens??0,s=t.outputTokens??0,c=t.cacheReadTokens??0,l=t.cacheWriteTokens??0,!0)}let p=kt({systemPrompt:n.systemPrompt,tools:n.tools,lastIn:o,lastOut:s,lastCacheRead:c,lastCacheWrite:l,contextWindow:i,modelName:r?.name??r?.id??``,totIn:u,totOut:d,messageCount:a.length});t.tui.stores.budget.setBudget(p),t.tui.stores.context.setBudget(p),t.tui.modal.openModal({kind:`context`})}function kn(){let e=process.env.OTTO_NOTIFY_COALESCE_WARN_RATIO,t=e?Number(e):NaN;return Number.isFinite(t)&&t>=1?t:1.5}function An(e,t){return t===0?`healthy`:e<kn()?`warning`:`healthy`}async function jn(e,t){t.tui.engine.pushEngineEvent({kind:`perf`,memory:t.app.memoryGovernor.sample()});let n=t.tui.info.getNotifyStats(),r=n.coalescedCalls/Math.max(1,n.coalescedFires);t.tui.engine.pushEngineEvent({kind:`perf`,notify:{coalescedCalls:n.coalescedCalls,coalescedFires:n.coalescedFires,immediateCalls:n.immediateCalls,flushFires:n.flushFires,coalesceRatio:r,alert:An(r,n.coalescedCalls)}});let i=t.app.activePlugins();try{let e=await me(i,void 0,e=>t.app.pluginHealthTracker.recordToolTimeout(e));t.tui.engine.pushEngineEvent({kind:`perf`,pluginMetrics:e})}catch(e){t.app.logger.warn({err:e instanceof Error?e.message:String(e)},`[perf] collectPluginPerfMetrics failed`),t.tui.engine.pushEngineEvent({kind:`perf`,pluginMetrics:[]})}t.tui.panes.togglePane(`perf`)}async function Mn(e,t){let n=t.state.session.getCostSummary(),r=n.perModel.map(e=>{let t={inputTokens:e.inputTokens,outputTokens:0,cacheReadTokens:e.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens};return{modelId:e.modelId,modelName:e.modelName,cacheReadTokens:e.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens,inputTokens:e.inputTokens,hitRatio:at(t,e.api)}}),i=r.some(e=>e.hitRatio!==null),a={inputTokens:n.totalInputTokens,outputTokens:0,cacheReadTokens:n.totalCacheReadTokens,cacheWriteTokens:n.totalCacheWriteTokens},o=i?at(a):null;t.tui.stores.cache.setView({lastTurnHitRatio:t.state.session.getLastCacheHitRatio(),sessionHitRatio:o,totalCacheReadTokens:n.totalCacheReadTokens,totalCacheWriteTokens:n.totalCacheWriteTokens,totalInputTokens:n.totalInputTokens,totalCostUSD:n.totalCostUSD>0?n.totalCostUSD:void 0,perModel:r}),t.tui.panes.togglePane(`cacheStats`)}async function Nn(e,t){if(process.env.OTTO_DEV!==`1`){t.tui.info.showToast(`Gallery`,`Set OTTO_DEV=1 to enable the component gallery.`);return}t.tui.panes.togglePane(`gallery`)}function Pn(e){return new Date(e*1e3).toLocaleString()}async function Fn(e,t){let n=t.state.session.model?.provider;if((n?await t.app.authStore.getAuthSource(n).catch(()=>null):null)!==`oauth`){t.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleUsage`),lines:[k.t(`cmd.usageNotSubscription`)]});return}let r=t.callbacks.getLastProviderUsage();if(!r){t.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleUsage`),lines:[k.t(`cmd.usageNoSnapshotYet`)]});return}let i=[],a=n===`anthropic`;if(r.limitType&&i.push(k.t(`cmd.usageLineType`,{type:Ge(r.limitType)})),(a||r.usedPercent!==void 0)&&i.push(k.t(`cmd.usageLineStatus`,{status:r.status})),r.usedPercent!==void 0&&i.push(k.t(`cmd.usageLinePercent`,{pct:Math.round(r.usedPercent)})),r.resetsAt!==void 0&&i.push(k.t(`cmd.usageLineResetsAt`,{when:Pn(r.resetsAt)})),r.standardLimits){let e=r.standardLimits;i.push(k.t(`cmd.usageLineStandardLimits`,{reqR:e.remainingRequests??0,reqL:e.limitRequests??0,tokRk:(e.remainingTokens??0)/1e3|0,tokLk:(e.limitTokens??0)/1e3|0,reset:Math.round(Math.max(e.resetRequestsMs??0,e.resetTokensMs??0)/1e3)}))}!a&&r.limitType===void 0&&(i.push(``),i.push(k.t(`cmd.usageSubPoolNotInHeaders`))),t.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleUsage`),lines:i})}function In(e){let t=e.trim(),n=(t.split(`
|
|
7
|
+
`,1)[0]??``).replace(/\s+/g,` `).trim(),r=n.split(` `).slice(0,6).join(` `).slice(0,48).trim()||`note`;return{name:r,description:n.slice(0,60).trim()||r,content:t}}const Ln=e=>`把下面的笔记归纳成一个简短标题(≤6 词)和一句话描述。严格只按此格式输出:\nTITLE: <标题>\nDESC: <一句话描述>\n\n笔记:\n${e}`;function Rn(e){let t=/TITLE:\s*(.+)/i.exec(e)?.[1]?.trim();if(!t)return null;let n=/DESC:\s*(.+)/i.exec(e)?.[1]?.trim();return{name:t.slice(0,60),description:(n||t).slice(0,80)}}async function zn(e,t,n=8e3){let r=In(e);if(!t)return r;let i=new AbortController,a=setTimeout(()=>i.abort(),n);a.unref?.();try{let n=Rn(await t(Ln(e),{maxTokens:64,signal:i.signal}));if(n)return{name:n.name,description:n.description,content:r.content}}catch{}finally{clearTimeout(a)}return r}function Bn(e,t){return{onViewEntry:async n=>{let r=n.source===`project`?e:t;return r?r.read(n.name):null},onForget:async n=>{let r=n.source===`project`?e:t;r&&await r.forget(n.name)}}}async function Vn(e,t){let n=t.app.storage.autoMemory,r=t.app.userMemory,i=(e[0]??``).toLowerCase(),a=e=>t.tui.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:e}]}),o=(e,n,r)=>t.tui.messages.pushMessage({role:`command_echo`,command:e,status:n,summary:r});if(i===`user`){let i=e.slice(1).join(` `).trim();if(i){let e=In(i);await r.record(e),o(`/memory user`,`ok`,k.t(`cmd.memoryUserSaved`,{name:e.name}));return}let a=r.getInjection().trim();t.tui.modal.openModal({kind:`memory`,projectIndex:``,userIndex:a,...Bn(n,r)});return}if(i===`project`){let e=n?n.getInjection().trim():``;t.tui.modal.openModal({kind:`memory`,projectIndex:e,userIndex:``,...Bn(n,r)});return}if(i===`forget`){let t=e.slice(1).join(` `).trim();if(!t){o(`/memory forget`,`warn`,k.t(`cmd.memoryForgetUsage`));return}let i=!1;n&&await n.read(t)!==null&&(await n.forget(t),i=!0),await r.read(t)!==null&&(await r.forget(t),i=!0),o(`/memory forget`,i?`ok`:`error`,i?k.t(`cmd.memoryDeleted`,{name:t}):k.t(`cmd.memoryNotFound`,{name:t}));return}if(e.length>0){let t=e.join(` `).trim(),i=(n?await n.read(t):null)??await r.read(t);i==null?o(`/memory ${t}`,`error`,k.t(`cmd.memoryNotFound`,{name:t})):a(i);return}let s=n?n.getInjection().trim():``,c=r.getInjection().trim();t.tui.modal.openModal({kind:`memory`,projectIndex:s,userIndex:c,...Bn(n,r)})}async function Hn(e,t){let n=k.t(`cmd.titleCompact`);if((e[0]??``).toLowerCase()===`log`){t.tui.panes.togglePane(`compactionLog`);return}if(!t.app.storage.memory){t.tui.info.showToast(n,k.t(`compact.unavailable`));return}t.tui.info.showToast(n,k.t(`compact.ing`)),t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!0});try{let e=await t.state.session.compactNow();e.compacted?(t.tui.info.showToast(n,k.t(`compact.edResult`,{before:e.before,after:e.after})),t.callbacks.onContextCompacted()):t.tui.info.showToast(n,k.t(`compact.noop`))}catch(e){t.tui.info.showToast(n,k.t(`cmd.compactFailed`,{msg:e instanceof Error?e.message:String(e)}))}finally{t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!1})}}const Un=async(e,t)=>{let n=e[0];switch(n){case`memory-sync`:return Wn(e.slice(1),t);default:t.tui.info.showToast(`Workspace`,`/workspace ${n??``} — unknown subcommand. Use: memory-sync [status|enable|disable]`)}};async function Wn(e,t){let n=e[0]??`status`,r=t.app.workspaceRef;if(!r?.root){t.tui.info.showToast(`Workspace memory-sync`,`No local workspace identity yet — cannot configure memory sync.`);return}switch(n){case`status`:{let e=r.memorySyncEnabled===!0;t.tui.info.showToast(`Workspace memory-sync`,e?`Enabled — workspace memory (auto-memory/lessons) syncs to the remote store.`:`Disabled — workspace memory stays local (default).`);return}case`enable`:{if(!t.app.storage.remoteMemoryConfigured){t.tui.info.showToast(`Workspace memory-sync`,`No remote memory service configured (needs --session-url + remote.getAuth) — enabling now would have no effect.`);return}let e=await t.app.setWorkspaceMemorySyncEnabled(!0);t.tui.info.showToast(`Workspace memory-sync`,e?`Enabled. Next memory_record/learn calls will sync to the remote store.`:`Failed to enable — no workspace marker to update.`);return}case`disable`:{let e=await t.app.setWorkspaceMemorySyncEnabled(!1);t.tui.info.showToast(`Workspace memory-sync`,e?`Disabled. Workspace memory now stays local.`:`Failed to disable — no workspace marker to update.`);return}default:t.tui.info.showToast(`Workspace memory-sync`,`/workspace memory-sync ${n} — unknown subcommand. Use: status|enable|disable`)}}async function Gn(e,t){t.tui.info.showToast(k.t(`cmd.titleUpgrade`),k.t(`cmd.upgradeCheckScanning`));try{let e=we({workspaceDir:t.app.workspaceDir,workspaceRoot:ye(t.app.workspaceDir),scope:`all`});if(e.length===0){t.tui.info.showToast(k.t(`cmd.titleUpgrade`),k.t(`cmd.upgradeCheckNoVersioned`));return}let n=await pe(e),r=[],i=0;for(let e of n){let t=`[${e.type}]`;e.error?r.push(`${t} ${e.name} v${e.installed} — ${e.error}`):e.newer?(i++,r.push(k.t(`cmd.upgradeCheckLineUpdate`,{tag:t,name:e.name,installed:e.installed,latest:e.latest??``}))):r.push(k.t(`cmd.upgradeCheckLineLatest`,{tag:t,name:e.name,installed:e.installed}))}i>0&&(r.push(``),r.push(k.t(`cmd.upgradeCheckSummary`,{count:i}))),t.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleUpgradeCheck`),lines:r})}catch(e){t.tui.info.showToast(k.t(`cmd.titleUpgrade`),k.t(`cmd.upgradeCheckFailed`,{err:e instanceof Error?e.message:String(e)}))}}async function Kn(t,n){let r=n.state.session,i=r.model?.id??k.t(`cmd.aboutModelNotSet`),a=re().length,o=Math.round(b()/(1024*1024*1024)),s=Math.round(ie()/(1024*1024)),c=[{kind:`group`,title:k.t(`cmd.aboutGroupVersion`)},{kind:`row`,label:k.t(`cmd.aboutVersion`),value:`${Ne} (build ${je})`},{kind:`row`,label:k.t(`cmd.aboutBranch`),value:`dev`},{kind:`row`,label:k.t(`cmd.aboutCommit`),value:e},{kind:`group`,title:k.t(`cmd.aboutGroupRuntime`)},{kind:`row`,label:k.t(`cmd.aboutRuntime`),value:`Node.js ${process.version} · ${oe()} ${ne()} · ${y()}`,tone:`muted`},{kind:`row`,label:k.t(`cmd.aboutCPU`),value:`${a} cores`,tone:`muted`},{kind:`row`,label:k.t(`cmd.aboutMemory`),value:`${o} GB total / ${Math.round(s)} MB free`,tone:`muted`},{kind:`row`,label:k.t(`cmd.aboutShell`),value:process.env.SHELL??`(unknown)`,tone:`muted`},{kind:`row`,label:k.t(`cmd.aboutTerminal`),value:process.env.TERM??`(unknown)`,tone:`muted`},{kind:`group`,title:k.t(`cmd.aboutGroupSession`)},{kind:`row`,label:k.t(`cmd.aboutModel`),value:i,tone:`secondary`}];r.id&&c.push({kind:`row`,label:k.t(`cmd.aboutSession`),value:r.id.slice(0,8)}),c.push({kind:`blank`},{kind:`text`,value:k.t(`cmd.aboutUpdateHint`),tone:`muted`}),n.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleAbout`),lines:[],dataListEntries:c})}async function G(e,t){return e.tui.modal.openModal({kind:`input`,...t})}function qn(e,t,n){return new Promise(r=>{e.tui.modal.openModal({kind:`confirm`,title:t,message:n,onConfirm:()=>r(!0),onCancel:()=>r(!1)})})}async function Jn(e,t){let n=t.app.feedbackRegistry.get();if(!n){t.tui.info.showToast(k.t(`cmd.titleFeedback`),k.t(`cmd.feedbackUnavailable`));return}let r=e.indexOf(`--repo`),i=r>=0?e[r+1]:void 0,a=await ee({configuredRepo:t.app.settings.get(`feedback_repo`),cliRepoArg:i,cwd:t.app.workspaceDir});if(!a){t.tui.info.showToast(k.t(`cmd.titleFeedback`),k.t(`cmd.feedbackRepoUnresolved`));return}let o=await G(t,{title:k.t(`cmd.feedbackStepTitle`)});if(!o||o.trim().length===0)return;let s=await G(t,{title:k.t(`cmd.feedbackStepRepro`)})??void 0,c=await G(t,{title:k.t(`cmd.feedbackStepExpected`)})??void 0,l=await G(t,{title:k.t(`cmd.feedbackStepActual`)})??void 0,u=v(t.state.session.model?.id),d={title:o.trim(),reproduce:s,expected:c,actual:l,envInfo:u,repo:a},f=[s,c,l].filter(Boolean).join(`
|
|
8
|
+
`).slice(0,300);if(!await qn(t,k.t(`cmd.feedbackConfirmTitle`),k.t(`cmd.feedbackConfirmMessage`,{title:d.title,bodyPreview:f})))return;if(t.tui.info.showToast(k.t(`cmd.titleFeedback`),k.t(`cmd.feedbackChannelSubmitting`)),n.submitIssueViaGh){let e=await n.submitIssueViaGh(d);if(e.ok){t.tui.info.showToast(k.t(`cmd.titleFeedback`),k.t(`cmd.feedbackCreated`,{url:e.url}));return}}let p=n.buildIssueUrl?.(d);if(!p){t.tui.info.showToast(k.t(`cmd.titleFeedback`),k.t(`cmd.feedbackUnavailable`));return}ke(p),t.tui.info.showToast(k.t(`cmd.titleFeedback`),k.t(`cmd.feedbackCreated`,{url:p}))}function Yn(e,t){try{let n=Se(e,t);if(!n)return;let r=w(n,fe),i=be(Le(r,`utf-8`),r);return i?i.codeProviderIds?.[0]??i.contributes?.providers?.[0]?.id??i.contributes?.oauth?.[0]?.id:void 0}catch{return}}function Xn(e,t,n){return!e||t.get(e)?[{label:n.oauth.label,value:`oauth`,detail:n.oauth.detail},{label:n.apiKey.label,value:`key`,detail:n.apiKey.detail}]:[{label:n.apiKey.label,value:`key`,detail:n.apiKey.detail}]}const Zn={provider:`install-provider`,authentication:`connect-provider`,model:`choose-model`,ready:`send-first-prompt`,"first-prompt":`none`};function Qn(e){if(!e.providerInstalled)return`provider`;if((e.connectedProviderIds??[]).length===0)return`authentication`;let t=e.usableModelIds??[];if(t.length===0)return`model`;let n=e.selectedModelId;return!n||!t.includes(n)?`model`:e.firstPromptSubmitted?`first-prompt`:`ready`}function $n(e){let t=Qn(e),n=e.providerCandidates??[],r=e.connectedProviderIds??[],i=e.usableModelIds??[],a=e.firstPromptSubmitted??!1,o=(t===`provider`||t===`authentication`||t===`model`)&&!(e.dismissed??!1);return{stage:t,provider:{installed:e.providerInstalled,candidates:n},authentication:{connectedProviderIds:r},model:{...e.selectedModelId===void 0?{}:{selectedId:e.selectedModelId},usableIds:i},firstPrompt:{submitted:a},recommendation:{action:Zn[t],stage:t,autoOpen:o}}}function er(e){return e.stage===`ready`||e.stage===`first-prompt`}function tr(e,t){return e.get(t)===!0}function nr(e){return{personalizationSeen:tr(e,`has_completed_onboarding`),dismissed:tr(e,`has_completed_wizard`)||tr(e,`wizard_dont_show_again`),firstPromptSubmitted:!1}}const rr=`__otto_setup__`;async function ir(e){let t=nr(e.settings),n=e.listProviders(),r=(await Promise.all(n.map(async t=>({provider:t,source:await e.getAuthSource(t).catch(()=>null)})))).filter(e=>e.source!=null).map(e=>e.provider),i=e.listModels().filter(e=>e.id!==rr),a=(await Promise.all(i.map(async t=>{try{let{usable:n}=await e.isModelUsable({provider:t.provider,api:t.api});return n?t.id:null}catch{return null}}))).filter(e=>e!==null),o=e.getSelectedModelId();return $n({providerInstalled:e.hasProviderPlugin(),...e.providerCandidates?{providerCandidates:e.providerCandidates}:{},connectedProviderIds:r,usableModelIds:a,...o!==void 0&&o!==rr?{selectedModelId:o}:{},firstPromptSubmitted:t.firstPromptSubmitted,dismissed:t.dismissed})}function ar(e){return{hasProviderPlugin:()=>e.modelRegistry.hasAnyPluginSourcedModel(),listProviders:()=>e.authStore.listProviders(),getAuthSource:t=>e.authStore.getAuthSource(t),listModels:()=>e.modelRegistry.getAll().map(e=>({id:e.id,provider:e.provider,api:e.api})),isModelUsable:e.isModelUsable,getSelectedModelId:e.selectedModelId,settings:{get:t=>e.settings.get(t)},...e.providerCandidates?{providerCandidates:e.providerCandidates}:{}}}var or=class{snapshot=null;listeners=new Set;constructor(e){this.deps=e}current(){return this.snapshot}async refresh(){let e=await ir(this.deps);this.snapshot=e;for(let t of this.listeners)try{t(e)}catch{}return e}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}};function sr(e,t){return(e.envKeys??[]).some(e=>{let n=t[e];return typeof n==`string`&&n.trim().length>0})?0:e.supportsOAuth?1:2}function cr(e,t){return e.map((e,n)=>({provider:e,index:n,rank:sr(e,t)})).sort((e,t)=>e.rank-t.rank||e.index-t.index).map(e=>e.provider)}function lr(e){try{let{createRequire:t}=j(`node:module`),{readFileSync:n}=j(`node:fs`),{dirname:r,join:i}=j(`node:path`),a=i(r(t(import.meta.url).resolve(`${e}/package.json`)),`otto-plugin.json`),o=JSON.parse(n(a,`utf8`)).contributes??{},s=(o.providers??[]).map(e=>e.envKey).filter(e=>typeof e==`string`&&e.length>0);return{supportsOAuth:!!o.oauth,envKeys:s}}catch{return{supportsOAuth:!1,envKeys:[]}}}function ur(e){let t=e.map((e,t)=>({model:e,index:t})).sort((e,t)=>Number(t.model.usable)-Number(e.model.usable)||e.index-t.index).map(e=>e.model),n=dr(t);return t.map(e=>({...e,recommended:e.usable&&e.id===n}))}function dr(e){return e.find(e=>e.usable)?.id}const fr=`oxygen-provider`,pr=new Set([`plugin-oxygen`,fr]);async function mr(e){try{let{makeRegistryClient:t}=await import(`./registry-B3nfN62q.js`),{registries:n}=await t(e.app).loadAll();return n.some(e=>e.entries.some(e=>pr.has(e.id)||e.source===`@x-otto/plugin-oxygen`||e.source.includes(`/plugin-oxygen`)||e.subPath?.endsWith(`plugin-oxygen`)))}catch{return!1}}async function hr(e){let t=e.tui,n=e.app,r=await ir(ar({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>e.state.session?.model?.id,isModelUsable:ot(n.authStore)})),i=n.authStore.listProviders(),a=[];r.provider.installed&&a.push(0),r.authentication.connectedProviderIds.length>0&&a.push(1),r.model.usableIds.length>0&&a.push(2);let s=(()=>{for(let e=0;e<3;e++)if(!a.includes(e))return e;return 3})(),c=await mr(e),l=Object.entries(o).filter(([e,t])=>t.capabilities.includes(`provider`)&&(e!==fr||c)),u={"anthropic-provider":`Claude 全系列 · OAuth 一键登录`,"deepseek-provider":`高性价比 · API-key 接入 · 中文友好`,"openai-codex-provider":`GPT / Codex 系列 · 需要 API key 或 OAuth`,"github-copilot-provider":`订阅即用 · GitHub 账号授权`,"cursor-provider":`Cursor IDE 内置 · 需 Cursor 订阅`,"oxygen-provider":`企业级 · 按组织授权`},d=cr(l.map(([e,t])=>({id:e,...lr(t.pkg)})),process.env).map(({id:e})=>({label:e,value:e,detail:u[e]??o[e]?.pkg??e})),f=e=>Xn(e,n.authStore.oauth,{oauth:{label:k.t(`setup.loginOAuth`),detail:`Open browser, complete authorization — no copy-paste needed.`},apiKey:{label:k.t(`setup.loginApiKey`),detail:`Generate a key on your provider dashboard and paste it here.`}}),p=ot(n.authStore),m=new Set(r.model.usableIds),h=n.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`),g=ur((await Promise.all(h.map(async e=>{let t=m.has(e.id);return t?{model:e,usable:t,reason:void 0}:{model:e,usable:!1,reason:(await p({provider:e.provider,api:e.api}).catch(()=>({usable:!1,reason:`unauthenticated`}))).reason??`unauthenticated`}}))).map(({model:e,usable:t,reason:n})=>({id:e.id,label:e.name,detail:`${e.provider} · ${e.strengths?.join(`, `)??``}`,usable:t,...n?{reason:n}:{}}))).map(e=>({label:e.label,value:e.id,detail:e.detail,recommended:e.recommended,...e.reason?{unusableReason:e.reason}:{}})),_=i.length===1?i[0]:void 0;t.modal.openModal({kind:`wizard`,title:k.t(`setup.title`),welcomeTitle:k.t(`setup.welcomeTitle`),welcomeGreeting:``,welcomeDescription:k.t(`setup.welcomeDescription`),welcomeDontShowAgainLabel:k.t(`setup.welcomeDontShowAgain`),welcomeStartLabel:k.t(`setup.welcomeStart`),welcomeCancelLabel:k.t(`setup.welcomeCancel`),stepNames:[k.t(`setup.stepNameProvider`),k.t(`setup.stepNameLogin`),k.t(`setup.stepNameModel`),k.t(`setup.stepNameStart`)],stepSubtitles:[k.t(`setup.step1Subtitle`),k.t(`setup.step3Subtitle`),k.t(`setup.step4Subtitle`),k.t(`setup.step5Done`)],initialCompleted:a,initialCurrent:s,providerOptions:d,providerAuthOptions:f,authProviderName:_,modelOptions:g,examplePrompts:[`Explain what's in this project`,`Fix the failing test in src/x.ts`,`Add a health check endpoint`],workspacePath:n.workspaceDir,async onInstallProvider(t,n){n(`Resolving package…`);try{let{runPluginInstall:r}=await import(`./extension-plugin-BjY-x3u8.js`),i=!1,a=await r(t,e,{autoTrust:!0,onProgress:e=>n(`${e}…`),onPendingCapabilities:()=>{i=!0}}),s=o[t]?.pkg??t;if(!a)return{ok:!1,error:k.t(`setup.installFailed`,{reason:t})};let c=[];try{let{readHighRiskCapabilities:e,resolvePackageDir:t}=await import(`@x-otto/coding`),n=t(s);n&&(c=e(n))}catch{}return{ok:!0,providerId:Yn(s),capabilities:c,pendingCapabilities:i}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},async onProviderOAuthStart(t){let r=t||i[0]||n.authStore.listProviders()[0];if(!r)return null;let a=new AbortController;try{let{openBrowser:t}=await import(`@x-otto/shared`),i,o,s,c=n.authStore.login(r,{signal:a.signal,onAuth:e=>{o=e.code,s=e.instructions,e.url&&(i=e.url,e.code||t(e.url))},onProgress:()=>{},onPrompt:async()=>``});return c.catch(()=>{}),await new Promise(e=>setTimeout(e,200)),{authorizationUrl:i??``,code:o,instructions:s,openAgain:()=>{i&&t(i)},poll:async()=>{try{return await Promise.race([c.then(()=>`done`),new Promise(e=>setTimeout(()=>e(`pending`),500))])===`done`?(await e.callbacks.refreshModelsNow(),`done`):`pending`}catch(e){let t=e instanceof Error?e:void 0;if(t?.code===`OAUTH_CANCELLED`)return{status:`error`,reason:`cancelled`};let n=new Set([`ENOTFOUND`,`ECONNREFUSED`,`ECONNRESET`,`ETIMEDOUT`,`EAI_AGAIN`,`EHOSTUNREACH`,`ENETUNREACH`,`UND_ERR_CONNECT_TIMEOUT`]),r=t?.code,i=t?.cause?.code;return r&&n.has(r)||i&&n.has(i)?{status:`error`,reason:`network`}:{status:`error`,reason:`rejected`}}},cancel:()=>{a.abort()}}}catch{return null}},async onSubmitProviderApiKey(t,r){let a=t||i[0]||n.authStore.listProviders()[0];if(!a)return{ok:!1,error:`No provider selected.`};try{return await n.authStore.setCredentialKey(a,r),await n.authStore.save(),await e.callbacks.refreshModelsNow(),{ok:!0}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}},onOpenProxySettings(){import(`./proxy-BvdBsB1O.js`).then(({handleProxy:t})=>t([],e)).catch(()=>{})},async onSelectModel(t){if(await e.callbacks.applyModel(t),!e.state.modelReady)throw Error(`Model selected but not ready. Check your credentials and try /model refresh.`)},onComplete(){e.callbacks.refreshModelsNow().catch(()=>{}),n.settings.persist({has_completed_wizard:!0},`global`).catch(()=>{})},onDismiss(){},onDontShowAgain(e){n.settings.persist({wizard_dont_show_again:e},`global`).catch(()=>{})}})}async function gr(e,t){await hr(t)}function K(e,t,n){let r={ts:Date.now(),sessionId:e.sessionId,...e.turn===void 0?{}:{turn:e.turn},kind:`lifecycle`,node:t,payload:n};e.traceStore.append(e.sessionId,r).catch(()=>{})}function _r(e,t,n){let{tui:r,session:i,traceStore:a}=e,o=t===`model`?`model_switch`:`effort_switch`,s=t===`model`?`model.switch`:`effort.change`;r.messages.pushMessage({role:o,label:n.label}),i.session.append({role:`system`,subtype:o,content:n.label,level:`info`,timestamp:Date.now()});let c=i.session.getTurnCount(),l={ts:Date.now(),sessionId:i.id,...c===void 0?{}:{turn:c},kind:`lifecycle`,node:s,payload:{from:n.from??null,to:n.to,label:n.label}};a.append(i.id,l).catch(()=>{})}function vr(e,t){_r(e,`model`,t)}function yr(e,t){_r(e,`effort`,t)}function br(e,t){K(e,`retry.queued`,{attempt:t.attempt,max:t.max,...t.mode===void 0?{}:{mode:t.mode},...t.reason===void 0?{}:{reason:t.reason}})}function xr(e,t){K(e,`retry.cancelled`,{attempt:t.attempt})}function Sr(e){K(e,`retry.reset`,{})}function Cr(e,t,n){K(e,`pause.${t}`,{...n===void 0?{}:{source:n}})}const wr=[`low`,`medium`,`high`,`xhigh`,`max`],Tr={low:{label:`Low`,desc:`节约 Token,快速响应`,intensity:.2},medium:{label:`Medium`,desc:`平衡速度与推理质量`,intensity:.4},high:{label:`High`,desc:`深度推理,延迟较高`,intensity:.6},xhigh:{label:`XHigh`,desc:`更长推理链,更全面思考`,intensity:.8},max:{label:`Max`,desc:`全力推理,最慢但最深入`,intensity:1}};function Er(e){let t=Math.round(e*8);return`━`.repeat(Math.max(0,t))+`╌`.repeat(Math.max(0,8-t))}async function Dr(e,t){let n=e[0]?.toLowerCase();if(n&&wr.includes(n)){Or(t,n);return}if(n){t.tui.info.showToast(k.t(`cmd.titleEffort`),k.t(`cmd.effortUnknown`,{arg:n,levels:wr.join(` / `)}));return}let r=t.state.session.thinkingLevel;t.tui.modal.openModal({kind:`select`,title:k.t(`cmd.selectEffortTitle`),options:wr.map(e=>{let t=Tr[e],n=e===r,i=Er(t.intensity);return{label:t.label,value:e,detail:`${i} ${t.desc}${n?` · 当前`:``}`}}),onSelect:e=>Or(t,e),onCancel:()=>{}})}function Or(e,t){let n=e.state.session,r=n.thinkingLevel;n.thinkingLevel=t,e.app.settings.persist({thinking_level:t}),r!==t&&yr({tui:e.tui,session:n,traceStore:e.app.storage.traceStore},{from:r,to:t,label:Pt(t)}),n.model?.id&&e.tui.stores.tasks.setModelName(L(e.app,n.model.id,t)),e.tui.info.showToast(k.t(`cmd.titleEffort`),t)}async function kr(e,t){let n=e[0]?.toLowerCase();if(n===`general`||n===`gen`){J(t);return}if(n===`lang`||n===`language`){Br(e.slice(1),t);return}if(n===`theme`){Vr(e.slice(1),t);return}if(n){t.tui.info.showToast(k.t(`cmd.titlePreference`),k.t(`cmd.preferenceUsage`));return}q(t)}function q(e,t){let n=e.app.settings,r=n.get(`language`),i=r===`zh`?`中文 (zh)`:r===`en`?`English (en)`:`Auto`,a=e.state.themeRegistry??Ve(),o=n.get(`theme_preset`)??{},s=a.get(o.dark??`dark`)?.label??o.dark??`dark`;e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.titlePreference`),detailPlacement:`inline`,options:[{label:k.t(`cmd.prefOptionGeneral`),value:`general`,detail:k.t(`cmd.prefDescGeneral`)},{label:k.t(`cmd.prefOptionLang`),trailingLabel:i,value:`lang`,detail:k.t(`cmd.prefDescLang`)},{label:k.t(`cmd.prefOptionTheme`),trailingLabel:s,value:`theme`,detail:k.t(`cmd.prefDescTheme`)}],defaultSelectedValue:t,onSelect:t=>{t===`general`?J(e):t===`lang`?Br([],e):t===`theme`&&Vr([],e)},onCancel:()=>{}})}let Ar;function J(e,t,n,r){let i=e.app.settings,a=i.get(`notification`),o=i.get(`nickname`)??``,s=a?.on_completion!==!1,c=a?.sound===!0,l=i.get(`auto_update_check`)!==!1,u=i.get(`skill_loop`)?.enabled===!0,d=e.app.activePlugins().some(e=>e.id===x),f={on:O.toggleOn,off:O.toggleOff},p={on:k.t(`cmd.toggleOn`),off:k.t(`cmd.toggleOff`)},m=e=>Ft(e,f,p);e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.selectGeneralTitle`),detailPlacement:`inline`,subtitle:t,replace:r,options:[{label:k.t(`cmd.genNickname`),trailingLabel:o||`—`,value:`nickname`,detail:k.t(`cmd.genNicknameDesc`)},{label:k.t(`cmd.genCompletionNotice`),trailingLabel:m(s),value:`completion`,detail:k.t(`cmd.genCompletionNoticeDesc`)},{label:k.t(`cmd.genSound`),trailingLabel:m(c),value:`sound`,detail:k.t(`cmd.genSoundDesc`)},{label:k.t(`cmd.genUpdateCheck`),trailingLabel:m(l),value:`updateCheck`,detail:k.t(`cmd.genUpdateCheckDesc`)},{label:k.t(`cmd.genSkillLoop`),trailingLabel:d?m(u):k.t(`cmd.genSkillLoopMissing`),value:`skillLoopPanel`,detail:k.t(`cmd.genSkillLoopEntryDesc`)}],defaultSelectedValue:n??Ar,onHighlight:e=>{Ar=e},onSelect:t=>{if(t===`nickname`){jr(e);return}if(t===`skillLoopPanel`){Y(e);return}zr(e,t)},onCancel:()=>{q(e,`general`)}})}async function jr(e){let t=await e.tui.modal.openModal({kind:`input`,title:k.t(`cmd.genNicknameInputTitle`),placeholder:k.t(`cmd.genNicknamePlaceholder`)});if(t==null){J(e);return}let n=t.trim();await e.app.settings.persist({nickname:n}),J(e,k.t(`cmd.genSaved`))}const Mr=[4,6,12,20];function Nr(e){let t=typeof e==`number`?e:6,n=Mr.includes(t)?`genSkillLoopThr${t}`:``;return n?k.t(`cmd.${n}`):String(t)}function Pr(e){let t=e.app.settings,n=t.get(`skill_loop`)?.min_messages??6;e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.genSkillLoopThresholdTitle`),detailPlacement:`inline`,options:Mr.map(e=>({label:k.t(`cmd.genSkillLoopThr${e}`),value:String(e),detail:k.t(`cmd.genSkillLoopThr${e}Desc`),trailingLabel:e===n?O.toggleOn:void 0})),onSelect:n=>{(async()=>{let r={...t.get(`skill_loop`)??{}};r.min_messages=Number(n),await t.persist({skill_loop:r}),Y(e,k.t(`cmd.genSaved`),`threshold`)})()},onCancel:()=>{Y(e,void 0,`threshold`)}})}const Fr=[3,14,30,365];function Ir(e){let t=typeof e==`number`?e:14;return Fr.includes(t)?k.t(`cmd.genSkillLoopCd${t}`):k.t(`cmd.genSkillLoopCdDays`,{n:t})}function Lr(e){let t=e.app.settings,n=t.get(`skill_loop`)?.dismiss_cooldown_days??14;e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.genSkillLoopCooldownTitle`),detailPlacement:`inline`,options:Fr.map(e=>({label:k.t(`cmd.genSkillLoopCd${e}`),value:String(e),detail:k.t(`cmd.genSkillLoopCd${e}Desc`),trailingLabel:e===n?O.toggleOn:void 0})),onSelect:n=>{(async()=>{let r={...t.get(`skill_loop`)??{}};r.dismiss_cooldown_days=Number(n),await t.persist({skill_loop:r}),Y(e,k.t(`cmd.genSaved`),`cooldown`)})()},onCancel:()=>{Y(e,void 0,`cooldown`)}})}function Y(e,t,n){let r=e.app.settings,i=r.get(`skill_loop`)?.enabled===!0,a=e.app.activePlugins().some(e=>e.id===x),o={on:O.toggleOn,off:O.toggleOff},s={on:k.t(`cmd.toggleOn`),off:k.t(`cmd.toggleOff`)};if(!a){e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.skillLoopPanelTitle`),detailPlacement:`inline`,subtitle:k.t(`cmd.genSkillLoopMissingHint`),options:[{label:k.t(`cmd.genSkillLoopMissing`),value:`noop`,detail:``}],onSelect:()=>{J(e,void 0,`skillLoopPanel`)},onCancel:()=>{J(e,void 0,`skillLoopPanel`)}});return}e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.skillLoopPanelTitle`),detailPlacement:`inline`,subtitle:t,defaultSelectedValue:n,options:[{label:k.t(`cmd.skillLoopOnOff`),trailingLabel:Ft(i,o,s),value:`toggle`,detail:k.t(`cmd.genSkillLoopEntryDesc`)},...i?[{label:k.t(`cmd.genSkillLoopThreshold`),trailingLabel:Nr(r.get(`skill_loop`)?.min_messages),value:`threshold`,detail:k.t(`cmd.genSkillLoopThresholdDesc`)},{label:k.t(`cmd.genSkillLoopCooldown`),trailingLabel:Ir(r.get(`skill_loop`)?.dismiss_cooldown_days),value:`cooldown`,detail:k.t(`cmd.genSkillLoopCooldownDesc`)},{label:k.t(`cmd.genSkillLoopStatus`),value:`status`,detail:k.t(`cmd.genSkillLoopStatusDesc`)}]:[]],onSelect:t=>{if(t===`threshold`){Pr(e);return}if(t===`cooldown`){Lr(e);return}if(t===`status`){Rr(e);return}(async()=>{let t={...r.get(`skill_loop`)??{}},n=t.enabled!==!0;t.enabled=n,await r.persist({skill_loop:t}),Y(e,n?k.t(`cmd.genSkillLoopOn`):k.t(`cmd.genSkillLoopOff`),`toggle`)})()},onCancel:()=>{J(e,void 0,`skillLoopPanel`)}})}function Rr(e){let t=e.app.settings,n=e.app.activePlugins().some(e=>e.id===x),r=xe({workspaceKey:e.app.workspaceRef?.key??de,now:Date.now(),cooldownDays:t.get(`skill_loop`)?.dismiss_cooldown_days,pluginInstalled:n}),i=e=>k.t(`cmd.skillLoopStatusCount`,{n:e}),a=[];if(!n)a.push({label:k.t(`cmd.skillLoopStatusNotInstalled`),value:`noop`,detail:k.t(`cmd.genSkillLoopMissingHint`)});else{a.push({label:k.t(`cmd.skillLoopStatusEpisodes`),trailingLabel:i(r.episodeCount),value:`noop`,detail:k.t(`cmd.skillLoopStatusSuccess`)+` `+i(r.successCount)},{label:k.t(`cmd.skillLoopStatusPending`),trailingLabel:i(r.pendingCount),value:`noop`,detail:i(r.candidateCount)+` `+k.t(`cmd.skillLoopStatusCandidates`)+` · `+i(r.coolingCount)+` `+k.t(`cmd.skillLoopStatusCooling`)});for(let e of r.pending)a.push({label:e.taskSignature,trailingLabel:k.t(`cmd.skillLoopStatusTimes`,{n:e.size}),value:`noop`,detail:k.t(`cmd.skillLoopStatusGroupPending`)});for(let e of r.recentSignatures)a.push({label:e,value:`noop`,detail:k.t(`cmd.skillLoopStatusGroupRecent`)})}let o=r.episodeCount===0?`cmd.skillLoopStatusEmpty`:{"no-episodes":`cmd.skillLoopStatusHintNoEpisodes`,"not-enough-successes":`cmd.skillLoopStatusHintNotEnough`,"no-cluster-yet":`cmd.skillLoopStatusHintNoCluster`}[r.nextProposalHint??``]??``;e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.skillLoopStatusTitle`),detailPlacement:`inline`,subtitle:o?k.t(o):void 0,options:a,onSelect:()=>{Y(e,void 0,`status`)},onCancel:()=>{Y(e,void 0,`status`)}})}async function zr(e,t){let n=e.app.settings;if(t===`updateCheck`){let r=n.get(`auto_update_check`)!==!1;await n.persist({auto_update_check:!r}),J(e,k.t(`cmd.genSaved`),t,!0);return}let r={...n.get(`notification`)??{}};t===`completion`?r.on_completion=r.on_completion===!1:t===`sound`&&(r.sound=r.sound!==!0),await n.persist({notification:r}),J(e,k.t(`cmd.genSaved`),t,!0)}function Br(e,t){let n=e[0]?.toLowerCase();if(n===`en`||n===`zh`||n===`auto`){Wr(t,n);return}if(n){t.tui.info.showToast(k.t(`cmd.titlePreference`),k.t(`pref.languageUsage`));return}t.tui.modal.openModal({kind:`select`,title:k.t(`cmd.selectLanguageTitle`),detailPlacement:`inline`,options:[{label:`中文 (zh)`,value:`zh`,detail:k.t(`cmd.langDescZh`)},{label:`English (en)`,value:`en`,detail:k.t(`cmd.langDescEn`)},{label:`Auto`,value:`auto`,detail:k.t(`cmd.langDescAuto`)}],onSelect:e=>Wr(t,e),onCancel:()=>{q(t,`lang`)}})}function Vr(e,t){Hr(t)}function Hr(e){let t=e.state.themeRegistry??Ve(),n=e.app.settings.get(`theme_preset`)??{},r=t.get(n.dark??`dark`)??t.get(`dark`),i=t.get(n.light??`light`)??t.get(`light`);e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.prefOptionTheme`),detailPlacement:`inline`,options:[{label:k.t(`cmd.themeDarkPresetOption`),value:`preset-dark`,detail:k.t(`cmd.themeDarkPresetDesc`),trailingLabel:r?.label},{label:k.t(`cmd.themeLightPresetOption`),value:`preset-light`,detail:k.t(`cmd.themeLightPresetDesc`),trailingLabel:i?.label}],onSelect:t=>{if(t===`preset-dark`){Ur(e,`dark`);return}if(t===`preset-light`){Ur(e,`light`);return}},onCancel:()=>{q(e,`theme`)}})}function Ur(e,t){let n=e.state.themeRegistry??Ve(),r=e.app.settings.get(`theme_preset`)??{},i=r[t]??t,a=[...n.list().filter(e=>e.appearance===t).map(e=>({label:e.label,value:e.id,detail:e.source.kind===`builtin`?k.t(`cmd.themePresetBuiltin`):k.t(`cmd.themePresetFromExtension`,{id:e.source.extensionId}),trailingLabel:e.id===i?`✓`:void 0})),{label:k.t(`cmd.themePresetReset`),value:`__reset__`,detail:k.t(`cmd.themePresetResetDesc`)}],o=n=>{let i={...r};n===void 0?delete i[t]:i[t]=n,e.tui.lifecycle.setPresetSelection?.(i)},s=()=>{e.tui.lifecycle.setPresetSelection?.(r)};e.tui.modal.openModal({kind:`select`,title:t===`dark`?k.t(`cmd.themePresetTitleDark`):k.t(`cmd.themePresetTitleLight`),options:a,onHighlight:e=>{o(e===`__reset__`?void 0:e)},onSelect:i=>{let a=i===`__reset__`?void 0:i,o={...r};a===void 0?delete o[t]:o[t]=a,e.tui.lifecycle.setPresetSelection?.(o),e.app.settings.persist({theme_preset:o},`global`);let s=a===void 0?t===`dark`?n.get(`dark`)?.label:n.get(`light`)?.label:n.get(a)?.label;e.tui.info.showToast(k.t(`cmd.titlePreference`),k.t(`cmd.themePresetSaved`,{label:s??a??t}))},onCancel:()=>{s(),e.tui.info.showToast(k.t(`cmd.titlePreference`),k.t(`cmd.selectCancelled`))}})}function Wr(e,t){e.state.currentLang=e.tui.lifecycle.setLanguage(t),vt(t),e.tui.plugins.setCommands(e.callbacks.refreshSlashCommands()),e.app.settings.persist({language:t}),e.tui.info.showToast(k.t(`cmd.titleLanguage`),k.t(`pref.languageSwitched`,{l:e.state.currentLang,name:e.state.currentLang===`zh`?`中文`:`English`}))}async function Gr(e,t){let r=t.app.workspaceDir??process.cwd(),i=e[0]?.toLowerCase()??`status`;if(i===`plugin`){let i=e[1]?.toLowerCase()===`untrust`,a=i?e[2]:e[1];if(!a){t.tui.info.showToast(k.t(`cmd.titlePlugin`),k.t(`cmd.pluginUsage`,{seg:(i?`untrust`:`trust`)==`untrust`?`untrust `:``}));return}let o=n({cwd:r,homedir:ae()}).find(e=>e.id===a);if(!o){t.tui.info.showToast(k.t(`cmd.titlePlugin`),k.t(`cmd.pluginNotFound`,{id:a}));return}i?(Ee(o.dir),t.tui.info.showToast(k.t(`cmd.titlePlugin`),k.t(`cmd.pluginUntrusted`,{id:a}))):u(t,o);return}if(i===`trust`){Te(r),t.tui.info.showToast(k.t(`cmd.titleCompat`),k.t(`cmd.compatTrusting`)),t.app.reloadCapabilities().then(e=>{t.tui.plugins.setPluginRegistrations(t.app.getPluginRegistrations()),t.tui.info.showToast(k.t(`cmd.titleCompat`),k.t(`cmd.compatTrusted`,{count:e.mcpTools}))},e=>t.tui.info.showToast(k.t(`cmd.titleCompat`),k.t(`cmd.compatReloadFailed`,{err:e instanceof Error?e.message:String(e)})));return}if(i===`untrust`){De(r),t.tui.info.showToast(k.t(`cmd.titleCompat`),k.t(`cmd.compatUntrusted`));return}let a=_e(r),o=he(r,{interactive:!0}),s=[];if(a.surface.any){let e=[a.surface.mcpJson?`.mcp.json`:null,a.surface.commands?`.claude/commands`:null].filter(Boolean),t=a.trusted?k.t(`cmd.compatTrustedLabel`):k.t(`cmd.compatUntrustedLabel`);s.push(`${e.join(k.t(`cmd.listSep`))} ${t}`)}if(o.highRiskKeys.length>0){let e=o.highRiskKeys.join(k.t(`cmd.listSep`));s.push(o.gated?k.t(`cmd.compatConfigGated`,{keys:e}):k.t(`cmd.compatConfigActive`,{keys:e}))}let c=n({cwd:r,homedir:ae()}).filter(e=>e.scope===`project`||e.scope===`repository`);for(let e of c){let t=ve(e);if(!t.surface.any)continue;let n=t.gated?k.t(`cmd.compatUntrustedLabel`):k.t(`cmd.compatTrustedLabel`);s.push(`plugin:${e.id} ${n}${t.gated?` → /trust plugin ${e.id}`:``}`)}if(s.length===0){t.tui.info.showToast(k.t(`cmd.titleCompat`),k.t(`cmd.compatNone`));return}o.gated?t.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleCompat`),lines:s}):t.tui.info.showToast(k.t(`cmd.titleCompat`),s.join(`
|
|
9
|
+
`))}async function Kr(e,t){let n=e[0];if(n===`clear`){t.app.clearSessionAlwaysAllow(t.state.session.id),t.tui.info.showToast(k.t(`cmd.titlePermissions`),k.t(`cmd.permsCleared`));return}if(n===`add`||n===`remove`){let r=e.slice(1).join(` `).trim();if(!r){t.tui.info.showToast(k.t(`cmd.titlePermissions`),k.t(`cmd.permsManageHint`));return}if(n===`add`){if(!t.app.isWellFormedAllowEntry(r)){t.tui.info.showToast(k.t(`cmd.titlePermissions`),k.t(`cmd.permsInvalidEntry`,{entry:r}));return}await t.app.allowToolAlways(r),t.tui.info.showToast(k.t(`cmd.titlePermissions`),k.t(`cmd.permsAdded`,{entry:r}))}else{let e=await t.app.disallowToolAlways(r);t.tui.info.showToast(k.t(`cmd.titlePermissions`),e?k.t(`cmd.permsRemoved`,{entry:r}):k.t(`cmd.permsNotFound`,{entry:r}))}return}let r=t.app.getSessionAlwaysAllow(t.state.session.id),i=t.app.settings.get(`permission_always_allow`)??[],a=(e,t)=>`${e} ${t.length?t.join(`, `):k.t(`cmd.permsEmpty`)}`;t.tui.modal.openModal({kind:`permissions`,lines:[a(k.t(`cmd.permsSessionLabel`),r),a(k.t(`cmd.permsProjectLabel`),i),``,k.t(`cmd.permsClearHint`),k.t(`cmd.permsManageHint`)]})}async function qr(e,n){let r=t();n.tui.info.showToast(k.t(`cmd.titleUpgrade`),k.t(`cmd.upgradeChecking`,{current:r}));let i=await yt(r);if(!i){n.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleUpgrade`),lines:[k.t(`cmd.upgradeNoNetwork`)]});return}if(!i.newer){n.tui.info.showToast(k.t(`cmd.titleUpgrade`),k.t(`cmd.upgradeLatest`,{current:r}));return}n.tui.modal.openModal({kind:`info`,title:k.t(`cmd.titleUpgrade`),lines:k.t(`cmd.upgradeAvailableLines`,{returnObjects:!0,current:r,latest:i.latest})})}async function Jr(e,t){if(!e.includes(`--force`))return!1;t.tui.info.showToast(k.t(`cmd.titleUpgrade`),k.t(`cmd.upgrading`));let{ok:n,error:r}=await St();return n?(t.state.restartRequested=!0,t.tui.lifecycle.stop(),!0):(t.tui.info.showToast(k.t(`cmd.titleUpgrade`),k.t(`cmd.upgradeFailed`,{err:r??k.t(`cmd.unknownError`)})),!0)}async function Yr(e,t,n){let r=k.t(`cmdDesc`,{returnObjects:!0}),i={session:k.t(`cmd.helpGroupSession`),model:k.t(`cmd.helpGroupModel`),agent:k.t(`cmd.helpGroupAgent`),debug:k.t(`cmd.helpGroupDebug`),ui:k.t(`cmd.helpGroupUi`),other:k.t(`cmd.helpGroupOther`)},a=[];for(let e of Li){let t=n.filter(t=>t.group===e&&!t.tuiHidden);if(t.length!==0)for(let n of t){let t=n.aliases?.length?[n.name,...n.aliases].map(e=>`/${e}`).join(`, `):`/${n.name}`;a.push({label:t,value:n.name,detail:r[n.name]??n.description??void 0,group:i[e],searchText:[n.name,...n.aliases??[]].join(` `)})}}let o=`${k.t(`cmd.helpPrefixes`)} !<cmd> ${k.t(`cmd.helpPrefixShell`)} · @<file> ${k.t(`cmd.helpPrefixFile`)}`;t.tui.modal.openModal({kind:`select`,title:k.t(`cmd.titleCommands`),subtitle:o,searchable:!0,options:a,onSelect:e=>{$(e,[],t)},onCancel:()=>{}})}async function Xr(e,t){t.tui.panes.togglePane(`history`)}async function Zr(e,t){t.tui.panes.togglePane(`notifications`)}async function Qr(e,t){t.tui.panes.togglePane(`prompts`)}async function $r(e,t){t.tui.panes.setServices(!0)}let ei;function ti(e){ei=e}const ni=async(e,t)=>{let n=ei;if(!n){t.tui.info.showToast(`Schedule`,`Schedule system not available`);return}let r=e[0];switch(r){case void 0:return ri(t);case`list`:return ii(n,t);case`add`:return ai(e.slice(1),n,t);case`remove`:return oi(e[1],n,t);case`run`:return si(e[1],n,t);case`enable`:return li(e[1],!0,n,t);case`disable`:return li(e[1],!1,n,t);case`logs`:return ui(e[1],t);case`cancel`:return ci(e[1],t);default:t.tui.info.showToast(`Schedule`,`/schedule ${r} — unknown subcommand. Use: add|list|remove|run|enable|disable|cancel|logs`)}};async function ri(e){let t=(e.app.getPluginPanelRegistrations?.()??[]).find(e=>e.pluginId===`plugin-schedule`);if(!t){e.tui.info.showToast(`Schedule`,`Schedule panel not installed — run "otto extension install plugin-schedule"`);return}e.tui.modal.openModal({kind:`pluginPanel`,panelInfo:{title:t.title,modulePath:t.modulePath,exportName:t.exportName,pluginId:t.pluginId},onClose:()=>{}})}async function ii(e,t){let n=e.list(),r=e.isFireOwner()?[]:e.fireOwnerFailureReason()===`network-error`?[`[read-only — could not reach the remote schedule service; check network/persistenced connectivity]`]:[`[read-only — another terminal holds the fire-ownership lease for this workspace]`];if(n.length===0){t.tui.info.showToast(`Schedule`,r.length>0?`No scheduled tasks. ${r[0]}`:`No scheduled tasks`);return}let i=[];for(let e of n){let t=e.lastFireFailed?`✕`:e.enabled?`◉`:`○`,n=e.recurring?e.cronExpression:`one-shot`,r=new Date(e.nextFireAt).toLocaleString(),a=e.lastFireFailed&&e.lastFireError?` (failed: ${e.lastFireError})`:``;i.push(`${t} ${e.id} ${e.name}${a}`),i.push(` ${n} next: ${r}`)}t.tui.messages.pushMessage({role:`command_echo`,command:`/schedule`,status:r.length>0?`warn`:`ok`,summary:r.length>0?r[0]:`${n.length} 个已排定任务`,detail:i.join(`
|
|
10
|
+
`)}),t.tui.panes.togglePane?.(`schedulePane`)}async function ai(e,t,n){if(e.length<2){n.tui.info.showToast(`Schedule`,`/schedule add [--once] <cron> <prompt>`);return}let r=!1,i=[...e],a=i.indexOf(`--once`);if(a!==-1&&(r=!0,i.splice(a,1)),i.length<2){n.tui.info.showToast(`Schedule`,`Opening schedule panel in create mode`),ri(n);return}let o=i[0],s=i.slice(1).join(` `);try{let e=t.add({name:s.slice(0,40),prompt:s,cronExpression:o,recurring:!r,origin:`user`}),i=r?`one-shot`:`recurring`,a=new Date(e.nextFireAt).toLocaleString();n.tui.info.showToast(`Schedule`,`${e.id}: ${e.name} (${i}) next: ${a}`)}catch(e){n.tui.info.showToast(`Schedule`,`Failed: ${e instanceof Error?e.message:String(e)}`)}}async function oi(e,t,n){if(!e){n.tui.info.showToast(`Schedule`,`/schedule remove <id>`);return}let r=t.remove(e);n.tui.info.showToast(`Schedule`,r?`Removed ${e}`:`Schedule "${e}" not found`)}async function si(e,t,n){if(!e){n.tui.info.showToast(`Schedule`,`/schedule run <id>`);return}try{t.runNow(e),n.tui.info.showToast(`Schedule`,`Triggering ${e}...`)}catch(e){n.tui.info.showToast(`Schedule`,`Failed: ${e instanceof Error?e.message:String(e)}`)}}async function ci(e,t){let n=ei;if(!n){t.tui.info.showToast(`Schedule`,`Schedule system not available`);return}if(!e){t.tui.info.showToast(`Schedule`,`/schedule cancel <id>`);return}let r=n.cancel(e);r.ok?t.tui.info.showToast(`Schedule`,`Canceled "${e}"`):t.tui.info.showToast(`Schedule`,`Cannot cancel "${e}": ${r.reason??`unknown`}`)}async function li(e,t,n,r){if(!e){r.tui.info.showToast(`Schedule`,`/schedule ${t?`enable`:`disable`} <id>`);return}let i=n.update(e,{enabled:t});r.tui.info.showToast(`Schedule`,i?`Schedule ${e} ${t?`enabled`:`disabled`}`:`Schedule "${e}" not found`)}async function ui(e,t){let n=T(Me,`schedule-logs`),r;try{r=ze(n)}catch{t.tui.info.showToast(`Schedule`,`No schedule logs found`);return}if(e&&(r=r.filter(t=>t.startsWith(e+`-`))),r.length===0){t.tui.info.showToast(`Schedule`,e?`No logs for schedule "${e}"`:`No schedule logs found`);return}r.sort().reverse();let i=r.slice(0,5),a=[];for(let e of i)try{let t=Le(T(n,e),`utf-8`).trim(),r=e.indexOf(`-`),i=r>0?e.slice(0,r):e;a.push(`${i} ${t}`)}catch{a.push(`${e} (unreadable)`)}let o=r.length-i.length;o>0&&a.push(`... and ${o} more entries`),t.tui.messages.pushMessage({role:`command_echo`,command:`/schedule logs`,summary:`${r.length} 条日志文件`,detail:a.join(`
|
|
11
|
+
`)})}function X(e){return Jt(e.state.session.session.getDrafts()??[])}function di(e,t){e.state.session.session.setDrafts(t),e.app.sessionManager.save(e.state.session.id).catch(()=>{}),e.tui.stores.tasks.setDrafts(X(e))}const fi=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return pi(e.slice(1),t);case`save`:return mi(e.slice(1),t);case`load`:return hi(e.slice(1),t);case`delete`:case`remove`:return gi(e.slice(1),t);default:t.tui.info.showToast(`Draft`,`/draft ${n} — unknown subcommand. Use: save|list|load|delete`)}};async function pi(e,t){let n=X(t);t.tui.stores.tasks.setDrafts(n),t.tui.panes.togglePane(`draftPane`,!0),n.length===0&&t.tui.info.showToast(`Draft`,`No drafts. Save one with Ctrl+S`)}async function mi(e,t){if(e.length===0){t.tui.info.showToast(`Draft`,`/draft save <name?> <text>`);return}let[n,...r]=e,i=r.length>0,a=i?n:void 0,o=i?r.join(` `):e.join(` `),s=X(t),c=Xt(a,o,s),l=Zt([...s,c]);try{di(t,l)}catch(e){t.tui.info.showToast(`Draft`,`Save failed: ${e instanceof Error?e.message:String(e)}`);return}t.tui.info.showToast(`Draft`,`Saved "${c.name}"`)}async function hi(e,t){let n=e.join(` `);if(!n){t.tui.info.showToast(`Draft`,`/draft load <name>`);return}let r=X(t).find(e=>e.name===n);if(!r){t.tui.info.showToast(`Draft`,`Draft "${n}" not found`);return}t.tui.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:r.text}]})}async function gi(e,t){let n=e.join(` `);if(!n){t.tui.info.showToast(`Draft`,`/draft delete <name>`);return}let r=X(t),i=r.find(e=>e.name===n);if(!i){t.tui.info.showToast(`Draft`,`Draft "${n}" not found`);return}let a=r.filter(e=>e.id!==i.id);try{di(t,a)}catch(e){t.tui.info.showToast(`Draft`,`Delete failed: ${e instanceof Error?e.message:String(e)}`);return}t.tui.info.showToast(`Draft`,`Removed "${i.name}"`)}const _i=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return vi(t);case`remove`:return yi(e[1],t);case`move`:return bi(e[1],e[2],t);case`clear`:return xi(t);default:t.tui.info.showToast(`Queue`,`/queue ${n} — unknown subcommand. Use: list|remove|move|clear`)}};async function vi(e){e.tui.panes.togglePane(`queuePane`,!0)}async function yi(e,t){let n=e?Number.parseInt(e,10):NaN;if(!Number.isInteger(n)||n<1){t.tui.info.showToast(`Queue`,`/queue remove <index> (1-based)`);return}t.tui.panes.removeQueuedAt(n-1),t.tui.info.showToast(`Queue`,`Removed item ${n}`)}async function bi(e,t,n){let r=e?Number.parseInt(e,10):NaN;if(!Number.isInteger(r)||r<1||t!==`up`&&t!==`down`){n.tui.info.showToast(`Queue`,`/queue move <index> <up|down> (1-based)`);return}let i=t===`down`?1:-1;n.tui.panes.moveQueuedItem(r-1,i),n.tui.info.showToast(`Queue`,`Moved item ${r} ${t}`)}async function xi(e){e.tui.panes.clearQueue(),e.tui.info.showToast(`Queue`,`Queue cleared`)}const Si=async(e,t)=>{let{session:n,agentProcessing:r}=t.state;if(n.isPaused&&!n.isBusy){n.resumeRun(),t.tui.info.showToast(k.t(`cmd.titleInfo`),k.t(`cmd.runResumedByCommand`)),Ci(t);return}if(n.isPaused&&n.isBusy){n.cancelPauseRun()?t.tui.info.showToast(k.t(`cmd.titleInfo`),k.t(`cmd.pauseCancelled`)):(n.resumeRun(),t.tui.info.showToast(k.t(`cmd.titleInfo`),k.t(`cmd.runResumedByCommand`))),Ci(t);return}if(r){n.pauseRun()?t.tui.info.showToast(k.t(`cmd.titlePauseRequested`),k.t(`cmd.runWillPauseAfterTurn`)):t.tui.info.showToast(k.t(`cmd.titleInfo`),k.t(`cmd.noRunningTaskToPause`)),Ci(t);return}t.tui.info.showToast(k.t(`cmd.titleInfo`),k.t(`cmd.nothingToPause`))};function Ci(e){let t=e.callbacks.refreshSlashCommands?.();t&&e.tui.plugins.setCommands(t)}async function wi(e,t){let n=t.app.settings.get(`keybinding_overrides`),r=()=>{t.tui.info.showToast(k.t(`cmd.keybindTitle`),k.t(`cmd.keybindSavedRestartHint`))};t.tui.modal.openModal({kind:`keybindingPanel`,overrides:n,onSave:(e,n,i)=>{let a=t.app.settings.get(`keybinding_overrides`)??{};t.app.settings.persist({keybinding_overrides:{...a,[e]:n}},i),r()},onSaveReplace:(e,n)=>{let i={...t.app.settings.get(`keybinding_overrides`)??{}};for(let t of e)i[t.commandId]=t.predicate;t.app.settings.persist({keybinding_overrides:i},n),r()},onReset:e=>{let n=t.app.settings.get(`keybinding_overrides`);if(!n||!(e in n))return;let{[e]:i,...a}=n;t.app.settings.persist({keybinding_overrides:a}),r()},onResetAll:()=>{t.app.settings.persist({keybinding_overrides:{}}),r()}})}function Ti(e){let t=e=>e.replace(/]/g,`\\]`),n=()=>{e.pluginInput.unregisterBySource(`extensions`);let n=e.extensions.list().filter(e=>e.category===`agent`||e.category===`skill`||e.category===`mcp`).map(e=>({label:`@${e.name}`,value:`[@${e.category}:${t(e.name)}]`,description:e.description||e.category,kind:e.category,source:`extensions`}));n.length&&e.pluginInput.register(n)};return n(),{refreshSigilExtensions:n}}function Ei(e){let t=e.trim().split(`
|
|
12
|
+
`)[0].replace(/\s+/g,` `).trim();return t.length>40?`${t.slice(0,39)}…`:t}function Di(e){e.pluginInput.unregisterBySource(`shortcut`);let t=(e.settings.get(`shortcuts`)??[]).map(e=>({label:`@${e.name}`,value:`[@shortcut:${e.name.replace(/]/g,`\\]`)}]`,description:Ei(e.text),kind:`shortcut`,source:`shortcut`}));t.length&&e.pluginInput.register(t)}function Oi(e,t){let n=e.modelRegistry.getAll();if(n.length===0)return;let r=e=>e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${Math.round(e/1e3)}k`:``,i=n.filter(e=>t.has(e.id)).sort((e,t)=>e.name.localeCompare(t.name)).map(e=>{let t=r(e.contextWindow),n=[];e.strengths&&e.strengths.length>0&&n.push(...e.strengths),t&&n.push(t);let i=n.length>0?`${e.provider} · ${n.join(` · `)}`:e.provider;return{label:e.name,value:`[@model:${e.id.replace(/]/g,`\\]`)}]`,description:i,kind:`model`,source:`builtin`}});e.pluginInput.unregisterBySource(`builtin-model`),e.pluginInput.register(i)}async function ki(e,t){t.tui.modal.openModal({kind:`shortcutsPanel`,shortcuts:t.app.getShortcuts(),onSave:(e,n,r)=>{t.app.saveShortcut(e,n,r).then(()=>Di(t.app)).catch(e=>{t.tui.info.showToast(`Shortcuts`,`Save failed: ${e instanceof Error?e.message:String(e)}`)})},onDelete:e=>{t.app.deleteShortcut(e).then(()=>Di(t.app)).catch(e=>{t.tui.info.showToast(`Shortcuts`,`Delete failed: ${e instanceof Error?e.message:String(e)}`)})}})}function Ai(e){let t;try{let n=Ie(e,`r`);try{t=Buffer.alloc(512);let e=Re(n,t,0,512,0);t=t.subarray(0,e)}finally{Fe(n)}}catch{return!1}if(t.length===0)return!1;let n=0;for(let e of t){if(e===0)return!0;!(e>=32&&e<127)&&!(e===9||e===10||e===13)&&!(e>=192&&e<=253)&&!(e>=128&&e<=191)&&n++}return n/t.length>.3}function ji(e){return e>=1048576?`${(e/1048576).toFixed(1)} MB`:e>=1024?`${(e/1024).toFixed(1)} KB`:`${e} B`}function Mi(e){let t;try{t=ze(e)}catch{return[]}let n=[];for(let r of t)try{let t=D(w(e,r));n.push({name:r,isDir:t.isDirectory(),size:t.isDirectory()?void 0:t.size})}catch{}return n}function Ni(e){return[...e].sort((e,t)=>e.isDir===t.isDir?e.name.localeCompare(t.name):e.isDir?-1:1)}function Z(e,t,n,r){let i=Ni(Mi(n)),a=Pe(t,n),o=a===``?k.t(`cmd.openBrowserSubtitleRoot`):k.t(`cmd.openBrowserSubtitleDir`,{relDir:a}),s=n!==t,c=i.map(e=>({label:e.isDir?`${e.name}/`:e.name,value:e.name,detail:e.isDir?void 0:ji(e.size??0)}));e.tui.modal.openModal({kind:`select`,title:k.t(`cmd.titleOpen`),subtitle:o,searchable:!0,options:c,initialFilter:r.get(n)??``,onFilterChange:e=>{r.set(n,e)},onSelect:i=>{let a=w(n,i),o;try{o=D(a).isDirectory()}catch{e.tui.info.showToast(k.t(`cmd.titleOpen`),k.t(`cmd.openNotFound`,{path:i}));return}if(o){Z(e,t,a,r);return}Pi(e,a,i,()=>{Z(e,t,n,r)}).catch(()=>{e.tui.info.showToast(k.t(`cmd.titleOpen`),k.t(`cmd.openNotFound`,{path:i}))})},onCancel:s?()=>Z(e,t,C(n),r):()=>{}})}async function Pi(e,t,n,r){if(Ai(t)){e.tui.info.showToast(k.t(`cmd.titleOpen`),k.t(`cmd.openBinaryRejected`,{path:n}));return}let{content:i,truncated:a}=await Ae(t);e.tui.modal.openModal({kind:`fileViewer`,path:n,content:i,preTruncated:a,onDismiss:r??(()=>{})})}async function Fi(e,t){let n=t.app.workspaceDir??process.cwd(),r=e.join(` `).trim(),i=new Map;if(!r){Z(t,n,n,i);return}let a=T(n,r),o=Pe(n,a).startsWith(`..`);if(!E(a)){if(o){t.tui.info.showToast(k.t(`cmd.titleOpen`),k.t(`cmd.openNotFound`,{path:r}));return}let e=C(a);for(;e!==n&&e!==C(e)&&!E(e);)e=C(e);if(E(e)&&D(e).isDirectory()){Z(t,n,e,i);return}t.tui.info.showToast(k.t(`cmd.titleOpen`),k.t(`cmd.openNotFound`,{path:r}));return}if(D(a).isDirectory()){if(o){t.tui.info.showToast(k.t(`cmd.titleOpen`),k.t(`cmd.openNotFound`,{path:r}));return}Z(t,n,a,i);return}await Pi(t,a,r)}var Ii=dt({DISPATCHABLE_COMMAND_NAMES:()=>Bi,ENGINE_BUILTIN_COMMANDS:()=>zi,HELP_GROUP_ORDER:()=>Li,SAFE_COMMAND_NAMES:()=>Ri,SLASH_COMMANDS:()=>Q,dispatchSlashCommand:()=>$,handleCompact:()=>Hn,handleMemory:()=>Vn});const Li=[`session`,`model`,`agent`,`debug`,`ui`,`other`],Q=[{name:`clear`,handler:un,engineBuiltin:!0,group:`session`,description:`Clear screen and reset interface state`},{name:`compact`,handler:Hn,group:`session`,description:`Compact context now, or /compact log for recent compaction/prune event details`},{name:`memory`,aliases:[`mem`],handler:Vn,group:`session`,description:`Project + user memory: /memory [user|project|<name>|forget <name>]`},{name:`workspace`,handler:Un,safe:!0,group:`session`,description:`Manage workspace settings: /workspace memory-sync [status|enable|disable] (RFC-164 R-form remote memory sync opt-in)`},{name:`status`,handler:Dn,safe:!0,engineBuiltin:!0,group:`session`,description:`Show session status (/status)`},{name:`open`,handler:Fi,safe:!0,group:`session`,description:`Open a file, or browse the current directory to find one: /open [path] (RFC-189)`},{name:`model`,aliases:[`m`],handler:d,group:`model`,description:`Switch model; /model [<id>|refresh]`},{name:`auth`,aliases:[`login`],handler:f,group:`model`,description:`Connect a model provider (OAuth or API key); /auth [<provider>]`},{name:`usage`,handler:Fn,safe:!0,engineBuiltin:!0,group:`model`,description:`Show provider usage quota snapshot (Anthropic OAuth subscription plans only)`},{name:`logout`,handler:p,group:`model`,description:`Remove stored credentials for a provider; /logout [<provider>]`},{name:`job`,handler:s,safe:!0,group:`agent`,description:`Start a background agent job: /job <directive> (worktree-isolated, full tools incl. MCP)`},{name:`schedule`,handler:ni,safe:!0,group:`agent`,description:`Manage scheduled tasks: /schedule add|list|remove|run|enable|disable <args>`},{name:`delegates`,handler:l,safe:!0,group:`agent`,description:`Toggle the Delegates panel (↑↓ select · k kill · o output · a apply)`},{name:`diagnose`,handler:mn,safe:!0,group:`debug`,description:`Surface improvement proposals from recurring hard failures (L1: suggest-only)`},{name:`context`,handler:On,safe:!0,group:`debug`,description:`Show context usage breakdown (system/tools/messages/cache/free bar)`},{name:`perf`,handler:jn,safe:!0,group:`debug`,description:`Open performance panel (memory pressure, rendering health)`},{name:`cache-stats`,handler:Mn,safe:!0,group:`debug`,description:`Open cache hit rate panel (session/last-turn hit ratio, per-model breakdown)`},{name:`gallery`,handler:Nn,safe:!0,group:`debug`,envGate:`OTTO_DEV`,description:`Open the TUI component gallery (all component examples; dev only, OTTO_DEV=1)`},{name:`trace-gc`,handler:Sn,group:`debug`,description:`Trace TTL lifecycle GC: /trace-gc [--ttl-days N] [--apply]. Cleans stale session trace files (not session data). TTL is based on the session's last agent engine activity time, not your last view/interaction time.`},{name:`session-archive-export`,handler:wn,group:`debug`,description:`Archive-export a cold session: /session-archive-export <sessionId> [--out <path>] [--and-delete]. Exports full session entries as JSON; optional --and-delete removes from DB after checksum verification + confirmation.`},{name:`effort`,handler:Dr,group:`ui`,description:`Switch reasoning effort (/effort low|medium|high|xhigh|max)`},{name:`preference`,aliases:[`pref`],handler:kr,safe:!0,group:`ui`,description:`Preferences: /preference [general|lang|theme]`},{name:`trust`,handler:Gr,safe:!0,group:`ui`,description:`Trust this project — apply its .otto/config.json high-risk keys + .claude executable config (/trust [status|trust|untrust])`},{name:`notification`,aliases:[`notif`],handler:Zr,group:`ui`,description:`Toggle the notification center panel (≡ ctrl+n)`},{name:`services`,handler:$r,safe:!0,group:`other`,description:`Show detected services from delegated background processes (/services)`},{name:`draft`,handler:fi,safe:!0,group:`ui`,description:`Manage saved drafts (≡ Ctrl+S save, Ctrl+O open panel): /draft [list|save <name?> <text>|load <name>|delete <name>]`},{name:`queue`,handler:_i,safe:!0,group:`ui`,description:`Open the queued-commands panel (≡ ctrl+q): /queue [list|remove <index>|move <index> <up|down>|clear]`},{name:`keybindings`,aliases:[`kb`],handler:wi,safe:!0,group:`ui`,description:`Open the keybinding panel: browse, search, remap, reset shortcuts (≡ default Ctrl+/)`},{name:`shortcuts`,handler:ki,safe:!0,group:`ui`,description:`Manage custom @ text shortcuts: [@shortcut:name] expands to predefined text on submit`},{name:`proxy`,handler:m,group:`ui`,description:`Configure HTTP proxy: /proxy [<url>|on|off|status|clear]`},{name:`help`,aliases:[`h`,`?`],safe:!0,engineBuiltin:!0,group:`other`,description:`Show available commands`,handler:async(e,t)=>Yr(e,t,Q)},{name:`exit`,aliases:[`quit`,`q`],safe:!0,engineBuiltin:!0,group:`other`,tuiHidden:!0,description:`Exit the TUI; /exit --restart to restart into the same session`},{name:`abort`,engineBuiltin:!0,group:`other`,tuiHidden:!0,description:`Abort the current agent run`},{name:`pause`,aliases:[`continue`],handler:Si,safe:!0,group:`other`,description:`Pause after current turn finishes (toggle with /continue)`},{name:`copy`,engineBuiltin:!0,group:`other`,tuiHidden:!0,description:`Copy last assistant response`},{name:`resume`,handler:fn,group:`other`,description:`List and switch to an existing session (--workspace <id>, --archived, --all)`},{name:`rename`,handler:dn,safe:!0,group:`session`,description:`Set a custom title for the current session (/rename <new title>)`},{name:`a2ui-action`,handler:xn,safe:!1,group:`session`,description:`Trigger A2UI interactive component action (/a2ui-action btn1 click)`},{name:`reload`,handler:pn,group:`other`,description:`Hot-reload capabilities (MCP / providers / declarative agents) without restart`},{name:`upgrade`,group:`other`,description:`Check for updates (/upgrade --check for extensions, /upgrade for otto CLI)`,handler:async(e,t)=>{if(e.includes(`--check`)){await Gn(e,t);return}await Jr(e,t)||await qr(e,t)}},{name:`about`,handler:Kn,safe:!0,group:`other`,description:`Show version, build, and environment info (/about)`},{name:`setup`,handler:gr,safe:!0,group:`other`,description:`Show onboarding progress (provider → login → model) with a jump-to-next-step button (/setup)`},{name:`extension`,aliases:[`extensions`,`ext`],handler:c,group:`other`,description:`Manage pluggable extensions (MCP / skills / agents / plugins / panels): ↑↓ select · Enter toggle/open · Esc close`},{name:`install`,handler:h,safe:!0,group:`other`,description:`Install a skill/plugin/MCP from a local archive/dir/URL (/install [--global] [--force] [--dry-run] [--sub-path <p>] [--ref <tag|branch>] --as <type> <source>)`},{name:`registry`,handler:_,safe:!0,group:`other`,description:`Manage plugin discovery registries (/registry [list|add <name> <url>|remove <name>]) — RFC-201`},{name:`search`,handler:g,safe:!0,group:`other`,description:`Search plugins/skills/MCP across registered registries (/search <keyword>) — RFC-201`},{name:`permissions`,aliases:[`perms`],handler:Kr,safe:!0,group:`other`,description:`View / clear the always-allow list (/permissions [clear])`},{name:`feedback`,handler:Jn,group:`other`,description:`Report an issue or send feedback via GitHub (/feedback [--repo <owner/repo>])`},{name:`archive`,handler:hn,safe:!0,description:`Toggle archive state (archived disables further input); /archive [<id>]`},{name:`session`,handler:yn,description:`Session management: /session fork | /session unlock <id> [--force] | /session kill <id> | /session inspect <id>`},{name:`fork`,handler:En,safe:!0,description:`Fork current session into a named branch`},{name:`pin`,aliases:[`unpin`],handler:gn,safe:!0,description:`Toggle pin state (pinned sessions sort to top of /resume); /pin [<id>...] [--group <name>]`},{name:`history`,aliases:[`hist`],handler:Xr,safe:!0,description:`Open history search panel (same panel as Ctrl+R)`},{name:`prompts`,handler:Qr,safe:!0,description:`View prompt log (list of submitted prompts this session)`}],Ri=new Set(Q.filter(e=>e.safe).flatMap(e=>[e.name,...e.aliases??[]])),zi=new Set(Q.filter(e=>e.engineBuiltin).flatMap(e=>[e.name,...e.aliases??[]])),Bi=new Set(Q.filter(e=>e.handler).flatMap(e=>[e.name,...e.aliases??[]]));async function $(e,t,n){let r=Q.find(t=>t.name===e);return r||=Q.find(t=>t.aliases?.includes(e)),r?.handler?(await r.handler(t,n),!0):!1}export{Je as A,It as B,$t as C,qt as D,Jt as E,Nt as F,vt as G,P as H,L as I,M as J,N as K,Pt as L,Ut as M,Ht as N,Be as O,At as P,jt as R,Qt as S,Xt as T,wt as U,kt as V,_t as W,dt as Y,ar as _,Ii as a,an as b,Oi as c,vr as d,Cr as f,or as g,Sr as h,Q as i,R as j,He as k,Ti as l,br as m,zi as n,$ as o,xr as p,gt as q,Ri as r,Di as s,Bi as t,ti as u,er as v,Zt as w,V as x,zn as y,Mt as z};
|
|
13
|
+
//# sourceMappingURL=command-dispatcher-8fY1u4JK.js.map
|