@x-otto/cli 0.0.1-alpha.15 → 0.0.1-alpha.16-debug
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-CIFJCmlj.js +3 -0
- package/dist/build-id-CIFJCmlj.js.map +1 -0
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/meta.json +1 -1
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/plugin.cjs +16 -6
- package/dist/bundled-extensions/plugin-otto-wire-protocols/src/openai-completions.ts +12 -5
- package/dist/bundled-extensions/plugin-otto-wire-protocols/src/openai-responses.ts +4 -1
- package/dist/command-dispatcher-DibEV53Q.js +17 -0
- package/dist/command-dispatcher-DibEV53Q.js.map +1 -0
- package/dist/{extension-plugin-u-j4qspX.js → extension-plugin-D7gnpllF.js} +3 -3
- package/dist/{extension-plugin-u-j4qspX.js.map → extension-plugin-D7gnpllF.js.map} +1 -1
- package/dist/extension-plugin-fPDz7XlG.js +2 -0
- package/dist/{feedback-kStioJn1.js → feedback-BVl4sRah.js} +2 -2
- package/dist/{feedback-kStioJn1.js.map → feedback-BVl4sRah.js.map} +1 -1
- package/dist/feedback-DAY-1bJ0.js +2 -0
- package/dist/index.js +10 -12
- package/dist/index.js.map +1 -1
- package/dist/model-auth-BxHBaDQx.js +2 -0
- package/dist/{model-auth-DyDSJSnS.js → model-auth-Dih25xOB.js} +2 -2
- package/dist/{model-auth-DyDSJSnS.js.map → model-auth-Dih25xOB.js.map} +1 -1
- package/dist/parse-cli-Dr-Fl0on.js +3 -0
- package/dist/{parse-cli-CqdN77oJ.js.map → parse-cli-Dr-Fl0on.js.map} +1 -1
- package/dist/{version-GXX-_4a_.js → version-Cd8HZ7ua.js} +2 -2
- package/dist/{version-GXX-_4a_.js.map → version-Cd8HZ7ua.js.map} +1 -1
- package/package.json +1 -1
- package/dist/build-id-DC7yuO1H.js +0 -3
- package/dist/build-id-DC7yuO1H.js.map +0 -1
- package/dist/command-dispatcher-BWljueVa.js +0 -13
- package/dist/command-dispatcher-BWljueVa.js.map +0 -1
- package/dist/extension-plugin-Dn_oVAX2.js +0 -2
- package/dist/feedback-BfGYf8Iv.js +0 -2
- package/dist/model-auth-D0pGB0He.js +0 -2
- package/dist/parse-cli-CqdN77oJ.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-id-CIFJCmlj.js","names":[],"sources":["../src/build-id.ts"],"sourcesContent":["// auto-generated by scripts/gen-build-id.mjs — DO NOT EDIT\nexport const BUILD_ID = 4666\nexport const BUILD_BRANCH = 'dev'\nexport const BUILD_HASH = 'ef6ab3815'\n"],"mappings":";AACA,MAAa,EAAW,KAEX,EAAa"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"apiVersion":1,"compilerVersion":"0.1.0-alpha.3","sourceHash":"
|
|
1
|
+
{"apiVersion":1,"compilerVersion":"0.1.0-alpha.3","sourceHash":"751b68806b51427abf0408f41b78808a83834412f82502bb918d492e4cd44b57"}
|
|
@@ -6768,7 +6768,10 @@ var OpenAIResponsesStream = class {
|
|
|
6768
6768
|
body,
|
|
6769
6769
|
headers: this.buildHeaders(auth, model.provider),
|
|
6770
6770
|
signal,
|
|
6771
|
-
|
|
6771
|
+
// RFC-361 D5:不再兜底 300s——那会让墙钟先于首字节空闲阈值(默认 900s)触发,
|
|
6772
|
+
// 使分段计时成为死代码。`stream()` 会按 `max(requested, firstTokenIdle + 余量)`
|
|
6773
|
+
// 统一解析,保证墙钟总是大于首字节阈值。o3/o1 等 reasoning 模型的长思考同样受益。
|
|
6774
|
+
timeout: options.timeout,
|
|
6772
6775
|
onResponse: (h) => {
|
|
6773
6776
|
responseHeaders = h;
|
|
6774
6777
|
}
|
|
@@ -6914,11 +6917,18 @@ var OpenAICompletionsStream = class {
|
|
|
6914
6917
|
identity: { api: model.api, provider: model.provider, model: model.id },
|
|
6915
6918
|
signal,
|
|
6916
6919
|
timeout: options.timeout,
|
|
6917
|
-
// RFC-
|
|
6918
|
-
//
|
|
6919
|
-
//
|
|
6920
|
-
//
|
|
6921
|
-
|
|
6920
|
+
// RFC-361:**不再**给 reasoning 模型统一放大 idleTimeout。
|
|
6921
|
+
//
|
|
6922
|
+
// 旧做法(`idleTimeout: model.reasoning ? 300_000 : undefined`)是"把阈值往上堆"的
|
|
6923
|
+
// 治标手段:它同时放宽了两个语义完全不同的阶段——"首 token 前的长思考"(正常)与
|
|
6924
|
+
// "已开始吐字后突然静默"(真卡死)。后果有二:①300s 对 deepseek-v4-flash·max 的
|
|
6925
|
+
// thinking 仍然不够,误杀照旧(真机实测 4 个长推理任务因此失败);②真卡死的检测被
|
|
6926
|
+
// 无谓延迟到 5 分钟。
|
|
6927
|
+
//
|
|
6928
|
+
// 新机制由 `@x-otto/shared` 的 `stream()` 分段承担:首字节前默认 900s(放行长思考),
|
|
6929
|
+
// 首字节后回到 120s(保持对流中断的灵敏度)。故此处不再需要按 `model.reasoning`
|
|
6930
|
+
// 区分——分段判据比"模型是否声明 reasoning"更准(同一个 reasoning 模型的不同 turn,
|
|
6931
|
+
// 思考时长差异极大,用模型属性预测本就是弱相关变量)。
|
|
6922
6932
|
// RFC-232(终局修正):跨 wire 协议救回违约响应,见 @x-otto/provider stream-state.ts。
|
|
6923
6933
|
registeredToolNames: (0, import_provider3.registeredToolNames)(context.tools)
|
|
6924
6934
|
});
|
|
@@ -133,11 +133,18 @@ class OpenAICompletionsStream implements ProviderStream {
|
|
|
133
133
|
identity: { api: model.api, provider: model.provider, model: model.id },
|
|
134
134
|
signal,
|
|
135
135
|
timeout: options.timeout,
|
|
136
|
-
// RFC-
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
//
|
|
140
|
-
|
|
136
|
+
// RFC-361:**不再**给 reasoning 模型统一放大 idleTimeout。
|
|
137
|
+
//
|
|
138
|
+
// 旧做法(`idleTimeout: model.reasoning ? 300_000 : undefined`)是"把阈值往上堆"的
|
|
139
|
+
// 治标手段:它同时放宽了两个语义完全不同的阶段——"首 token 前的长思考"(正常)与
|
|
140
|
+
// "已开始吐字后突然静默"(真卡死)。后果有二:①300s 对 deepseek-v4-flash·max 的
|
|
141
|
+
// thinking 仍然不够,误杀照旧(真机实测 4 个长推理任务因此失败);②真卡死的检测被
|
|
142
|
+
// 无谓延迟到 5 分钟。
|
|
143
|
+
//
|
|
144
|
+
// 新机制由 `@x-otto/shared` 的 `stream()` 分段承担:首字节前默认 900s(放行长思考),
|
|
145
|
+
// 首字节后回到 120s(保持对流中断的灵敏度)。故此处不再需要按 `model.reasoning`
|
|
146
|
+
// 区分——分段判据比"模型是否声明 reasoning"更准(同一个 reasoning 模型的不同 turn,
|
|
147
|
+
// 思考时长差异极大,用模型属性预测本就是弱相关变量)。
|
|
141
148
|
// RFC-232(终局修正):跨 wire 协议救回违约响应,见 @x-otto/provider stream-state.ts。
|
|
142
149
|
registeredToolNames: registeredToolNames(context.tools),
|
|
143
150
|
})
|
|
@@ -464,7 +464,10 @@ class OpenAIResponsesStream implements ProviderStream {
|
|
|
464
464
|
body,
|
|
465
465
|
headers: this.buildHeaders(auth, model.provider),
|
|
466
466
|
signal,
|
|
467
|
-
|
|
467
|
+
// RFC-361 D5:不再兜底 300s——那会让墙钟先于首字节空闲阈值(默认 900s)触发,
|
|
468
|
+
// 使分段计时成为死代码。`stream()` 会按 `max(requested, firstTokenIdle + 余量)`
|
|
469
|
+
// 统一解析,保证墙钟总是大于首字节阈值。o3/o1 等 reasoning 模型的长思考同样受益。
|
|
470
|
+
timeout: options.timeout,
|
|
468
471
|
onResponse: (h) => {
|
|
469
472
|
responseHeaders = h
|
|
470
473
|
},
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{t as e}from"./build-id-CIFJCmlj.js";import{t}from"./version-Cd8HZ7ua.js";import{t as n}from"./discover-with-bundled-wSuXDvNc.js";import{n as r,r as i,t as a}from"./service-client-BLNeugM9.js";import{n as o}from"./extension-DAex6RFK.js";import{a as s,i as c,r as l,s as u}from"./extension-plugin-D7gnpllF.js";import{n as d,r as f,t as p}from"./model-auth-Dih25xOB.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-BVl4sRah.js";import{createRequire as te}from"node:module";import{arch as ne,cpus as re,freemem as y,homedir as b,platform as ie,release as ae,totalmem as oe}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 fe,PLUGIN_MANIFEST_FILENAME as pe,checkUpgrades as me,collectPluginPerfMetrics as he,detectProjectConfigGating as ge,discoverFileCommands as _e,discoverPlugins as ve,evaluateClaudeTrust as ye,evaluatePluginTrust as be,findWorkspaceRoot as xe,getLastAssistantText as x,parsePluginManifest as Se,readSkillLoopStatus as Ce,resolvePackageDir as we,resolveSessionTitle as Te,scanInstalledVersions as Ee,trustProject as De,untrustPlugin as Oe,untrustProject as ke}from"@x-otto/coding";import{checkShellCommand as Ae,openBrowser as je,readFileCapped as Me}from"@x-otto/shared";import{BUILD_ID as Ne,OTTO_HOME as Pe,SDK_VERSION as Fe}from"@x-otto/env";import{dirname as S,join as C,relative as Ie,resolve as w}from"node:path";import{closeSync as Le,existsSync as T,openSync as Re,readFileSync as ze,readSync as Be,readdirSync as Ve,statSync as E}from"node:fs";import{FIGURES as D,buildTurnSummary as He,createBuiltinThemeRegistry as Ue,createReducerState as We,deriveTurnBoundaries as Ge,detectLanguage as Ke,formatProviderUsageLimitTypeFull as qe,i18next as O,initI18n as Je,insertTurnSummaries as Ye,reduceToTui as Xe}from"@x-otto/tui";import{createBuiltinCommands as Ze}from"@x-otto/tui/compat";import{MaxToolTurnsError as Qe,PromptBudgetExceededError as $e}from"@x-otto/agent";import{readFile as et,readdir as tt,stat as nt,unlink as rt}from"node:fs/promises";import{DEFAULT_COMPACTION_CONFIG as it,DEFAULT_PRUNE_CONFIG as at,estimateTokensHeuristic as ot,resolveContextSize as st}from"@x-otto/memory";import{classifyAuthErrorType as ct,computeCacheHitRatio as lt,createModelUsabilityGate as k,getToolCallsByAssistantMessage as ut,isAuthError as dt}from"@x-otto/ai";import{promisify as ft}from"node:util";var pt=Object.defineProperty,mt=(e,t)=>{let n={};for(var r in e)pt(n,r,{get:e[r],enumerable:!0});return t||pt(n,Symbol.toStringTag,{value:`Module`}),n},ht=te(import.meta.url);function gt(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 _t(e,t){let n=x(e.session.messages())||t.partialText,r=gt(t);return n?`${n}\n${r}`:r}function vt(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 yt(e,t){let n=x(e.session.messages())||t.partialText,r=vt(t);return n?`${n}\n${r}`:r}async function bt(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 Qe||t instanceof $e){let n=t instanceof $e,r=n?vt(t):gt(t);o?.(n?`budget-exceeded`:`max-tool-turns`,r);let l=o?x(e.session.messages())||t.partialText:n?yt(e,t):_t(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}),x(n)}let l=x(e.session.messages());return s(l),l}async function xt(e,t){try{await e.prompt(t)}catch(t){if(t instanceof Qe)return{sessionId:e.id,status:`max_turns`,messageCount:e.session.messages().length,response:x(e.session.messages())||t.partialText};if(t instanceof $e)return{sessionId:e.id,status:`budget_exceeded`,messageCount:e.session.messages().length,response:x(e.session.messages())||t.partialText};throw t}return{sessionId:e.id,status:e.status,messageCount:e.session.messages().length,response:x(e.session.messages())}}var A=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=Ze()}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=Ae(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 bt(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 bt(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 St(){return Ke()}function Ct(e=`auto`){let t=e===`auto`?Ke():e;return Je(t),t}async function wt(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:Tt(i,e)>0}:null}catch{return null}}function Tt(e,t){let n=Et(e),r=Et(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 Et(e){let t=/(\d+)\.(\d+)\.(\d+)/.exec(e);return t?[Number(t[1]),Number(t[2]),Number(t[3])]:null}async function Dt(){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 Ot(e){return e?Date.now()-e>216e5:!0}async function kt(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||!Ot(e.lastCheck)?null:wt(e.currentVersion).then(async t=>t&&(e.persistLastCheck().catch(()=>{}),t.newer)?{...t,forced:!1}:null).catch(()=>null)}const At=ot;let j,jt;function Mt(e){let t=e.map(e=>e.name).sort().join(`,`);if(j!==void 0&&jt===t)return j;let n=e=>typeof e==`function`?`[fn]`:typeof e==`string`?e:``;return j=At(JSON.stringify(e.map(e=>({name:e.name,description:n(e.description),parameters:e.parameters})))),jt=t,j}let M,Nt;function Pt(e){return M!==void 0&&Nt===e?M:(M=At(e),Nt=e,M)}function N(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=Pt(t)+Mt(n),h=a+o+r+i+p,g=Math.max(0,h-m),_=Math.max(0,s-m-g),ee=st(at.trigger,s),v=st(it.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 Ft={openai:`OpenAI`};function It(e){let t=[`confirm`,`auto`,`bypass`];return t[(t.indexOf(e)+1)%t.length]??`confirm`}function Lt(e){return e===`error`?`error`:e===`approval_required`||e===`input_required`?`warning`:`info`}function Rt(e,t,n){let r=t===void 0?void 0:{code:t},i=r!==void 0&&dt(r),a=i&&ct(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 P(e){return e?e.toLowerCase()===`xhigh`?`XHigh`:e.charAt(0).toUpperCase()+e.slice(1):``}function zt(e,t,n){return e?`${t.on} ${n.on}`:`${t.off} ${n.off}`}function F(e,t,n){if(!t)return`(no model)`;let r=P(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 Bt(e,t){let n=[..._e(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 Vt(e){return{id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}}function Ht(e){return{type:`thinking`,thinking:e.text}}function Ut(e){return{type:`text`,text:e.text}}function Wt(e){return{type:`a2ui`,version:e.version,components:e.components}}function Gt(e){let t=[],n=[];for(let r of e)switch(r.type){case`text`:r.text.trim()&&t.push(Ut(r));break;case`thinking`:r.text.trim()&&t.push(Ht(r));break;case`tool_call`:n.push(Vt(r));break;case`a2ui`:t.push(Wt(r));break}return{content:t,toolCalls:n}}function Kt(e){return typeof e==`string`?e.trim():e.filter(e=>e.type===`text`).map(e=>e.text).join(``).trim()}function qt(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 I(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=Kt(e.content);t&&i.push({role:`user`,content:t});continue}if(e.role===`assistant`){let{content:t}=Gt(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:qt(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:qt(r),argsObj:r,result:Kt(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 Jt=ft(se);function Yt(e,t,n){for(let r of e){if(r.role!==`assistant`)continue;let e=ut(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 Xt(e,t){let n=S(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=ze(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 Zt(e,t){let n=S(e),r=async e=>{try{let{stdout:t}=await Jt(`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 et(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 Qt(e){return[...e].sort((e,t)=>t.savedAt-e.savedAt)}function $t(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 en(e,t,n){let r=Date.now();return{id:`${r.toString(36)}-${Math.random().toString(36).slice(2,6)}`,name:$t(e,n),text:t,savedAt:r}}function tn(e){return e.length<=50?[...e]:e.slice(-50)}function L(e){let t=I(e.session.visibleMessages()),n=e.session.getTurnSummaries();return!n||n.length===0?t:Ye(t,n,e.session.getTurnCount()??t.filter(e=>e.role===`user`).length)}function nn(e){let{resumedNote:t,isFound:n,session:r,projState:i,tui:a}=e,o=L(r);a.messages.pushMessages(o),n&&o.length>0&&a.info.setTopView({session:r.id}),a.info.showToast(n?O.t(`cmd.titleSessionResumed`):O.t(`cmd.titleSession`),t.replace(/^↻ /,``)),rn({session:r,projState:i,tui:a,chatMsgs:o})}function rn(e){let{session:t,projState:n,tui:r}=e,i=e.chatMsgs??L(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(O.t(`cmd.titleSession`),O.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(Ge(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?Yt(e,t.toolCallId,n):{};return r.oldContent===void 0&&r.newContent===void 0&&(r=Xt(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(Qt(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 R=new Map;function an(e){return R.get(e)}function z(e){R.delete(e);let t=H.get(e);t&&(clearTimeout(t),H.delete(e))}function on(){return[...R.values()]}function B(e,t,n){let r={id:e,transcript:I(t),streaming:``,status:n?`busy`:`idle`,lastActivityAt:Date.now()};return R.set(e,r),r}function sn(e,t){let n=R.get(e);n&&(n.transcript=I(t),n.lastActivityAt=Date.now())}const V=new Set;function cn(e){return V.add(e),()=>{V.delete(e)}}const H=new Map;function ln(e){let t=H.get(e.id);t&&clearTimeout(t),H.set(e.id,setTimeout(()=>{H.delete(e.id);for(let t of V)t(e)},300))}function un(e,t){let n=``,r=t=>{e.status!==t&&(e.status=t,ln(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`),sn(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(),ln(e);return}},()=>e]}function dn(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 fn(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${dn(s)}`}]}),t.tui.info.showToast(`/session inspect`,`已查看会话 ${s.session.id}(只读快照;如需实时参与该会话请用 otto --attach ${s.session.id})`)}async function pn(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(F(t.app,n.id,t.state.session.thinkingLevel));let r=n?.contextWindow??2e5,i=N({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(O.t(`cmd.titleCleared`),O.t(`cmd.clearedDone`))}async function mn(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 hn(e,t){let n,r,i=!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].startsWith(`--`)||(n=e[t]);let a=r?{workspaceId:r}:void 0,o=await t.app.listAllSessions(a),s=o.filter(e=>e.status===`archived`).length,c=n?o:o.filter(e=>i?e.status===`archived`:e.status!==`archived`).filter(e=>(e.entryCount??e.messageCount)>0),l=(e,t,n)=>e.tui.info.showToast(t,n),u=async e=>{if(e===t.state.session.id){l(t,O.t(`cmd.titleResume`),O.t(`cmd.resumeAlreadyOn`));return}let n=t.app.getSession(e)??await t.app.sessionManager.restore(e);if(!n){l(t,O.t(`cmd.titleResume`),O.t(`cmd.resumeSessionNotFound`,{idShort:e.slice(0,8)}));return}let r=t.state.session;if(t.state.session.isBusy){let[e]=un(B(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 B(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 A(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(F(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=an(n.id);if(a)t.tui.messages.pushMessages(a.transcript),z(n.id);else{let e=L(n);t.tui.messages.pushMessages(e)}t.callbacks.restoreSwitchedSession(),t.tui.info.setTopView({session:n.id}),l(t,O.t(`cmd.titleResume`),O.t(`cmd.resumeSwitched`,{idShort:e.slice(0,8),count:n.session.messages().length}))};if(n){let e=c.find(e=>e.id===n);if(e){await u(e.id);return}let r=c.find(e=>e.id.startsWith(n));if(r){await u(r.id);return}let i=c.find(e=>e.id.includes(n));if(i){await u(i.id);return}l(t,O.t(`cmd.titleResume`),O.t(`cmd.sessionNoMatch`,{arg:n}));return}if(c.length===0){l(t,O.t(`cmd.titleResume`),O.t(`cmd.resumeNoSaved`));return}let d=t.state.session.id,f=c.some(e=>e.pinned);function p(e){if(!e.pinned)return``;let t=e.pinGroup?.trim();return t?`\u0001${t.toLowerCase()}`:`\0`}let m=[...c].sort((e,t)=>{let n=p(e).localeCompare(p(t));if(n!==0)return n;let r=e.updatedAt?.getTime()??e.createdAt.getTime();return(t.updatedAt?.getTime()??t.createdAt.getTime())-r});function h(e){if(f)return e.pinned?e.pinGroup?.trim()||O.t(`cmd.resumeDefaultPinGroup`):O.t(`cmd.resumeRecentGroup`)}function g(e){if(!e)return``;let t=Math.max(0,Math.floor((Date.now()-e.getTime())/1e3));return t<10?O.t(`cmd.agoJustNow`):t<60?O.t(`cmd.agoSeconds`,{n:t}):t<3600?O.t(`cmd.agoMinutes`,{n:Math.floor(t/60)}):t<86400?O.t(`cmd.agoHours`,{n:Math.floor(t/3600)}):O.t(`cmd.agoDays`,{n:Math.floor(t/86400)})}let _=c[0]?.updatedAt?g(c[0].updatedAt):`—`,ee=c.reduce((e,t)=>e+(t.messageCount??0),0),v=r?` [workspace: ${r}]`:``,te=[!i&&s>0?O.t(`cmd.resumeArchivedHiddenHint`,{count:s}):``].filter(Boolean),ne=te.length>0?` ${te.join(` `)}`:``,re=new Map(on().map(e=>[e.id,e])),y=0,b=0,ie=e=>{if(e.id===d)return``;let n=re.get(e.id);return n?n.status===`busy`?(y++,`● ${O.t(`cmd.resumeStatusBusy`)} · `):n.status===`needs-input`?(b++,`● ${O.t(`cmd.resumeStatusNeedsInput`)} · `):`· ${O.t(`cmd.resumeStatusIdle`)} · `:t.app.getSession(e.id)?.isBusy?(y++,`● ${O.t(`cmd.resumeStatusBusy`)} · `):``},ae=[y>0?`${y} ${O.t(`cmd.resumeStatusBusy`)}`:``,b>0?`${b} ${O.t(`cmd.resumeStatusNeedsInput`)}`:``].filter(Boolean).join(`, `),oe=ae?` · ${ae}`:``,se=O.t(`cmd.resumeSubtitle`,{sessions:c.length,msgs:ee,recent:_})+oe+ne,ce=i?O.t(`cmd.resumeArchivedOnlyTitle`,{n:c.length}):O.t(`cmd.resumeSelectTitle`,{n:c.length});t.tui.modal.openModal({kind:`select`,title:ce+v,subtitle:se,searchable:!0,maxVisible:13,options:m.map(e=>{let t=e.id===d?`●`:` `,n=e.pinned?O.t(`cmd.resumePinnedPrefix`):``,r=e.title||e.id.slice(0,8),i=e.status===`archived`?O.t(`cmd.resumeArchivedSuffix`):``,a=e.writeLocked?O.t(`cmd.resumeReadOnlySuffix`):``,o=`${n}${r}${i}`,s=g(e.updatedAt),c=[ie(e).trim(),s,O.t(`welcome.msgCountLabel`,{count:e.messageCount??0}),a.trim()].filter(Boolean);return{label:`${t} ${o}`,trailingLabel:c.join(` · `),value:e.id,searchText:o,group:h(e)}}),detailPlacement:`inline`,onSelect:e=>{u(e).catch(e=>l(t,O.t(`cmd.titleResume`),O.t(`cmd.resumeFailed`,{msg:e instanceof Error?e.message:String(e)})))},onCancel:()=>{}})}async function gn(e,t){t.app.reloadCapabilities().then(e=>{t.tui.plugins.setPluginRegistrations(t.app.getPluginRegistrations()),t.tui.info.showToast(O.t(`cmd.titleReload`),O.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:O.t(`cmd.reloadFailed`,{msg:e instanceof Error?e.message:String(e)})}))}async function _n(e,t){let n=t.app.diagnoser.propose();if(n.length===0){t.tui.info.showToast(O.t(`cmd.titleDiagnose`),O.t(`cmd.diagnoseNone`));return}let r=n.map((e,t)=>O.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:O.t(`cmd.diagnoseSummary`,{count:n.length}),detail:r.join(`
|
|
5
|
+
`)})}async function vn(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(O.t(`cmd.titleArchive`),O.t(`cmd.sessionNoMatch`,{arg:n}));return}if(r.status===`archived`){let e=t.app.getSession(r.id);if(!e){t.tui.info.showToast(O.t(`cmd.titleUnarchive`),O.t(`cmd.unarchiveNotLoaded`,{idShort:r.id.slice(0,8)}));return}e.unarchive(),t.tui.info.showToast(O.t(`cmd.titleUnarchive`),O.t(`cmd.unarchiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}));return}if(!await t.app.archiveSession(r.id)){t.tui.info.showToast(O.t(`cmd.titleArchive`),O.t(`cmd.archiveCannot`,{idShort:r.id.slice(0,8)}));return}t.tui.info.showToast(O.t(`cmd.titleArchive`),O.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(O.t(`cmd.titleUnarchive`),O.t(`cmd.unarchiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}));return}r.archive(),t.tui.info.showToast(O.t(`cmd.titleArchive`),O.t(`cmd.archiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}))}async function yn(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(O.t(`cmd.titlePin`),O.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(O.t(`cmd.titleUnpin`),O.t(`cmd.unpinDone`,{idShort:e.id.slice(0,8),title:e.title??``}))):(e.pin(),t.tui.info.showToast(O.t(`cmd.titlePin`),O.t(`cmd.pinDone`,{idShort:e.id.slice(0,8),title:e.title??``}))),U(t);return}if(r.length===0){bn(t.state.session.id,n,t),U(t);return}if(r.length===1){bn(r[0],n,t),U(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(O.t(`cmd.titlePin`),O.t(`cmd.pinBatchSummary`,{seg:o.length>0?`${a} pinned (${o.length} not found: ${o.join(`, `)})`:`${a} pinned`})),U(t)}function U(e){let t=e.callbacks.refreshSlashCommands();e.tui.plugins.setCommands(t)}function bn(e,t,n){if(e===n.state.session.id){xn(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(O.t(`cmd.titlePin`),O.t(`cmd.sessionNoMatch`,{arg:e}));return}let a=n.app.getSession(i.id);if(!a){n.tui.info.showToast(O.t(`cmd.titlePin`),O.t(`cmd.pinNotLoaded`,{idShort:i.id.slice(0,8)}));return}xn(a,t,n)}function xn(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(O.t(`cmd.titleUnpin`),O.t(`cmd.unpinDone`,{idShort:r,title:i}));return}e.pin(t),n.tui.info.showToast(O.t(`cmd.titlePin`),O.t(`cmd.pinGroupDone`,{idShort:r,title:i,group:t}));return}e.pin(t),t===void 0?n.tui.info.showToast(O.t(`cmd.titlePin`),O.t(`cmd.pinDone`,{idShort:r,title:i})):n.tui.info.showToast(O.t(`cmd.titlePin`),O.t(`cmd.pinGroupDone`,{idShort:r,title:i,group:t}))}async function Sn(e,t){let n=e[0];if(n===`fork`){await Cn(e.slice(1),t);return}if(n===`kill`){await Dn(e.slice(1),t);return}if(n===`inspect`){await fn(e.slice(1),t);return}if(n!==`unlock`){t.tui.info.showToast(O.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(O.t(`cmd.titleSessionUnlock`),O.t(`cmd.unlockUsage`));return}let o=t.app.sessionManager.inspectSessionWriteLease(a),s=a.slice(0,8);if(!o.locked){t.tui.info.showToast(O.t(`cmd.titleSessionUnlock`),O.t(`cmd.unlockNotLocked`,{idShort:s}));return}let c=o.alive===!0?O.t(`cmd.unlockAliveConfirmed`):o.alive===!1?O.t(`cmd.unlockDeadConfirmed`):O.t(`cmd.unlockUnknownAlive`),l=Math.round((o.mtimeAgoMs??0)/1e3);if(!i){t.tui.messages.pushMessage({role:`command_echo`,command:`/session unlock`,summary:O.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:O.t(`cmd.unlockHungWarning`,{idShort:s})}),t.tui.modal.openModal({kind:`confirm`,title:O.t(`cmd.unlockConfirmTitle`),message:O.t(`cmd.unlockConfirmMessage`,{idShort:s,pid:o.pid,hostname:o.hostname}),confirmLabel:O.t(`cmd.unlockConfirmLabel`),cancelLabel:O.t(`cmd.unlockCancelLabel`),dangerous:!0,onConfirm:()=>{t.app.sessionManager.forceReleaseSessionWriteLease(a),t.tui.info.showToast(O.t(`cmd.titleSessionUnlock`),O.t(`cmd.unlockForcedDone`,{idShort:s}))},onCancel:()=>{t.tui.info.showToast(O.t(`cmd.titleSessionUnlock`),O.t(`cmd.unlockCancelled`))}});return}(o.mtimeAgoMs??0)<5e3&&t.tui.messages.pushMessage({role:`command_echo`,command:`/session unlock --force`,status:`warn`,summary:O.t(`cmd.unlockRecentReleaseHint`,{idShort:s})}),t.app.sessionManager.forceReleaseSessionWriteLease(a),t.tui.info.showToast(O.t(`cmd.titleSessionUnlock`),O.t(`cmd.unlockForcedDone`,{idShort:s}))}async function Cn(e,t){let n=t.state.session.id,r=await t.app.sessionManager.forkSession(n);if(!r){t.tui.info.showToast(O.t(`cmd.titleSessionFork`),O.t(`cmd.forkFailed`));return}let i=t.state.session;if(t.state.session.isBusy){let[e]=un(B(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 B(i.id,i.session.messages(),!1);t.callbacks.sessionUnsub?.(),t.state.session=r,t.state.interactive=new A(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(F(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=L(r);t.tui.messages.pushMessages(o),t.callbacks.restoreSwitchedSession(),t.tui.info.setTopView({session:r.id}),t.tui.info.showToast(O.t(`cmd.titleSessionFork`),O.t(`cmd.forkSuccess`,{idShort:r.id.slice(0,8)}))}async function wn(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 Tn(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=C(o,`trace`),d=[];for(let e of l){let t=C(u,`${encodeURIComponent(e.id)}.jsonl`);try{let n=await nt(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} | 预估回收: ${W(e)}`,i=[`会话 ID 大小 最后活跃 标题`,...d.map(e=>` ${e.session.id.slice(0,8)} ${W(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 rt(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 文件,回收 ${W(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 W(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 En(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??C(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 Dn(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`,O.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){z(i.id),t.tui.info.showToast(`session kill`,`Removed stale session ${i.id.slice(0,8)} from background.`);return}a.abort(),z(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 On(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(O.t(`cmd.titleSessionFork`),O.t(`cmd.forkFailed`));return}let a=`${r} (fork)`,o=(await t.tui.modal.openModal({kind:`input`,title:O.t(`cmd.forkNameTitle`),placeholder:a,defaultValue:a})??``).trim()||a;i.renameSession(o);let s=t.state.session;if(t.state.session.isBusy){let[e]=un(B(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 B(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 A(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(F(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=L(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(O.t(`cmd.titleSessionFork`),O.t(`cmd.forkSuccessNamed`,{title:o}))}async function kn(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=Te(r.metadata().title,r.messages(),n.id),u=t.callbacks.isWriteLeaseReadOnly(),d=[{kind:`row`,label:O.t(`cmd.statusRowTitle`),value:l},{kind:`row`,label:O.t(`cmd.statusRowSessionId`),value:n.id.slice(0,8)},{kind:`row`,label:O.t(`cmd.statusRowModel`),value:n.model?.id??O.t(`cmd.statusModelUnset`)},{kind:`row`,label:O.t(`cmd.statusRowMsgs`),value:String(i.length)},{kind:`row`,label:O.t(`cmd.statusRowOccupancy`),value:O.t(`cmd.statusValueOccupancy`,{occ:a.toLocaleString(),window:o?.toLocaleString()??`N/A`,seg:s===void 0?``:` (${s}%)`})},{kind:`row`,label:O.t(`cmd.statusRowCumOutput`),value:c.toLocaleString()},{kind:`row`,label:O.t(`cmd.statusRowWriteAccess`),value:u?O.t(`cmd.statusValueWriteLeaseReadOnly`):O.t(`cmd.statusValueWriteLeaseOk`),tone:u?`warning`:void 0}];t.callbacks.isRunPaused()&&d.push({kind:`blank`},{kind:`text`,value:O.t(`cmd.statusLineRunPaused`),tone:`warning`}),t.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleStatus`),lines:[],dataListEntries:d})}async function An(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=N({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 jn(){let e=process.env.OTTO_NOTIFY_COALESCE_WARN_RATIO,t=e?Number(e):NaN;return Number.isFinite(t)&&t>=1?t:1.5}function Mn(e,t){return t===0?`healthy`:e<jn()?`warning`:`healthy`}async function Nn(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:Mn(r,n.coalescedCalls)}});let i=t.app.activePlugins();try{let e=await he(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 Pn(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:lt(t,e.api)}}),i=r.some(e=>e.hitRatio!==null),a={inputTokens:n.totalInputTokens,outputTokens:0,cacheReadTokens:n.totalCacheReadTokens,cacheWriteTokens:n.totalCacheWriteTokens},o=i?lt(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 Fn(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 In(e){return new Date(e*1e3).toLocaleString()}async function Ln(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:O.t(`cmd.titleUsage`),lines:[O.t(`cmd.usageNotSubscription`)]});return}let r=t.callbacks.getLastProviderUsage();if(!r){t.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleUsage`),lines:[O.t(`cmd.usageNoSnapshotYet`)]});return}let i=[],a=n===`anthropic`;if(r.limitType&&i.push(O.t(`cmd.usageLineType`,{type:qe(r.limitType)})),(a||r.usedPercent!==void 0)&&i.push(O.t(`cmd.usageLineStatus`,{status:r.status})),r.usedPercent!==void 0&&i.push(O.t(`cmd.usageLinePercent`,{pct:Math.round(r.usedPercent)})),r.resetsAt!==void 0&&i.push(O.t(`cmd.usageLineResetsAt`,{when:In(r.resetsAt)})),r.standardLimits){let e=r.standardLimits;i.push(O.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(O.t(`cmd.usageSubPoolNotInHeaders`))),t.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleUsage`),lines:i})}function Rn(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 zn=e=>`把下面的笔记归纳成一个简短标题(≤6 词)和一句话描述。严格只按此格式输出:\nTITLE: <标题>\nDESC: <一句话描述>\n\n笔记:\n${e}`;function Bn(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 Vn(e,t,n=8e3){let r=Rn(e);if(!t)return r;let i=new AbortController,a=setTimeout(()=>i.abort(),n);a.unref?.();try{let n=Bn(await t(zn(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 Hn(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 Un(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=Rn(i);await r.record(e),o(`/memory user`,`ok`,O.t(`cmd.memoryUserSaved`,{name:e.name}));return}let a=r.getInjection().trim();t.tui.modal.openModal({kind:`memory`,projectIndex:``,userIndex:a,...Hn(n,r)});return}if(i===`project`){let e=n?n.getInjection().trim():``;t.tui.modal.openModal({kind:`memory`,projectIndex:e,userIndex:``,...Hn(n,r)});return}if(i===`forget`){let t=e.slice(1).join(` `).trim();if(!t){o(`/memory forget`,`warn`,O.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?O.t(`cmd.memoryDeleted`,{name:t}):O.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`,O.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,...Hn(n,r)})}async function Wn(e,t){let n=O.t(`cmd.titleCompact`);if((e[0]??``).toLowerCase()===`log`){t.tui.panes.togglePane(`compactionLog`);return}if(!t.app.storage.memory){t.tui.info.showToast(n,O.t(`compact.unavailable`));return}t.tui.info.showToast(n,O.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,O.t(`compact.edResult`,{before:e.before,after:e.after})),t.callbacks.onContextCompacted()):t.tui.info.showToast(n,O.t(`compact.noop`))}catch(e){t.tui.info.showToast(n,O.t(`cmd.compactFailed`,{msg:e instanceof Error?e.message:String(e)}))}finally{t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!1})}}const Gn=async(e,t)=>{let n=e[0];switch(n){case`memory-sync`:return Kn(e.slice(1),t);default:t.tui.info.showToast(`Workspace`,`/workspace ${n??``} — unknown subcommand. Use: memory-sync [status|enable|disable]`)}};async function Kn(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 qn(e,t){t.tui.info.showToast(O.t(`cmd.titleUpgrade`),O.t(`cmd.upgradeCheckScanning`));try{let e=Ee({workspaceDir:t.app.workspaceDir,workspaceRoot:xe(t.app.workspaceDir),scope:`all`});if(e.length===0){t.tui.info.showToast(O.t(`cmd.titleUpgrade`),O.t(`cmd.upgradeCheckNoVersioned`));return}let n=await me(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(O.t(`cmd.upgradeCheckLineUpdate`,{tag:t,name:e.name,installed:e.installed,latest:e.latest??``}))):r.push(O.t(`cmd.upgradeCheckLineLatest`,{tag:t,name:e.name,installed:e.installed}))}i>0&&(r.push(``),r.push(O.t(`cmd.upgradeCheckSummary`,{count:i}))),t.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleUpgradeCheck`),lines:r})}catch(e){t.tui.info.showToast(O.t(`cmd.titleUpgrade`),O.t(`cmd.upgradeCheckFailed`,{err:e instanceof Error?e.message:String(e)}))}}async function Jn(t,n){let r=n.state.session,i=r.model?.id??O.t(`cmd.aboutModelNotSet`),a=re().length,o=Math.round(oe()/(1024*1024*1024)),s=Math.round(y()/(1024*1024)),c=[{kind:`group`,title:O.t(`cmd.aboutGroupVersion`)},{kind:`row`,label:O.t(`cmd.aboutVersion`),value:`${Fe} (build ${Ne})`},{kind:`row`,label:O.t(`cmd.aboutBranch`),value:`dev`},{kind:`row`,label:O.t(`cmd.aboutCommit`),value:e},{kind:`group`,title:O.t(`cmd.aboutGroupRuntime`)},{kind:`row`,label:O.t(`cmd.aboutRuntime`),value:`Node.js ${process.version} · ${ie()} ${ne()} · ${ae()}`,tone:`muted`},{kind:`row`,label:O.t(`cmd.aboutCPU`),value:`${a} cores`,tone:`muted`},{kind:`row`,label:O.t(`cmd.aboutMemory`),value:`${o} GB total / ${Math.round(s)} MB free`,tone:`muted`},{kind:`row`,label:O.t(`cmd.aboutShell`),value:process.env.SHELL??`(unknown)`,tone:`muted`},{kind:`row`,label:O.t(`cmd.aboutTerminal`),value:process.env.TERM??`(unknown)`,tone:`muted`},{kind:`group`,title:O.t(`cmd.aboutGroupSession`)},{kind:`row`,label:O.t(`cmd.aboutModel`),value:i,tone:`secondary`}];r.id&&c.push({kind:`row`,label:O.t(`cmd.aboutSession`),value:r.id.slice(0,8)}),c.push({kind:`blank`},{kind:`text`,value:O.t(`cmd.aboutUpdateHint`),tone:`muted`}),n.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleAbout`),lines:[],dataListEntries:c})}async function G(e,t){return e.tui.modal.openModal({kind:`input`,...t})}function Yn(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 Xn(e,t){let n=t.app.feedbackRegistry.get();if(!n){t.tui.info.showToast(O.t(`cmd.titleFeedback`),O.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(O.t(`cmd.titleFeedback`),O.t(`cmd.feedbackRepoUnresolved`));return}let o=await G(t,{title:O.t(`cmd.feedbackStepTitle`)});if(!o||o.trim().length===0)return;let s=await G(t,{title:O.t(`cmd.feedbackStepRepro`)})??void 0,c=await G(t,{title:O.t(`cmd.feedbackStepExpected`)})??void 0,l=await G(t,{title:O.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 Yn(t,O.t(`cmd.feedbackConfirmTitle`),O.t(`cmd.feedbackConfirmMessage`,{title:d.title,bodyPreview:f})))return;if(t.tui.info.showToast(O.t(`cmd.titleFeedback`),O.t(`cmd.feedbackChannelSubmitting`)),n.submitIssueViaGh){let e=await n.submitIssueViaGh(d);if(e.ok){t.tui.info.showToast(O.t(`cmd.titleFeedback`),O.t(`cmd.feedbackCreated`,{url:e.url}));return}}let p=n.buildIssueUrl?.(d);if(!p){t.tui.info.showToast(O.t(`cmd.titleFeedback`),O.t(`cmd.feedbackUnavailable`));return}je(p),t.tui.info.showToast(O.t(`cmd.titleFeedback`),O.t(`cmd.feedbackCreated`,{url:p}))}function Zn(e,t,n){let r=we(e,t);if(r)return r;let i=e.split(`/`).pop();if(i)return ve({cwd:t??process.cwd(),homedir:n??b()}).find(e=>e.id===i)?.dir}function Qn(e,t,n){try{let r=Zn(e,t,n);if(!r)return;let i=C(r,pe),a=Se(ze(i,`utf-8`),i);return a?a.codeProviderIds?.[0]??a.contributes?.providers?.[0]?.id??a.contributes?.oauth?.[0]?.id:void 0}catch{return}}function $n(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 er={provider:`install-provider`,authentication:`connect-provider`,model:`choose-model`,ready:`send-first-prompt`,"first-prompt":`none`};function tr(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||!(e.selectedModelUsableInMainSession??t.includes(n))?`model`:e.firstPromptSubmitted?`first-prompt`:`ready`}function nr(e){let t=tr(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:er[t],stage:t,autoOpen:o}}}function rr(e){return e.stage===`ready`||e.stage===`first-prompt`}function ir(e,t){return e.get(t)===!0}function ar(e){return{personalizationSeen:ir(e,`has_completed_onboarding`),dismissed:ir(e,`has_completed_wizard`)||ir(e,`wizard_dont_show_again`),firstPromptSubmitted:typeof e.get(`first_prompt_submitted_at`)==`number`}}const or=`__otto_setup__`;async function sr(e){let t=ar(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!==or),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(),s=o!==void 0&&o!==or?i.find(e=>e.id===o):void 0,c=s&&e.isModelUsableInMainSession?await e.isModelUsableInMainSession({provider:s.provider,api:s.api}).then(({usable:e})=>e).catch(()=>!1):void 0;return nr({providerInstalled:e.hasProviderPlugin(),...e.providerCandidates?{providerCandidates:e.providerCandidates}:{},connectedProviderIds:r,usableModelIds:a,...o!==void 0&&o!==or?{selectedModelId:o}:{},...c===void 0?{}:{selectedModelUsableInMainSession:c},firstPromptSubmitted:t.firstPromptSubmitted,dismissed:t.dismissed})}function cr(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 lr=class{snapshot=null;listeners=new Set;constructor(e){this.deps=e}current(){return this.snapshot}async refresh(){let e=await sr(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 ur(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 dr(e,t){return e.map((e,n)=>({provider:e,index:n,rank:ur(e,t)})).sort((e,t)=>e.rank-t.rank||e.index-t.index).map(e=>e.provider)}function fr(e){try{let{createRequire:t}=ht(`node:module`),{readFileSync:n}=ht(`node:fs`),{dirname:r,join:i}=ht(`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 pr(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=mr(t);return t.map(e=>({...e,recommended:e.usable&&e.id===n}))}function mr(e){return e.find(e=>e.usable)?.id}const hr={hasReadme:!1,hasPackageManifest:!1,hasTestConfig:!1,isEmpty:!1},gr=new Set([`node_modules`,`.git`,`.hg`,`.svn`,`.venv`,`venv`,`__pycache__`,`.pytest_cache`,`.mypy_cache`,`.tox`,`dist`,`build`,`.next`,`.nuxt`,`.cache`,`.DS_Store`]),_r=/^readme(\.(md|markdown|txt|rst))?$/i,vr=new Set([`package.json`,`pyproject.toml`,`setup.py`,`requirements.txt`,`Cargo.toml`,`go.mod`,`Gemfile`,`composer.json`,`pom.xml`,`build.gradle`,`build.gradle.kts`,`Package.swift`]),yr=/^(jest\.config|vitest\.config|karma\.conf|\.mocharc)(\.(js|ts|mjs|cjs|json))?$/i,br=new Set([`pytest.ini`,`tox.ini`,`phpunit.xml`,`phpunit.xml.dist`,`setup.cfg`]);async function xr(e,t){let n;try{n=await t.readdir(e)}catch{return hr}let r=n.filter(e=>!gr.has(e.name)),i=r.length===0,a=!1,o=!1,s=!1,c=0;for(let e of r)if(c>=2e3||(c++,e.isFile()&&(!a&&_r.test(e.name)&&(a=!0),!o&&vr.has(e.name)&&(o=!0),!s&&(br.has(e.name)||yr.test(e.name))&&(s=!0),a&&o&&s)))break;return{hasReadme:a,hasPackageManifest:o,hasTestConfig:s,isEmpty:i}}function Sr(e){if(e.isEmpty)return[`suggestion.emptyProject`];let t=[];return e.hasReadme&&t.push(`suggestion.hasReadme`),e.hasPackageManifest&&t.push(`suggestion.hasPackageManifest`),e.hasTestConfig&&t.push(`suggestion.hasTestConfig`),t.length>0?t:[`suggestion.unrecognized`]}const Cr=`oxygen-provider`,wr=new Set([`plugin-oxygen`,Cr]);async function Tr(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=>wr.has(e.id)||e.source===`@x-otto/plugin-oxygen`||e.source.includes(`/plugin-oxygen`)||e.subPath?.endsWith(`plugin-oxygen`)))}catch{return!1}}async function Er(e){let t=e.tui,n=e.app,r=await sr(cr({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>e.state.session?.model?.id,isModelUsable:k(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 Tr(e),l=Object.entries(o).filter(([e,t])=>t.capabilities.includes(`provider`)&&(e!==Cr||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=dr(l.map(([e,t])=>({id:e,...fr(t.pkg)})),process.env).map(({id:e})=>({label:e,value:e,detail:u[e]??o[e]?.pkg??e})),f=e=>$n(e,n.authStore.oauth,{oauth:{label:O.t(`setup.loginOAuth`),detail:`Open browser, complete authorization — no copy-paste needed.`},apiKey:{label:O.t(`setup.loginApiKey`),detail:`Generate a key on your provider dashboard and paste it here.`}}),p=async()=>{let t=await sr(cr({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>e.state.session?.model?.id,isModelUsable:k(n.authStore)})),r=k(n.authStore),i=new Set(t.model.usableIds),a=n.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`);return pr((await Promise.all(a.map(async e=>{let t=i.has(e.id);return t?{model:e,usable:t,reason:void 0}:{model:e,usable:!1,reason:(await r({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}:{}}))},m=await p(),h=i.length===1?i[0]:void 0,g=Sr(await xr(n.workspaceDir,{readdir:e=>tt(e,{withFileTypes:!0})})).map(e=>O.t(e));t.modal.openModal({kind:`wizard`,title:O.t(`setup.title`),welcomeTitle:O.t(`setup.welcomeTitle`),welcomeGreeting:``,welcomeDescription:O.t(`setup.welcomeDescription`),welcomeDontShowAgainLabel:O.t(`setup.welcomeDontShowAgain`),welcomeStartLabel:O.t(`setup.welcomeStart`),welcomeCancelLabel:O.t(`setup.welcomeCancel`),stepNames:[O.t(`setup.stepNameProvider`),O.t(`setup.stepNameLogin`),O.t(`setup.stepNameModel`),O.t(`setup.stepNameStart`)],stepSubtitles:[O.t(`setup.step1Subtitle`),O.t(`setup.step3Subtitle`),O.t(`setup.step4Subtitle`),O.t(`setup.step5Done`)],initialCompleted:a,initialCurrent:s,providerOptions:d,providerAuthOptions:f,authProviderName:h,modelOptions:m,onRefreshModelOptions:p,examplePrompts:g,workspacePath:n.workspaceDir,async onInstallProvider(t,n){n(`Resolving package…`);try{let{runPluginInstall:r}=await import(`./extension-plugin-fPDz7XlG.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:O.t(`setup.installFailed`,{reason:t})};let c=[];try{let{readHighRiskCapabilities:e}=await import(`@x-otto/coding`),t=Zn(s);t&&(c=e(t))}catch{}return{ok:!0,providerId:Qn(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 Dr(e,t){await Er(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 Or(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 kr(e,t){Or(e,`model`,t)}function Ar(e,t){Or(e,`effort`,t)}function jr(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 Mr(e,t){K(e,`retry.cancelled`,{attempt:t.attempt})}function Nr(e){K(e,`retry.reset`,{})}function Pr(e,t,n){K(e,`pause.${t}`,{...n===void 0?{}:{source:n}})}const Fr=(e,t,n)=>{let r=P(n),i=r?`${e}·${r}`:e;return t?`${i} (${t>=1e6?`${(t/1e6).toFixed(1)}M`:`${Math.round(t/1e3)}K`})`:i},q=[`low`,`medium`,`high`,`xhigh`,`max`];function Ir(e,t){return[t,...e.filter(e=>e!==t)].slice(0,5)}function Lr(e){let t=/\[@model:((?:\\\]|[^\]])+)\]/g,n=[];return{text:e.replace(t,(e,t)=>(n.push(t.replace(/\\\]/g,`]`)),``)).replace(/\n{3,}/g,`
|
|
9
|
+
|
|
10
|
+
`).trim(),modelIds:n}}async function Rr(e,t){let n=Lr(e),r=n.modelIds.at(-1);if(r&&r!==t.currentModelId){let e=await t.applyModel(r);e.includes(`not in registry`)&&t.onSwitchFailed?.(e)}return n.text}function zr(e){let t=/\[@effort:((?:\\\]|[^\]])+)\]/g,n=[];return{text:e.replace(t,(e,t)=>(n.push(t.replace(/\\\]/g,`]`)),``)).replace(/\n{3,}/g,`
|
|
11
|
+
|
|
12
|
+
`).trim(),levels:n}}function Br(e,t){let n=zr(e),r=n.levels.at(-1);return r&&(q.includes(r)?r!==t.currentEffort&&t.applyEffort(r):t.onInvalidLevel?.(r)),n.text}function Vr(e){let{modelReady:t,currentModelId:n,contextWindow:r,tuiRef:i,pushBudgetNow:a,app:o,getSession:s,options:c,fmtDisplayModel:l,onEngineModelAction:u}=e;return async(e,d)=>{let f=s(),p=f.model?.id;c.value&&(c.value.model=e),n.value=e;let m=o.modelRegistry.find(e);if(m&&m.id===`__otto_setup__`)return`Model "${e}" is a setup placeholder — pick a real model with /model first.`;if(d?.persist!==!1)try{let t={model:e},n=o.settings.get(`model_slots`);n&&(t.model_slots={...n,default:e}),m&&(t.recent_models=Ir(o.settings.get(`recent_models`)??[],e)),await o.settings.persist(t)}catch{}if(m){if(f.model=m,t.value=!0,e!==p&&(o.syncSessionToolsFor(f.id),kr({tui:i.value??{messages:{pushMessage:()=>{}}},session:f,traceStore:o.storage.traceStore},{from:p,to:m.id,label:Fr(m.id,m.contextWindow,f.thinkingLevel)})),m.api.includes(`:`)&&o.firePluginActivationEvent?.(`onProvider:${m.api}`),u?.({kind:`setModel`,modelId:e}),i.value?.stores.tasks.setModelName(Fr(m.id,m.contextWindow,f.thinkingLevel)),i.value?.engine.pushEngineEvent({kind:`maxOutputTokens`,n:m.maxOutputTokens}),o.authStore?.getAuthSource?o.authStore.getAuthSource(m.provider).then(e=>{e!==`oauth`&&i.value?.stores.notification.setProviderUsage(null)}).catch(()=>{i.value?.stores.notification.setProviderUsage(null)}):i.value?.stores.notification.setProviderUsage(null),e!==p&&o.storage.memory?.reconfigure){o.storage.memory.reconfigure({contextWindow:m.contextWindow,maxOutput:m.maxOutputTokens});try{let e=f.session.buildContext(),t=await o.storage.memory.ensureFitsWindow?.(e.messages,f.id);if(t?.compacted&&t.summary&&t.replacement){f.session.recordCompaction(t.summary,t.replacement),u?.({kind:`recordCompaction`,summary:t.summary,replacement:t.replacement});let e=m.contextWindow>=1e6?`${(m.contextWindow/1e6).toFixed(1)}M`:`${Math.round(m.contextWindow/1e3)}k`;i.value?.info.showToast(O.t(`cmd.titleModel`),O.t(`cmd.modelCompactedFor`,{window:e}))}}catch(e){console.error(`\x1b[3m\x1b[2m[model-switch] compaction skipped: ${e instanceof Error?e.message:String(e)}\x1b[0m`)}}return r.value=m.contextWindow,a.value?.(),e!==p&&!d?.silent&&i.value?.info.showToast(O.t(`cmd.titleModel`),O.t(`model.switchedTo`,{label:l(e)})),`Model → ${e} (active next turn).`}return f.model&&(i.value?.stores.tasks.setModelName(Fr(f.model.id,f.model.contextWindow,f.thinkingLevel)),i.value?.engine.pushEngineEvent({kind:`maxOutputTokens`,n:f.model.maxOutputTokens})),`Model "${e}" not in registry — switch NOT applied (still ${f.model?.id??`unset`}). Check the id or /auth the provider.`}}function Hr(e){let{getSession:t,app:n,tuiRef:r,options:i,fmtDisplayModel:a,applyModel:o}=e,s=!1,c=k(n.authStore,`delegation`),l=k(n.authStore,`main-session`);return async()=>{if(s)return;s=!0;let u=t().model;if(!u)return;let d=async e=>{try{return(await c(e)).usable}catch{return!1}},f=async e=>{try{return(await l(e)).usable}catch{return!1}},p=i.value?.model??n.settings.get(`model`);if(typeof p!=`string`||!p)return;let m=n.modelRegistry.find(p);if(m&&await f(m)){m.id!==u.id&&await o(m.id);return}let h=m?O.t(`model.reasonUnauthenticated`,{provider:m.provider}):O.t(`model.reasonNotFound`),g=u;if(!await f(u)){let e=n.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`),t;for(let n of e)if(await d(n)){t=n;break}t??=e[0],t&&(g=t)}let _=g.id;r.value?.modal.openModal({kind:`confirm`,title:O.t(`model.title`),message:[`${a(p)} → ${a(g.id)}`,``,h,``,O.t(`model.hint`)],confirmLabel:O.t(`model.permanent`),extraLabel:O.t(`model.login`),cancelLabel:O.t(`model.dismiss`),onConfirm:()=>{o(_,{persist:!0})},onExtra:()=>{e.onLogin&&m?.provider?e.onLogin(m.provider):r.value?.info.showToast(O.t(`model.login`),O.t(`model.fallbackLoginToast`,{provider:m?.provider??``}))},onCancel:()=>{e.onExitSession?.()}})}}const Ur={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 Wr(e){let t=Math.round(e*8);return`━`.repeat(Math.max(0,t))+`╌`.repeat(Math.max(0,8-t))}async function Gr(e,t){let n=e[0]?.toLowerCase();if(n&&q.includes(n)){Kr(t,n);return}if(n){t.tui.info.showToast(O.t(`cmd.titleEffort`),O.t(`cmd.effortUnknown`,{arg:n,levels:q.join(` / `)}));return}let r=t.state.session.thinkingLevel;t.tui.modal.openModal({kind:`select`,title:O.t(`cmd.selectEffortTitle`),options:q.map(e=>{let t=Ur[e],n=e===r,i=Wr(t.intensity);return{label:t.label,value:e,detail:`${i} ${t.desc}${n?` · 当前`:``}`}}),onSelect:e=>Kr(t,e),onCancel:()=>{}})}function Kr(e,t){let n=e.state.session,r=n.thinkingLevel;n.thinkingLevel=t,e.app.settings.persist({thinking_level:t}),r!==t&&Ar({tui:e.tui,session:n,traceStore:e.app.storage.traceStore},{from:r,to:t,label:P(t)}),n.model?.id&&e.tui.stores.tasks.setModelName(F(e.app,n.model.id,t)),e.tui.info.showToast(O.t(`cmd.titleEffort`),t)}async function qr(e,t){let n=e[0]?.toLowerCase();if(n===`general`||n===`gen`){Y(t);return}if(n===`lang`||n===`language`){ii(e.slice(1),t);return}if(n===`theme`){ai(e.slice(1),t);return}if(n){t.tui.info.showToast(O.t(`cmd.titlePreference`),O.t(`cmd.preferenceUsage`));return}J(t)}function J(e,t){let n=e.app.settings,r=n.get(`language`),i=r===`zh`?`中文 (zh)`:r===`en`?`English (en)`:`Auto`,a=e.state.themeRegistry??Ue(),o=n.get(`theme_preset`)??{},s=a.get(o.dark??`dark`)?.label??o.dark??`dark`;e.tui.modal.openModal({kind:`select`,title:O.t(`cmd.titlePreference`),detailPlacement:`inline`,options:[{label:O.t(`cmd.prefOptionGeneral`),value:`general`,detail:O.t(`cmd.prefDescGeneral`)},{label:O.t(`cmd.prefOptionLang`),trailingLabel:i,value:`lang`,detail:O.t(`cmd.prefDescLang`)},{label:O.t(`cmd.prefOptionTheme`),trailingLabel:s,value:`theme`,detail:O.t(`cmd.prefDescTheme`)}],defaultSelectedValue:t,onSelect:t=>{t===`general`?Y(e):t===`lang`?ii([],e):t===`theme`&&ai([],e)},onCancel:()=>{}})}let Jr;function Y(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===fe),f={on:D.toggleOn,off:D.toggleOff},p={on:O.t(`cmd.toggleOn`),off:O.t(`cmd.toggleOff`)},m=e=>zt(e,f,p);e.tui.modal.openModal({kind:`select`,title:O.t(`cmd.selectGeneralTitle`),detailPlacement:`inline`,subtitle:t,replace:r,options:[{label:O.t(`cmd.genNickname`),trailingLabel:o||`—`,value:`nickname`,detail:O.t(`cmd.genNicknameDesc`)},{label:O.t(`cmd.genCompletionNotice`),trailingLabel:m(s),value:`completion`,detail:O.t(`cmd.genCompletionNoticeDesc`)},{label:O.t(`cmd.genSound`),trailingLabel:m(c),value:`sound`,detail:O.t(`cmd.genSoundDesc`)},{label:O.t(`cmd.genUpdateCheck`),trailingLabel:m(l),value:`updateCheck`,detail:O.t(`cmd.genUpdateCheckDesc`)},{label:O.t(`cmd.genSkillLoop`),trailingLabel:d?m(u):O.t(`cmd.genSkillLoopMissing`),value:`skillLoopPanel`,detail:O.t(`cmd.genSkillLoopEntryDesc`)}],defaultSelectedValue:n??Jr,onHighlight:e=>{Jr=e},onSelect:t=>{if(t===`nickname`){Yr(e);return}if(t===`skillLoopPanel`){X(e);return}ri(e,t)},onCancel:()=>{J(e,`general`)}})}async function Yr(e){let t=await e.tui.modal.openModal({kind:`input`,title:O.t(`cmd.genNicknameInputTitle`),placeholder:O.t(`cmd.genNicknamePlaceholder`)});if(t==null){Y(e);return}let n=t.trim();await e.app.settings.persist({nickname:n}),Y(e,O.t(`cmd.genSaved`))}const Xr=[4,6,12,20];function Zr(e){let t=typeof e==`number`?e:6,n=Xr.includes(t)?`genSkillLoopThr${t}`:``;return n?O.t(`cmd.${n}`):String(t)}function Qr(e){let t=e.app.settings,n=t.get(`skill_loop`)?.min_messages??6;e.tui.modal.openModal({kind:`select`,title:O.t(`cmd.genSkillLoopThresholdTitle`),detailPlacement:`inline`,options:Xr.map(e=>({label:O.t(`cmd.genSkillLoopThr${e}`),value:String(e),detail:O.t(`cmd.genSkillLoopThr${e}Desc`),trailingLabel:e===n?D.toggleOn:void 0})),onSelect:n=>{(async()=>{let r={...t.get(`skill_loop`)??{}};r.min_messages=Number(n),await t.persist({skill_loop:r}),X(e,O.t(`cmd.genSaved`),`threshold`)})()},onCancel:()=>{X(e,void 0,`threshold`)}})}const $r=[3,14,30,365];function ei(e){let t=typeof e==`number`?e:14;return $r.includes(t)?O.t(`cmd.genSkillLoopCd${t}`):O.t(`cmd.genSkillLoopCdDays`,{n:t})}function ti(e){let t=e.app.settings,n=t.get(`skill_loop`)?.dismiss_cooldown_days??14;e.tui.modal.openModal({kind:`select`,title:O.t(`cmd.genSkillLoopCooldownTitle`),detailPlacement:`inline`,options:$r.map(e=>({label:O.t(`cmd.genSkillLoopCd${e}`),value:String(e),detail:O.t(`cmd.genSkillLoopCd${e}Desc`),trailingLabel:e===n?D.toggleOn:void 0})),onSelect:n=>{(async()=>{let r={...t.get(`skill_loop`)??{}};r.dismiss_cooldown_days=Number(n),await t.persist({skill_loop:r}),X(e,O.t(`cmd.genSaved`),`cooldown`)})()},onCancel:()=>{X(e,void 0,`cooldown`)}})}function X(e,t,n){let r=e.app.settings,i=r.get(`skill_loop`)?.enabled===!0,a=e.app.activePlugins().some(e=>e.id===fe),o={on:D.toggleOn,off:D.toggleOff},s={on:O.t(`cmd.toggleOn`),off:O.t(`cmd.toggleOff`)};if(!a){e.tui.modal.openModal({kind:`select`,title:O.t(`cmd.skillLoopPanelTitle`),detailPlacement:`inline`,subtitle:O.t(`cmd.genSkillLoopMissingHint`),options:[{label:O.t(`cmd.genSkillLoopMissing`),value:`noop`,detail:``}],onSelect:()=>{Y(e,void 0,`skillLoopPanel`)},onCancel:()=>{Y(e,void 0,`skillLoopPanel`)}});return}e.tui.modal.openModal({kind:`select`,title:O.t(`cmd.skillLoopPanelTitle`),detailPlacement:`inline`,subtitle:t,defaultSelectedValue:n,options:[{label:O.t(`cmd.skillLoopOnOff`),trailingLabel:zt(i,o,s),value:`toggle`,detail:O.t(`cmd.genSkillLoopEntryDesc`)},...i?[{label:O.t(`cmd.genSkillLoopThreshold`),trailingLabel:Zr(r.get(`skill_loop`)?.min_messages),value:`threshold`,detail:O.t(`cmd.genSkillLoopThresholdDesc`)},{label:O.t(`cmd.genSkillLoopCooldown`),trailingLabel:ei(r.get(`skill_loop`)?.dismiss_cooldown_days),value:`cooldown`,detail:O.t(`cmd.genSkillLoopCooldownDesc`)},{label:O.t(`cmd.genSkillLoopStatus`),value:`status`,detail:O.t(`cmd.genSkillLoopStatusDesc`)}]:[]],onSelect:t=>{if(t===`threshold`){Qr(e);return}if(t===`cooldown`){ti(e);return}if(t===`status`){ni(e);return}(async()=>{let t={...r.get(`skill_loop`)??{}},n=t.enabled!==!0;t.enabled=n,await r.persist({skill_loop:t}),X(e,n?O.t(`cmd.genSkillLoopOn`):O.t(`cmd.genSkillLoopOff`),`toggle`)})()},onCancel:()=>{Y(e,void 0,`skillLoopPanel`)}})}function ni(e){let t=e.app.settings,n=e.app.activePlugins().some(e=>e.id===fe),r=Ce({workspaceKey:e.app.workspaceRef?.key??de,now:Date.now(),cooldownDays:t.get(`skill_loop`)?.dismiss_cooldown_days,pluginInstalled:n}),i=e=>O.t(`cmd.skillLoopStatusCount`,{n:e}),a=[];if(!n)a.push({label:O.t(`cmd.skillLoopStatusNotInstalled`),value:`noop`,detail:O.t(`cmd.genSkillLoopMissingHint`)});else{a.push({label:O.t(`cmd.skillLoopStatusEpisodes`),trailingLabel:i(r.episodeCount),value:`noop`,detail:O.t(`cmd.skillLoopStatusSuccess`)+` `+i(r.successCount)},{label:O.t(`cmd.skillLoopStatusPending`),trailingLabel:i(r.pendingCount),value:`noop`,detail:i(r.candidateCount)+` `+O.t(`cmd.skillLoopStatusCandidates`)+` · `+i(r.coolingCount)+` `+O.t(`cmd.skillLoopStatusCooling`)});for(let e of r.pending)a.push({label:e.taskSignature,trailingLabel:O.t(`cmd.skillLoopStatusTimes`,{n:e.size}),value:`noop`,detail:O.t(`cmd.skillLoopStatusGroupPending`)});for(let e of r.recentSignatures)a.push({label:e,value:`noop`,detail:O.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:O.t(`cmd.skillLoopStatusTitle`),detailPlacement:`inline`,subtitle:o?O.t(o):void 0,options:a,onSelect:()=>{X(e,void 0,`status`)},onCancel:()=>{X(e,void 0,`status`)}})}async function ri(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}),Y(e,O.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}),Y(e,O.t(`cmd.genSaved`),t,!0)}function ii(e,t){let n=e[0]?.toLowerCase();if(n===`en`||n===`zh`||n===`auto`){ci(t,n);return}if(n){t.tui.info.showToast(O.t(`cmd.titlePreference`),O.t(`pref.languageUsage`));return}t.tui.modal.openModal({kind:`select`,title:O.t(`cmd.selectLanguageTitle`),detailPlacement:`inline`,options:[{label:`中文 (zh)`,value:`zh`,detail:O.t(`cmd.langDescZh`)},{label:`English (en)`,value:`en`,detail:O.t(`cmd.langDescEn`)},{label:`Auto`,value:`auto`,detail:O.t(`cmd.langDescAuto`)}],onSelect:e=>ci(t,e),onCancel:()=>{J(t,`lang`)}})}function ai(e,t){oi(t)}function oi(e){let t=e.state.themeRegistry??Ue(),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:O.t(`cmd.prefOptionTheme`),detailPlacement:`inline`,options:[{label:O.t(`cmd.themeDarkPresetOption`),value:`preset-dark`,detail:O.t(`cmd.themeDarkPresetDesc`),trailingLabel:r?.label},{label:O.t(`cmd.themeLightPresetOption`),value:`preset-light`,detail:O.t(`cmd.themeLightPresetDesc`),trailingLabel:i?.label}],onSelect:t=>{if(t===`preset-dark`){si(e,`dark`);return}if(t===`preset-light`){si(e,`light`);return}},onCancel:()=>{J(e,`theme`)}})}function si(e,t){let n=e.state.themeRegistry??Ue(),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`?O.t(`cmd.themePresetBuiltin`):O.t(`cmd.themePresetFromExtension`,{id:e.source.extensionId}),trailingLabel:e.id===i?`✓`:void 0})),{label:O.t(`cmd.themePresetReset`),value:`__reset__`,detail:O.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`?O.t(`cmd.themePresetTitleDark`):O.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(O.t(`cmd.titlePreference`),O.t(`cmd.themePresetSaved`,{label:s??a??t}))},onCancel:()=>{s(),e.tui.info.showToast(O.t(`cmd.titlePreference`),O.t(`cmd.selectCancelled`))}})}function ci(e,t){e.state.currentLang=e.tui.lifecycle.setLanguage(t),Ct(t),e.tui.plugins.setCommands(e.callbacks.refreshSlashCommands()),e.app.settings.persist({language:t}),e.tui.info.showToast(O.t(`cmd.titleLanguage`),O.t(`pref.languageSwitched`,{l:e.state.currentLang,name:e.state.currentLang===`zh`?`中文`:`English`}))}async function li(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(O.t(`cmd.titlePlugin`),O.t(`cmd.pluginUsage`,{seg:(i?`untrust`:`trust`)==`untrust`?`untrust `:``}));return}let o=n({cwd:r,homedir:b()}).find(e=>e.id===a);if(!o){t.tui.info.showToast(O.t(`cmd.titlePlugin`),O.t(`cmd.pluginNotFound`,{id:a}));return}if(i){try{Oe(o.dir)}catch(e){t.tui.info.showToast(O.t(`cmd.titlePlugin`),`撤销信任失败,权限未收回:${e instanceof Error?e.message:String(e)}`);return}t.tui.info.showToast(O.t(`cmd.titlePlugin`),O.t(`cmd.pluginUntrusted`,{id:a}))}else u(t,o);return}if(i===`trust`){De(r),t.tui.info.showToast(O.t(`cmd.titleCompat`),O.t(`cmd.compatTrusting`)),t.app.reloadCapabilities().then(e=>{t.tui.plugins.setPluginRegistrations(t.app.getPluginRegistrations()),t.tui.info.showToast(O.t(`cmd.titleCompat`),O.t(`cmd.compatTrusted`,{count:e.mcpTools}))},e=>t.tui.info.showToast(O.t(`cmd.titleCompat`),O.t(`cmd.compatReloadFailed`,{err:e instanceof Error?e.message:String(e)})));return}if(i===`untrust`){ke(r),t.tui.info.showToast(O.t(`cmd.titleCompat`),O.t(`cmd.compatUntrusted`));return}let a=ye(r),o=ge(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?O.t(`cmd.compatTrustedLabel`):O.t(`cmd.compatUntrustedLabel`);s.push(`${e.join(O.t(`cmd.listSep`))} ${t}`)}if(o.highRiskKeys.length>0){let e=o.highRiskKeys.join(O.t(`cmd.listSep`));s.push(o.gated?O.t(`cmd.compatConfigGated`,{keys:e}):O.t(`cmd.compatConfigActive`,{keys:e}))}let c=n({cwd:r,homedir:b()}).filter(e=>e.scope===`project`||e.scope===`repository`);for(let e of c){let t=be(e);if(!t.surface.any)continue;let n=t.gated?O.t(`cmd.compatUntrustedLabel`):O.t(`cmd.compatTrustedLabel`);s.push(`plugin:${e.id} ${n}${t.gated?` → /trust plugin ${e.id}`:``}`)}if(s.length===0){t.tui.info.showToast(O.t(`cmd.titleCompat`),O.t(`cmd.compatNone`));return}o.gated?t.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleCompat`),lines:s}):t.tui.info.showToast(O.t(`cmd.titleCompat`),s.join(`
|
|
13
|
+
`))}async function ui(e,t){let n=e[0];if(n===`clear`){t.app.clearSessionAlwaysAllow(t.state.session.id),t.tui.info.showToast(O.t(`cmd.titlePermissions`),O.t(`cmd.permsCleared`));return}if(n===`add`||n===`remove`){let r=e.slice(1).join(` `).trim();if(!r){t.tui.info.showToast(O.t(`cmd.titlePermissions`),O.t(`cmd.permsManageHint`));return}if(n===`add`){if(!t.app.isWellFormedAllowEntry(r)){t.tui.info.showToast(O.t(`cmd.titlePermissions`),O.t(`cmd.permsInvalidEntry`,{entry:r}));return}await t.app.allowToolAlways(r),t.tui.info.showToast(O.t(`cmd.titlePermissions`),O.t(`cmd.permsAdded`,{entry:r}))}else{let e=await t.app.disallowToolAlways(r);t.tui.info.showToast(O.t(`cmd.titlePermissions`),e?O.t(`cmd.permsRemoved`,{entry:r}):O.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(`, `):O.t(`cmd.permsEmpty`)}`;t.tui.modal.openModal({kind:`permissions`,lines:[a(O.t(`cmd.permsSessionLabel`),r),a(O.t(`cmd.permsProjectLabel`),i),``,O.t(`cmd.permsClearHint`),O.t(`cmd.permsManageHint`)]})}async function di(e,n){let r=t();n.tui.info.showToast(O.t(`cmd.titleUpgrade`),O.t(`cmd.upgradeChecking`,{current:r}));let i=await wt(r);if(!i){n.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleUpgrade`),lines:[O.t(`cmd.upgradeNoNetwork`)]});return}if(!i.newer){n.tui.info.showToast(O.t(`cmd.titleUpgrade`),O.t(`cmd.upgradeLatest`,{current:r}));return}n.tui.modal.openModal({kind:`info`,title:O.t(`cmd.titleUpgrade`),lines:O.t(`cmd.upgradeAvailableLines`,{returnObjects:!0,current:r,latest:i.latest})})}async function fi(e,t){if(!e.includes(`--force`))return!1;t.tui.info.showToast(O.t(`cmd.titleUpgrade`),O.t(`cmd.upgrading`));let{ok:n,error:r}=await Dt();return n?(t.state.restartRequested=!0,t.tui.lifecycle.stop(),!0):(t.tui.info.showToast(O.t(`cmd.titleUpgrade`),O.t(`cmd.upgradeFailed`,{err:r??O.t(`cmd.unknownError`)})),!0)}async function pi(e,t,n){let r=O.t(`cmdDesc`,{returnObjects:!0}),i={session:O.t(`cmd.helpGroupSession`),model:O.t(`cmd.helpGroupModel`),agent:O.t(`cmd.helpGroupAgent`),debug:O.t(`cmd.helpGroupDebug`),ui:O.t(`cmd.helpGroupUi`),other:O.t(`cmd.helpGroupOther`)},a=[];for(let e of ra){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=`${O.t(`cmd.helpPrefixes`)} !<cmd> ${O.t(`cmd.helpPrefixShell`)} · @<file> ${O.t(`cmd.helpPrefixFile`)}`;t.tui.modal.openModal({kind:`select`,title:O.t(`cmd.titleCommands`),subtitle:o,searchable:!0,options:a,onSelect:e=>{sa(e,[],t)},onCancel:()=>{}})}async function mi(e,t){t.tui.panes.togglePane(`history`)}async function hi(e,t){t.tui.panes.togglePane(`notifications`)}async function gi(e,t){t.tui.panes.togglePane(`prompts`)}async function _i(e,t){t.tui.panes.setServices(!0)}let vi;function yi(e){vi=e}const bi=async(e,t)=>{let n=vi;if(!n){t.tui.info.showToast(`Schedule`,`Schedule system not available`);return}let r=e[0];switch(r){case void 0:return xi(t);case`list`:return Si(n,t);case`add`:return Ci(e.slice(1),n,t);case`remove`:return wi(e[1],n,t);case`run`:return Ti(e[1],n,t);case`enable`:return Di(e[1],!0,n,t);case`disable`:return Di(e[1],!1,n,t);case`logs`:return Oi(e[1],t);case`cancel`:return Ei(e[1],t);default:t.tui.info.showToast(`Schedule`,`/schedule ${r} — unknown subcommand. Use: add|list|remove|run|enable|disable|cancel|logs`)}};async function xi(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 Si(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(`
|
|
14
|
+
`)}),t.tui.panes.togglePane?.(`schedulePane`)}async function Ci(e,t,n){if(e.length<2){n.tui.info.showToast(`Schedule`,`/schedule add [--once] [--session] <cron> <prompt>`);return}let r=!1,i,a=[...e],o=a.indexOf(`--once`);o!==-1&&(r=!0,a.splice(o,1));let s=a.indexOf(`--session`);if(s!==-1&&(i=`session`,a.splice(s,1)),a.length<2){n.tui.info.showToast(`Schedule`,`Opening schedule panel in create mode`),xi(n);return}let c=a[0],l=a.slice(1).join(` `);try{let e=t.add({name:l.slice(0,40),prompt:l,cronExpression:c,recurring:!r,origin:`user`,target:i}),a=r?`one-shot`:`recurring`,o=new Date(e.nextFireAt).toLocaleString(),s=e.target===`session`?` [fires into this conversation]`:``;n.tui.info.showToast(`Schedule`,`${e.id}: ${e.name} (${a})${s} next: ${o}`)}catch(e){n.tui.info.showToast(`Schedule`,`Failed: ${e instanceof Error?e.message:String(e)}`)}}async function wi(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 Ti(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 Ei(e,t){let n=vi;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 Di(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 Oi(e,t){let n=w(Pe,`schedule-logs`),r;try{r=Ve(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=ze(w(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(`
|
|
15
|
+
`)})}function Z(e){return Qt(e.state.session.session.getDrafts()??[])}function ki(e,t){e.state.session.session.setDrafts(t),e.app.sessionManager.save(e.state.session.id).catch(()=>{}),e.tui.stores.tasks.setDrafts(Z(e))}const Ai=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return ji(e.slice(1),t);case`save`:return Mi(e.slice(1),t);case`load`:return Ni(e.slice(1),t);case`delete`:case`remove`:return Pi(e.slice(1),t);default:t.tui.info.showToast(`Draft`,`/draft ${n} — unknown subcommand. Use: save|list|load|delete`)}};async function ji(e,t){let n=Z(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=Z(t),c=en(a,o,s),l=tn([...s,c]);try{ki(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 Ni(e,t){let n=e.join(` `);if(!n){t.tui.info.showToast(`Draft`,`/draft load <name>`);return}let r=Z(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 Pi(e,t){let n=e.join(` `);if(!n){t.tui.info.showToast(`Draft`,`/draft delete <name>`);return}let r=Z(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{ki(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 Fi=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return Ii(t);case`remove`:return Li(e[1],t);case`move`:return Ri(e[1],e[2],t);case`clear`:return zi(t);default:t.tui.info.showToast(`Queue`,`/queue ${n} — unknown subcommand. Use: list|remove|move|clear`)}};async function Ii(e){e.tui.panes.togglePane(`queuePane`,!0)}async function Li(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 Ri(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 zi(e){e.tui.panes.clearQueue(),e.tui.info.showToast(`Queue`,`Queue cleared`)}const Bi=async(e,t)=>{let{session:n,agentProcessing:r}=t.state;if(n.isPaused&&!n.isBusy){n.resumeRun(),t.tui.info.showToast(O.t(`cmd.titleInfo`),O.t(`cmd.runResumedByCommand`)),Vi(t);return}if(n.isPaused&&n.isBusy){n.cancelPauseRun()?t.tui.info.showToast(O.t(`cmd.titleInfo`),O.t(`cmd.pauseCancelled`)):(n.resumeRun(),t.tui.info.showToast(O.t(`cmd.titleInfo`),O.t(`cmd.runResumedByCommand`))),Vi(t);return}if(r){n.pauseRun()?t.tui.info.showToast(O.t(`cmd.titlePauseRequested`),O.t(`cmd.runWillPauseAfterTurn`)):t.tui.info.showToast(O.t(`cmd.titleInfo`),O.t(`cmd.noRunningTaskToPause`)),Vi(t);return}t.tui.info.showToast(O.t(`cmd.titleInfo`),O.t(`cmd.nothingToPause`))};function Vi(e){let t=e.callbacks.refreshSlashCommands?.();t&&e.tui.plugins.setCommands(t)}async function Hi(e,t){let n=t.app.settings.get(`keybinding_overrides`),r=()=>{t.tui.info.showToast(O.t(`cmd.keybindTitle`),O.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 Ui(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 Wi(e){let t=e.trim().split(`
|
|
16
|
+
`)[0].replace(/\s+/g,` `).trim();return t.length>40?`${t.slice(0,39)}…`:t}function Gi(e){e.pluginInput.unregisterBySource(`shortcut`);let t=(e.settings.get(`shortcuts`)??[]).map(e=>({label:`@${e.name}`,value:`[@shortcut:${e.name.replace(/]/g,`\\]`)}]`,description:Wi(e.text),kind:`shortcut`,source:`shortcut`}));t.length&&e.pluginInput.register(t)}function Ki(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)}const qi={low:`cmd.effortDescLow`,medium:`cmd.effortDescMedium`,high:`cmd.effortDescHigh`,xhigh:`cmd.effortDescXhigh`,max:`cmd.effortDescMax`};function Ji(e){let t=q.map(e=>({label:P(e),value:`[@effort:${e}]`,description:O.t(qi[e]??`cmd.effortDescLow`),kind:`effort`,source:`builtin-effort`}));e.pluginInput.unregisterBySource(`builtin-effort`),e.pluginInput.register(t)}async function Yi(e,t){t.tui.modal.openModal({kind:`shortcutsPanel`,shortcuts:t.app.getShortcuts(),onSave:(e,n,r)=>{t.app.saveShortcut(e,n,r).then(()=>Gi(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(()=>Gi(t.app)).catch(e=>{t.tui.info.showToast(`Shortcuts`,`Delete failed: ${e instanceof Error?e.message:String(e)}`)})}})}function Xi(e){let t;try{let n=Re(e,`r`);try{t=Buffer.alloc(512);let e=Be(n,t,0,512,0);t=t.subarray(0,e)}finally{Le(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 Zi(e){return e>=1048576?`${(e/1048576).toFixed(1)} MB`:e>=1024?`${(e/1024).toFixed(1)} KB`:`${e} B`}function Qi(e){let t;try{t=Ve(e)}catch{return[]}let n=[];for(let r of t)try{let t=E(C(e,r));n.push({name:r,isDir:t.isDirectory(),size:t.isDirectory()?void 0:t.size})}catch{}return n}function $i(e){return[...e].sort((e,t)=>e.isDir===t.isDir?e.name.localeCompare(t.name):e.isDir?-1:1)}function Q(e,t,n,r){let i=$i(Qi(n)),a=Ie(t,n),o=a===``?O.t(`cmd.openBrowserSubtitleRoot`):O.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:Zi(e.size??0)}));e.tui.modal.openModal({kind:`select`,title:O.t(`cmd.titleOpen`),subtitle:o,searchable:!0,options:c,initialFilter:r.get(n)??``,onFilterChange:e=>{r.set(n,e)},onSelect:i=>{let a=C(n,i),o;try{o=E(a).isDirectory()}catch{e.tui.info.showToast(O.t(`cmd.titleOpen`),O.t(`cmd.openNotFound`,{path:i}));return}if(o){Q(e,t,a,r);return}ea(e,a,i,()=>{Q(e,t,n,r)}).catch(()=>{e.tui.info.showToast(O.t(`cmd.titleOpen`),O.t(`cmd.openNotFound`,{path:i}))})},onCancel:s?()=>Q(e,t,S(n),r):()=>{}})}async function ea(e,t,n,r){if(Xi(t)){e.tui.info.showToast(O.t(`cmd.titleOpen`),O.t(`cmd.openBinaryRejected`,{path:n}));return}let{content:i,truncated:a}=await Me(t);e.tui.modal.openModal({kind:`fileViewer`,path:n,content:i,preTruncated:a,onDismiss:r??(()=>{})})}async function ta(e,t){let n=t.app.workspaceDir??process.cwd(),r=e.join(` `).trim(),i=new Map;if(!r){Q(t,n,n,i);return}let a=w(n,r),o=Ie(n,a).startsWith(`..`);if(!T(a)){if(o){t.tui.info.showToast(O.t(`cmd.titleOpen`),O.t(`cmd.openNotFound`,{path:r}));return}let e=S(a);for(;e!==n&&e!==S(e)&&!T(e);)e=S(e);if(T(e)&&E(e).isDirectory()){Q(t,n,e,i);return}t.tui.info.showToast(O.t(`cmd.titleOpen`),O.t(`cmd.openNotFound`,{path:r}));return}if(E(a).isDirectory()){if(o){t.tui.info.showToast(O.t(`cmd.titleOpen`),O.t(`cmd.openNotFound`,{path:r}));return}Q(t,n,a,i);return}await ea(t,a,r)}var na=mt({DISPATCHABLE_COMMAND_NAMES:()=>oa,ENGINE_BUILTIN_COMMANDS:()=>aa,HELP_GROUP_ORDER:()=>ra,SAFE_COMMAND_NAMES:()=>ia,SLASH_COMMANDS:()=>$,dispatchSlashCommand:()=>sa,handleCompact:()=>Wn,handleMemory:()=>Un});const ra=[`session`,`model`,`agent`,`debug`,`ui`,`other`],$=[{name:`clear`,handler:pn,engineBuiltin:!0,group:`session`,description:`Clear screen and reset interface state`},{name:`compact`,handler:Wn,group:`session`,description:`Compact context now, or /compact log for recent compaction/prune event details`},{name:`memory`,aliases:[`mem`],handler:Un,group:`session`,description:`Project + user memory: /memory [user|project|<name>|forget <name>]`},{name:`workspace`,handler:Gn,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:kn,safe:!0,engineBuiltin:!0,group:`session`,description:`Show session status (/status)`},{name:`open`,handler:ta,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:Ln,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:bi,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:_n,safe:!0,group:`debug`,description:`Surface improvement proposals from recurring hard failures (L1: suggest-only)`},{name:`context`,handler:An,safe:!0,group:`debug`,description:`Show context usage breakdown (system/tools/messages/cache/free bar)`},{name:`perf`,handler:Nn,safe:!0,group:`debug`,description:`Open performance panel (memory pressure, rendering health)`},{name:`cache-stats`,handler:Pn,safe:!0,group:`debug`,description:`Open cache hit rate panel (session/last-turn hit ratio, per-model breakdown)`},{name:`gallery`,handler:Fn,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:Tn,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:En,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:Gr,group:`ui`,description:`Switch reasoning effort (/effort low|medium|high|xhigh|max)`},{name:`preference`,aliases:[`pref`],handler:qr,safe:!0,group:`ui`,description:`Preferences: /preference [general|lang|theme]`},{name:`trust`,handler:li,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:hi,group:`ui`,description:`Toggle the notification center panel (≡ ctrl+n)`},{name:`services`,handler:_i,safe:!0,group:`other`,description:`Show detected services from delegated background processes (/services)`},{name:`draft`,handler:Ai,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:Fi,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:Hi,safe:!0,group:`ui`,description:`Open the keybinding panel: browse, search, remap, reset shortcuts (≡ default Ctrl+/)`},{name:`shortcuts`,handler:Yi,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)=>pi(e,t,$)},{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:Bi,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:hn,group:`other`,description:`List and switch to an existing session (--workspace <id>, --archived, --all)`},{name:`rename`,handler:mn,safe:!0,group:`session`,description:`Set a custom title for the current session (/rename <new title>)`},{name:`a2ui-action`,handler:wn,safe:!1,group:`session`,description:`Trigger A2UI interactive component action (/a2ui-action btn1 click)`},{name:`reload`,handler:gn,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 qn(e,t);return}await fi(e,t)||await di(e,t)}},{name:`about`,handler:Jn,safe:!0,group:`other`,description:`Show version, build, and environment info (/about)`},{name:`setup`,handler:Dr,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:ui,safe:!0,group:`other`,description:`View / clear the always-allow list (/permissions [clear])`},{name:`feedback`,handler:Xn,group:`other`,description:`Report an issue or send feedback via GitHub (/feedback [--repo <owner/repo>])`},{name:`archive`,handler:vn,safe:!0,description:`Toggle archive state (archived disables further input); /archive [<id>]`},{name:`session`,handler:Sn,description:`Session management: /session fork | /session unlock <id> [--force] | /session kill <id> | /session inspect <id>`},{name:`fork`,handler:On,safe:!0,description:`Fork current session into a named branch`},{name:`pin`,aliases:[`unpin`],handler:yn,safe:!0,description:`Toggle pin state (pinned sessions sort to top of /resume); /pin [<id>...] [--group <name>]`},{name:`history`,aliases:[`hist`],handler:mi,safe:!0,description:`Open history search panel (same panel as Ctrl+R)`},{name:`prompts`,handler:gi,safe:!0,description:`View prompt log (list of submitted prompts this session)`}],ia=new Set($.filter(e=>e.safe).flatMap(e=>[e.name,...e.aliases??[]])),aa=new Set($.filter(e=>e.engineBuiltin).flatMap(e=>[e.name,...e.aliases??[]])),oa=new Set($.filter(e=>e.handler).flatMap(e=>[e.name,...e.aliases??[]]));async function sa(e,t,n){let r=$.find(t=>t.name===e);return r||=$.find(t=>t.aliases?.includes(e)),r?.handler?(await r.handler(t,n),!0):!1}export{A as $,nn as A,qt as B,Sr as C,Vn as D,rr as E,Zt as F,It as G,Ft as H,He as I,N as J,Lt as K,We as L,tn as M,en as N,cn as O,Qt as P,Ct as Q,Xe as R,xr as S,cr as T,Rt as U,Kt as V,F as W,kt as X,At as Y,St as Z,Hr as _,na as a,jr as b,Ji as c,yi as d,xt as et,Kr as f,Vr as g,Rr as h,$ as i,rn as j,z as k,Ki as l,Br as m,aa as n,mt as nt,sa as o,q as p,Bt as q,ia as r,Gi as s,oa as t,bt as tt,Ui as u,Pr as v,lr as w,Nr as x,Mr as y,I as z};
|
|
17
|
+
//# sourceMappingURL=command-dispatcher-DibEV53Q.js.map
|