@x-otto/cli 0.0.1-alpha.32 → 0.0.1-alpha.33

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.
@@ -1 +1 @@
1
- {"version":3,"file":"parse-cli-sHwPwijC.js","names":[],"sources":["../src/parse-cli.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport type { CLIOptions, RunMode } from './types'\nimport { getVersion } from './version'\n\nexport type SubCommand = 'run' | 'serve' | 'daemon' | 'doctor' | 'config' | 'migrate' | 'auth' | 'observe' | 'debug' | 'time-travel' | 'mcp' | 'persistenced' | 'remote-persistence-server' | 'persistence' | 'extension' | 'ps' | 'feedback'\n\nexport interface ParsedCLI {\n options: CLIOptions\n /** 未命中任何内建子命令时为 `undefined`(而非 `null` 哨兵——与 SUB_COMMAND_NAMES 的\n * 元素类型保持一致,消费方无需 `.filter(n => n !== null)` 剔除哨兵值)。 */\n subCommand: SubCommand | undefined\n subCommandArgs: string\n /**\n * RFC-112 D2:内建 `SUB_COMMAND_NAMES` 未命中的第一个位置参数(候选插件 CLI 命令名,\n * 如 `otto feishu ...` 里的 `\"feishu\"`)。`undefined` 表示第一个参数已命中内建命令,\n * 或压根没有位置参数。**不改变** `options.prompt`/`subCommand` 的既有构建逻辑——\n * 这两者仍然按\"当作 prompt\"的旧行为完整计算好,供插件命令名查无匹配时零改动回退。\n */\n unresolvedCommandName?: string\n /**\n * 与 `unresolvedCommandName` 配对:该候选名之后的**原始** args(未做 flag 过滤,含 `-h`\n * 等字面量),只在插件命令表命中该名字时使用(透传给插件可执行文件)。\n */\n unresolvedCommandArgs?: string[]\n}\n\n/** RFC-112 D2:导出供 `cli.ts` 构建插件 CLI 命令表时用作保留字集合(插件不得覆盖)。 */\nexport const SUB_COMMAND_NAMES = new Set<SubCommand>([\n 'run', 'serve', 'daemon', 'doctor', 'config', 'migrate', 'auth', 'observe', 'debug', 'time-travel', 'mcp', 'persistenced', 'remote-persistence-server', 'persistence', 'extension', 'ps', 'feedback',\n])\n\ntype OptionEntry =\n | { flags: string[]; type: 'boolean'; key: keyof CLIOptions }\n | { flags: string[]; type: 'mode'; value: RunMode }\n | { flags: string[]; type: 'string'; key: keyof CLIOptions }\n | { flags: string[]; type: 'number'; key: keyof CLIOptions }\n | { flags: string[]; type: 'path'; key: keyof CLIOptions }\n | { flags: string[]; type: 'action'; handler: () => void }\n\nconst OPTIONS: OptionEntry[] = [\n { flags: ['--print', '-p'], type: 'mode', value: 'print' },\n { flags: ['--interactive', '-i'], type: 'mode', value: 'interactive' },\n { flags: ['--json'], type: 'mode', value: 'json' },\n { flags: ['--model', '-m'], type: 'string', key: 'model' },\n { flags: ['--config', '-c'], type: 'string', key: 'configPath' },\n { flags: ['--project', '-d'], type: 'path', key: 'projectDir' },\n { flags: ['--quiet', '-q'], type: 'boolean', key: 'quiet' },\n { flags: ['--verbose'], type: 'boolean', key: 'verbose' },\n { flags: ['--max-tool-turns'], type: 'number', key: 'maxToolTurns' },\n { flags: ['--max-tool-turn-extensions'], type: 'number', key: 'maxToolTurnExtensions' },\n { flags: ['--prompt-token-budget'], type: 'number', key: 'promptTokenBudget' },\n { flags: ['--prompt-time-budget'], type: 'number', key: 'promptTimeBudgetMin' },\n { flags: ['--session-cost-budget'], type: 'number', key: 'sessionCostBudget' },\n { flags: ['--no-stall-detection'], type: 'boolean', key: 'noStallDetection' },\n { flags: ['--stall-window-turns'], type: 'number', key: 'stallWindowTurns' },\n { flags: ['--stall-repeat-threshold'], type: 'number', key: 'stallRepeatThreshold' },\n { flags: ['--continue'], type: 'string', key: 'continueSession' },\n { flags: ['--attach'], type: 'string', key: 'attachSession' },\n { flags: ['--force-write-lease'], type: 'boolean', key: 'forceWriteLease' },\n // RFC-115 M3(P1-1 修正):仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——\n // 区分\"内存压力触发的自动重启\"与\"用户手动 otto --continue\",前者才应起算 D5 宽限期。\n { flags: ['--memory-restart-grace'], type: 'boolean', key: 'memoryRestartGrace' },\n // RFC-115 M4:仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——重启前\n // 会话正忙时的续跑原文,子进程启动后自动重新提交为续跑轮。\n { flags: ['--resume-prompt'], type: 'string', key: 'resumePrompt' },\n { flags: ['--session-url'], type: 'string', key: 'sessionUrl' },\n { flags: ['--session-token'], type: 'string', key: 'sessionToken' },\n { flags: ['--id'], type: 'string', key: 'workspaceId' },\n { flags: ['--shadow'], type: 'boolean', key: 'shadow' },\n { flags: ['--help', '-h'], type: 'boolean', key: 'showHelp' },\n { flags: ['--version', '-v'], type: 'action', handler: printVersion },\n]\n\nconst OPTION_LOOKUP: Map<string, OptionEntry> = new Map(\n OPTIONS.flatMap(e => e.flags.map(f => [f, e] as const)),\n)\n\nclass ArgCursor {\n private i: number\n constructor(private args: string[]) {\n this.i = 0\n }\n current(): string | undefined { return this.args[this.i] }\n next(): string | undefined { return this.args[++this.i] }\n advance(): void { this.i++ }\n skip(count: number): void { this.i += count }\n pos(): number { return this.i }\n}\n\nexport function parseCLI(argv: string[]): ParsedCLI {\n const args = argv.slice(2)\n const cursor = new ArgCursor(args)\n\n const options: CLIOptions = {\n mode: 'interactive',\n projectDir: process.cwd(),\n verbose: false,\n quiet: false,\n }\n\n const first = cursor.current()\n let subCommand: SubCommand | undefined\n let subCommandArgs = ''\n let unresolvedCommandName: string | undefined\n let unresolvedCommandArgs: string[] | undefined\n if (first && SUB_COMMAND_NAMES.has(first as SubCommand)) {\n subCommand = first as SubCommand\n subCommandArgs = args.slice(1).join(' ')\n cursor.skip(1)\n\n if (subCommand === 'run') {\n options.prompt = args.slice(1).filter(a => !a.startsWith('-')).join(' ')\n options.mode = 'print'\n }\n } else if (first && !first.startsWith('-')) {\n // RFC-112 D2:第一个位置参数不是内建命令,也不以 `-` 开头(不是 flag)——\n // 记录为候选插件 CLI 命令名,供 cli.ts 查插件表二次判定;不改变下方现有的\n // \"当作 prompt\" 逻辑(该逻辑仍会照常把 first 纳入 promptParts,回退路径零改动)。\n unresolvedCommandName = first\n unresolvedCommandArgs = args.slice(1)\n }\n\n let promptParts: string[] = options.prompt ? [options.prompt] : []\n\n while (cursor.current() !== undefined) {\n const arg = cursor.current()!\n\n if (arg === '--inspect') {\n options.inspect = true\n cursor.advance()\n continue\n }\n if (arg?.startsWith('--inspect=')) {\n const port = Number(arg.slice('--inspect='.length))\n options.inspect = Number.isInteger(port) && port > 0 ? port : true\n cursor.advance()\n continue\n }\n // RFC-196 M3:重启代际计数(chaperone 重启 spawn 注入,不文档化——内部可观测标记,\n // 供 ≥3 代告警与 otto ps GEN 列展示;不驱动任何行为分支)。\n if (arg?.startsWith('--restart-generation=')) {\n const gen = Number(arg.slice('--restart-generation='.length))\n if (Number.isInteger(gen) && gen > 0) options.restartGeneration = gen\n cursor.advance()\n continue\n }\n\n const entry = OPTION_LOOKUP.get(arg)\n if (entry) {\n cursor.advance()\n switch (entry.type) {\n case 'boolean':\n ;(options as unknown as Record<string, unknown>)[entry.key] = true\n break\n case 'mode':\n options.mode = entry.value\n break\n case 'string':\n ;(options as unknown as Record<string, unknown>)[entry.key] = cursor.current()\n cursor.advance()\n break\n case 'number':\n ;(options as unknown as Record<string, unknown>)[entry.key] = Number(cursor.current())\n cursor.advance()\n break\n case 'path':\n ;(options as unknown as Record<string, unknown>)[entry.key] = resolve(cursor.current() ?? process.cwd())\n cursor.advance()\n break\n case 'action':\n entry.handler()\n break\n }\n continue\n }\n\n if (arg && !arg.startsWith('-') && !subCommand) {\n if (options.prompt === undefined && options.mode === 'interactive') {\n options.mode = 'print'\n }\n promptParts.push(arg)\n }\n cursor.advance()\n }\n\n if (promptParts.length > 0) {\n options.prompt = promptParts.join(' ')\n }\n\n return { options, subCommand, subCommandArgs, unresolvedCommandName, unresolvedCommandArgs }\n}\n\n/** 帮助文本行(供 plain-text printHelp 与 TUI InfoDialog 共用)。 */\nexport function getHelpLines(): string[] {\n return [\n '',\n 'otto - AI 助理命令行工具',\n '',\n '用法:',\n ' otto [提示词] 使用提示词启动(print 模式)',\n ' otto 进入交互式 TUI 模式',\n ' otto --json \"query\" JSON 输出模式',\n '',\n '选项:',\n ' -i, --interactive Interactive 模式(默认)',\n ' -p, --print Print 模式(非交互)',\n ' --json JSON 输出模式',\n ' -m, --model <id> 指定模型',\n ' -c, --config <path> 配置文件路径',\n ' -d, --project <dir> 项目目录',\n ' --verbose 输出详细日志',\n ' -q, --quiet 只输出 error 日志',\n ' --shadow 影子模式:otto 自有状态(凭据/会话/记忆/教训/配置/trace/日志)本次会话零磁盘写入(不保证 provider 服务端日志与 shell/OS 层痕迹;RFC-345)',\n ' --max-tool-turns <n> 单个用户回合最大工具回合数(默认 120)',\n ' --max-tool-turn-extensions <n> 触顶后压缩续跑的扩展次数(默认主会话 3 / 子 agent 0)',\n ' --prompt-token-budget <n> 单回合输出 token 预算(配置后轮次上限 ×4 退位安全阀;RFC-104)',\n ' --prompt-time-budget <min> 单回合墙钟时间预算(分钟)',\n ' --session-cost-budget <usd> 会话累计成本软预算(美元,超过一次性提醒不阻断;RFC-204)',\n ' --no-stall-detection 关闭早期停滞检测(默认开启;RFC-203)',\n ' --stall-window-turns <n> 停滞检测滑动窗口大小(需与 --stall-repeat-threshold 同时提供,默认 8)',\n ' --stall-repeat-threshold <n> 停滞检测同签名重复阈值(需与 --stall-window-turns 同时提供,默认 4)',\n ' --continue <id> 继续已有会话',\n ' --session-url <url> 远端会话持久化地址(如 http://host:3001/sessions)',\n ' --session-token <token> 远端会话持久化 Bearer token',\n ' --inspect[=port] 启用 Node.js inspector(默认: 9229)',\n ' -h, --help 显示帮助',\n ' --version, -v 显示版本',\n '',\n '命令:',\n ' otto run <prompt> 执行一次性任务',\n ' otto serve [--port N] [--inspect] [--static <dir>] [--token <t>] 启动 HTTP/WS service(--static 同源托管前端 SPA,--token 启用鉴权)',\n ' otto doctor [--summary|--json] 环境健康检查(环境/配置/存储状态/连通性)',\n ' otto auth login <provider> 登录(cursor / anthropic / openai-codex / github-copilot)',\n ' otto auth status 查看各 provider 凭据来源',\n ' otto auth logout <provider> 注销并清除凭据',\n ' otto config export [--project] [-o <path>] 导出配置(RFC-219)',\n ' otto config import <file> [--dry-run] [--scope global|project] [--no-plugins] [--plugins-only] [--yes] 导入配置',\n ' otto config restore [--list] 撤销最近一次导入',\n ' otto migrate export [--no-sessions] [-o <path>] 导出配置+插件清单+会话数据为迁移包(换电脑用)',\n ' otto migrate import <archive> [--no-sessions] 导入迁移包(目标已有会话数据时跳过会话部分)',\n ' otto observe <action> <id> 观测面板(summary / timeline / spans)',\n ' otto observe debug <action> [...] 调试面板(breakpoints / points / state)',\n ' otto observe replay <action> <id> 时间旅行(checkpoints / scrubber / restore / fork / replay)',\n ' otto debug <action> [...] (alias: otto observe debug)',\n ' otto time-travel <action> <id> (alias: otto observe replay)',\n ' otto mcp login <name> MCP server OAuth 登录',\n ' otto mcp logout <name> 登出 MCP server',\n ' otto mcp list 列出已认证的 MCP server',\n ' otto extension create <name> 生成插件骨架(命令 + 面板 + manifest,开箱即用)',\n ' otto extension install <name> [--yes] 安装首方/自定义插件(anthropic-provider / deepseek-provider / browser-use / …)',\n ' otto extension update [name] 检查并重装已过期的已安装 skill/plugin',\n ' otto persistence local [...flags] 启动独立持久化服务(storage + events + sync)',\n ' otto persistence remote [...flags] 启动最小化远程持久化服务(5 REST 端点)',\n ' otto persistenced [...flags] (alias: otto persistence local)',\n ' otto remote-persistence-server [...flags] (alias: otto persistence remote)',\n ' otto ps [--sweep] [--include-weak] [--json] 进程群列表与孤儿清扫(SIGTERM only,RFC-196)',\n '',\n '面板命令默认连 `otto serve` 实例(http://127.0.0.1:8417,OTTO_SERVICE_URL/--remote 可覆盖)。',\n ]\n}\n\nfunction printVersion(): void {\n process.stdout.write(`otto ${getVersion()}\\n`)\n process.exit(0)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parse-cli-LC0shiw-.js","names":[],"sources":["../src/parse-cli.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport type { CLIOptions, RunMode } from './types'\nimport { getVersion } from './version'\n\nexport type SubCommand = 'run' | 'serve' | 'daemon' | 'doctor' | 'config' | 'migrate' | 'auth' | 'observe' | 'debug' | 'time-travel' | 'mcp' | 'persistenced' | 'remote-persistence-server' | 'persistence' | 'extension' | 'ps' | 'feedback'\n\nexport interface ParsedCLI {\n options: CLIOptions\n /** 未命中任何内建子命令时为 `undefined`(而非 `null` 哨兵——与 SUB_COMMAND_NAMES 的\n * 元素类型保持一致,消费方无需 `.filter(n => n !== null)` 剔除哨兵值)。 */\n subCommand: SubCommand | undefined\n subCommandArgs: string\n /**\n * RFC-112 D2:内建 `SUB_COMMAND_NAMES` 未命中的第一个位置参数(候选插件 CLI 命令名,\n * 如 `otto feishu ...` 里的 `\"feishu\"`)。`undefined` 表示第一个参数已命中内建命令,\n * 或压根没有位置参数。**不改变** `options.prompt`/`subCommand` 的既有构建逻辑——\n * 这两者仍然按\"当作 prompt\"的旧行为完整计算好,供插件命令名查无匹配时零改动回退。\n */\n unresolvedCommandName?: string\n /**\n * 与 `unresolvedCommandName` 配对:该候选名之后的**原始** args(未做 flag 过滤,含 `-h`\n * 等字面量),只在插件命令表命中该名字时使用(透传给插件可执行文件)。\n */\n unresolvedCommandArgs?: string[]\n}\n\n/** RFC-112 D2:导出供 `cli.ts` 构建插件 CLI 命令表时用作保留字集合(插件不得覆盖)。 */\nexport const SUB_COMMAND_NAMES = new Set<SubCommand>([\n 'run', 'serve', 'daemon', 'doctor', 'config', 'migrate', 'auth', 'observe', 'debug', 'time-travel', 'mcp', 'persistenced', 'remote-persistence-server', 'persistence', 'extension', 'ps', 'feedback',\n])\n\ntype OptionEntry =\n | { flags: string[]; type: 'boolean'; key: keyof CLIOptions }\n | { flags: string[]; type: 'mode'; value: RunMode }\n | { flags: string[]; type: 'string'; key: keyof CLIOptions }\n | { flags: string[]; type: 'number'; key: keyof CLIOptions }\n | { flags: string[]; type: 'path'; key: keyof CLIOptions }\n | { flags: string[]; type: 'action'; handler: () => void }\n\nconst OPTIONS: OptionEntry[] = [\n { flags: ['--print', '-p'], type: 'mode', value: 'print' },\n { flags: ['--interactive', '-i'], type: 'mode', value: 'interactive' },\n { flags: ['--json'], type: 'mode', value: 'json' },\n { flags: ['--model', '-m'], type: 'string', key: 'model' },\n { flags: ['--config', '-c'], type: 'string', key: 'configPath' },\n { flags: ['--project', '-d'], type: 'path', key: 'projectDir' },\n { flags: ['--quiet', '-q'], type: 'boolean', key: 'quiet' },\n { flags: ['--verbose'], type: 'boolean', key: 'verbose' },\n { flags: ['--max-tool-turns'], type: 'number', key: 'maxToolTurns' },\n { flags: ['--max-tool-turn-extensions'], type: 'number', key: 'maxToolTurnExtensions' },\n { flags: ['--prompt-token-budget'], type: 'number', key: 'promptTokenBudget' },\n { flags: ['--prompt-time-budget'], type: 'number', key: 'promptTimeBudgetMin' },\n { flags: ['--session-cost-budget'], type: 'number', key: 'sessionCostBudget' },\n { flags: ['--no-stall-detection'], type: 'boolean', key: 'noStallDetection' },\n { flags: ['--stall-window-turns'], type: 'number', key: 'stallWindowTurns' },\n { flags: ['--stall-repeat-threshold'], type: 'number', key: 'stallRepeatThreshold' },\n { flags: ['--continue'], type: 'string', key: 'continueSession' },\n { flags: ['--attach'], type: 'string', key: 'attachSession' },\n { flags: ['--force-write-lease'], type: 'boolean', key: 'forceWriteLease' },\n // RFC-115 M3(P1-1 修正):仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——\n // 区分\"内存压力触发的自动重启\"与\"用户手动 otto --continue\",前者才应起算 D5 宽限期。\n { flags: ['--memory-restart-grace'], type: 'boolean', key: 'memoryRestartGrace' },\n // RFC-115 M4:仅由 cli.ts 的内存治理触发重启 chaperone 附加,不对外文档化——重启前\n // 会话正忙时的续跑原文,子进程启动后自动重新提交为续跑轮。\n { flags: ['--resume-prompt'], type: 'string', key: 'resumePrompt' },\n { flags: ['--session-url'], type: 'string', key: 'sessionUrl' },\n { flags: ['--session-token'], type: 'string', key: 'sessionToken' },\n { flags: ['--id'], type: 'string', key: 'workspaceId' },\n { flags: ['--shadow'], type: 'boolean', key: 'shadow' },\n { flags: ['--help', '-h'], type: 'boolean', key: 'showHelp' },\n { flags: ['--version', '-v'], type: 'action', handler: printVersion },\n]\n\nconst OPTION_LOOKUP: Map<string, OptionEntry> = new Map(\n OPTIONS.flatMap(e => e.flags.map(f => [f, e] as const)),\n)\n\nclass ArgCursor {\n private i: number\n constructor(private args: string[]) {\n this.i = 0\n }\n current(): string | undefined { return this.args[this.i] }\n next(): string | undefined { return this.args[++this.i] }\n advance(): void { this.i++ }\n skip(count: number): void { this.i += count }\n pos(): number { return this.i }\n}\n\nexport function parseCLI(argv: string[]): ParsedCLI {\n const args = argv.slice(2)\n const cursor = new ArgCursor(args)\n\n const options: CLIOptions = {\n mode: 'interactive',\n projectDir: process.cwd(),\n verbose: false,\n quiet: false,\n }\n\n const first = cursor.current()\n let subCommand: SubCommand | undefined\n let subCommandArgs = ''\n let unresolvedCommandName: string | undefined\n let unresolvedCommandArgs: string[] | undefined\n if (first && SUB_COMMAND_NAMES.has(first as SubCommand)) {\n subCommand = first as SubCommand\n subCommandArgs = args.slice(1).join(' ')\n cursor.skip(1)\n\n if (subCommand === 'run') {\n options.prompt = args.slice(1).filter(a => !a.startsWith('-')).join(' ')\n options.mode = 'print'\n }\n } else if (first && !first.startsWith('-')) {\n // RFC-112 D2:第一个位置参数不是内建命令,也不以 `-` 开头(不是 flag)——\n // 记录为候选插件 CLI 命令名,供 cli.ts 查插件表二次判定;不改变下方现有的\n // \"当作 prompt\" 逻辑(该逻辑仍会照常把 first 纳入 promptParts,回退路径零改动)。\n unresolvedCommandName = first\n unresolvedCommandArgs = args.slice(1)\n }\n\n let promptParts: string[] = options.prompt ? [options.prompt] : []\n\n while (cursor.current() !== undefined) {\n const arg = cursor.current()!\n\n if (arg === '--inspect') {\n options.inspect = true\n cursor.advance()\n continue\n }\n if (arg?.startsWith('--inspect=')) {\n const port = Number(arg.slice('--inspect='.length))\n options.inspect = Number.isInteger(port) && port > 0 ? port : true\n cursor.advance()\n continue\n }\n // RFC-196 M3:重启代际计数(chaperone 重启 spawn 注入,不文档化——内部可观测标记,\n // 供 ≥3 代告警与 otto ps GEN 列展示;不驱动任何行为分支)。\n if (arg?.startsWith('--restart-generation=')) {\n const gen = Number(arg.slice('--restart-generation='.length))\n if (Number.isInteger(gen) && gen > 0) options.restartGeneration = gen\n cursor.advance()\n continue\n }\n\n const entry = OPTION_LOOKUP.get(arg)\n if (entry) {\n cursor.advance()\n switch (entry.type) {\n case 'boolean':\n ;(options as unknown as Record<string, unknown>)[entry.key] = true\n break\n case 'mode':\n options.mode = entry.value\n break\n case 'string':\n ;(options as unknown as Record<string, unknown>)[entry.key] = cursor.current()\n cursor.advance()\n break\n case 'number':\n ;(options as unknown as Record<string, unknown>)[entry.key] = Number(cursor.current())\n cursor.advance()\n break\n case 'path':\n ;(options as unknown as Record<string, unknown>)[entry.key] = resolve(cursor.current() ?? process.cwd())\n cursor.advance()\n break\n case 'action':\n entry.handler()\n break\n }\n continue\n }\n\n if (arg && !arg.startsWith('-') && !subCommand) {\n if (options.prompt === undefined && options.mode === 'interactive') {\n options.mode = 'print'\n }\n promptParts.push(arg)\n }\n cursor.advance()\n }\n\n if (promptParts.length > 0) {\n options.prompt = promptParts.join(' ')\n }\n\n return { options, subCommand, subCommandArgs, unresolvedCommandName, unresolvedCommandArgs }\n}\n\n/** 帮助文本行(供 plain-text printHelp 与 TUI InfoDialog 共用)。 */\nexport function getHelpLines(): string[] {\n return [\n '',\n 'otto - AI 助理命令行工具',\n '',\n '用法:',\n ' otto [提示词] 使用提示词启动(print 模式)',\n ' otto 进入交互式 TUI 模式',\n ' otto --json \"query\" JSON 输出模式',\n '',\n '选项:',\n ' -i, --interactive Interactive 模式(默认)',\n ' -p, --print Print 模式(非交互)',\n ' --json JSON 输出模式',\n ' -m, --model <id> 指定模型',\n ' -c, --config <path> 配置文件路径',\n ' -d, --project <dir> 项目目录',\n ' --verbose 输出详细日志',\n ' -q, --quiet 只输出 error 日志',\n ' --shadow 影子模式:otto 自有状态(凭据/会话/记忆/教训/配置/trace/日志)本次会话零磁盘写入(不保证 provider 服务端日志与 shell/OS 层痕迹;RFC-345)',\n ' --max-tool-turns <n> 单个用户回合最大工具回合数(默认 120)',\n ' --max-tool-turn-extensions <n> 触顶后压缩续跑的扩展次数(默认主会话 3 / 子 agent 0)',\n ' --prompt-token-budget <n> 单回合输出 token 预算(配置后轮次上限 ×4 退位安全阀;RFC-104)',\n ' --prompt-time-budget <min> 单回合墙钟时间预算(分钟)',\n ' --session-cost-budget <usd> 会话累计成本软预算(美元,超过一次性提醒不阻断;RFC-204)',\n ' --no-stall-detection 关闭早期停滞检测(默认开启;RFC-203)',\n ' --stall-window-turns <n> 停滞检测滑动窗口大小(需与 --stall-repeat-threshold 同时提供,默认 8)',\n ' --stall-repeat-threshold <n> 停滞检测同签名重复阈值(需与 --stall-window-turns 同时提供,默认 4)',\n ' --continue <id> 继续已有会话',\n ' --session-url <url> 远端会话持久化地址(如 http://host:3001/sessions)',\n ' --session-token <token> 远端会话持久化 Bearer token',\n ' --inspect[=port] 启用 Node.js inspector(默认: 9229)',\n ' -h, --help 显示帮助',\n ' --version, -v 显示版本',\n '',\n '命令:',\n ' otto run <prompt> 执行一次性任务',\n ' otto serve [--port N] [--inspect] [--static <dir>] [--token <t>] 启动 HTTP/WS service(--static 同源托管前端 SPA,--token 启用鉴权)',\n ' otto doctor [--summary|--json] 环境健康检查(环境/配置/存储状态/连通性)',\n ' otto auth login <provider> 登录(cursor / anthropic / openai-codex / github-copilot)',\n ' otto auth status 查看各 provider 凭据来源',\n ' otto auth logout <provider> 注销并清除凭据',\n ' otto config export [--project] [-o <path>] 导出配置(RFC-219)',\n ' otto config import <file> [--dry-run] [--scope global|project] [--no-plugins] [--plugins-only] [--yes] 导入配置',\n ' otto config restore [--list] 撤销最近一次导入',\n ' otto migrate export [--no-sessions] [-o <path>] 导出配置+插件清单+会话数据为迁移包(换电脑用)',\n ' otto migrate import <archive> [--no-sessions] 导入迁移包(目标已有会话数据时跳过会话部分)',\n ' otto observe <action> <id> 观测面板(summary / timeline / spans)',\n ' otto observe debug <action> [...] 调试面板(breakpoints / points / state)',\n ' otto observe replay <action> <id> 时间旅行(checkpoints / scrubber / restore / fork / replay)',\n ' otto debug <action> [...] (alias: otto observe debug)',\n ' otto time-travel <action> <id> (alias: otto observe replay)',\n ' otto mcp login <name> MCP server OAuth 登录',\n ' otto mcp logout <name> 登出 MCP server',\n ' otto mcp list 列出已认证的 MCP server',\n ' otto extension create <name> 生成插件骨架(命令 + 面板 + manifest,开箱即用)',\n ' otto extension install <name> [--yes] 安装首方/自定义插件(anthropic-provider / deepseek-provider / browser-use / …)',\n ' otto extension update [name] 检查并重装已过期的已安装 skill/plugin',\n ' otto persistence local [...flags] 启动独立持久化服务(storage + events + sync)',\n ' otto persistence remote [...flags] 启动最小化远程持久化服务(5 REST 端点)',\n ' otto persistenced [...flags] (alias: otto persistence local)',\n ' otto remote-persistence-server [...flags] (alias: otto persistence remote)',\n ' otto ps [--sweep] [--include-weak] [--json] 进程群列表与孤儿清扫(SIGTERM only,RFC-196)',\n '',\n '面板命令默认连 `otto serve` 实例(http://127.0.0.1:8417,OTTO_SERVICE_URL/--remote 可覆盖)。',\n ]\n}\n\nfunction printVersion(): void {\n process.stdout.write(`otto ${getVersion()}\\n`)\n process.exit(0)\n}\n"],"mappings":"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"}
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{n as e}from"./build-id-C6her8PN.js";import{createRequire as t}from"node:module";const n=t(import.meta.url);function r(){return`${n(`../package.json`).version??`0.0.0`} (build ${e})`}export{r as t};
3
- //# sourceMappingURL=version-CQeP5w1h.js.map
2
+ import{n as e}from"./build-id-BSDWscJA.js";import{createRequire as t}from"node:module";const n=t(import.meta.url);function r(){return`${n(`../package.json`).version??`0.0.0`} (build ${e})`}export{r as t};
3
+ //# sourceMappingURL=version-qmnKId20.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-CQeP5w1h.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["import { createRequire } from 'node:module'\n\nimport { BUILD_ID } from './build-id'\n\nconst require = createRequire(import.meta.url)\n\n/**\n * 版本号 + build ID。\n * 格式:`0.1.0 (build 2072)`。build ID = git rev-list --count HEAD,随每次构建自增。\n */\nexport function getVersion(): string {\n const pkg = require('../package.json') as { version?: string }\n const ver = pkg.version ?? '0.0.0'\n return `${ver} (build ${BUILD_ID})`\n}\n"],"mappings":";uFAIA,MAAM,EAAU,EAAc,OAAO,KAAK,IAAI,CAM9C,SAAgB,GAAqB,CAGnC,MAAO,GAFK,EAAQ,kBAAkB,CACtB,SAAW,QACb,UAAU,EAAS"}
1
+ {"version":3,"file":"version-qmnKId20.js","names":[],"sources":["../src/version.ts"],"sourcesContent":["import { createRequire } from 'node:module'\n\nimport { BUILD_ID } from './build-id'\n\nconst require = createRequire(import.meta.url)\n\n/**\n * 版本号 + build ID。\n * 格式:`0.1.0 (build 2072)`。build ID = git rev-list --count HEAD,随每次构建自增。\n */\nexport function getVersion(): string {\n const pkg = require('../package.json') as { version?: string }\n const ver = pkg.version ?? '0.0.0'\n return `${ver} (build ${BUILD_ID})`\n}\n"],"mappings":";uFAIA,MAAM,EAAU,EAAc,OAAO,KAAK,IAAI,CAM9C,SAAgB,GAAqB,CAGnC,MAAO,GAFK,EAAQ,kBAAkB,CACtB,SAAW,QACb,UAAU,EAAS"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x-otto/cli",
3
- "version": "0.0.1-alpha.32",
3
+ "version": "0.0.1-alpha.33",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -18,26 +18,26 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "react": "^19.2.4",
21
- "@x-otto/ai": "0.0.1-alpha.0",
21
+ "@x-otto/env": "0.1.0-alpha.4",
22
22
  "@x-otto/agent": "0.0.1-alpha.0",
23
23
  "@x-otto/schedule": "0.0.1-alpha.0",
24
- "@x-otto/coding": "0.0.1-alpha.12",
25
- "@x-otto/hooks": "0.0.1-alpha.0",
26
- "@x-otto/env": "0.1.0-alpha.4",
24
+ "@x-otto/coding": "0.0.1-alpha.13",
27
25
  "@x-otto/mcp": "0.0.1-alpha.0",
28
- "@x-otto/remote-persistence-server": "0.0.1-alpha.0",
29
- "@x-otto/interchange": "0.1.0-alpha.1",
30
- "@x-otto/runtime": "0.0.1-alpha.2",
26
+ "@x-otto/ai": "0.0.1-alpha.0",
27
+ "@x-otto/hooks": "0.0.1-alpha.0",
28
+ "@x-otto/remote-persistence-server": "0.0.1-alpha.1",
31
29
  "@x-otto/service": "0.0.1-alpha.0",
32
- "@x-otto/session": "0.0.1-alpha.1",
33
- "@x-otto/session-contract": "0.0.1-alpha.0",
34
30
  "@x-otto/memory": "0.0.1-alpha.0",
31
+ "@x-otto/runtime": "0.0.1-alpha.3",
32
+ "@x-otto/session-contract": "0.0.1-alpha.0",
33
+ "@x-otto/interchange": "0.1.0-alpha.1",
34
+ "@x-otto/persistence": "0.0.1-alpha.1",
35
+ "@x-otto/session": "0.0.1-alpha.2",
35
36
  "@x-otto/setting": "0.0.1-alpha.1",
36
- "@x-otto/persistence": "0.0.1-alpha.0",
37
- "@x-otto/trace-view": "0.0.1-alpha.0",
37
+ "@x-otto/tools": "0.0.1-alpha.0",
38
38
  "@x-otto/shared": "0.1.0-alpha.4",
39
39
  "@x-otto/tui": "0.0.1-alpha.11",
40
- "@x-otto/tools": "0.0.1-alpha.0"
40
+ "@x-otto/trace-view": "0.0.1-alpha.0"
41
41
  },
42
42
  "publishConfig": {
43
43
  "access": "public",
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- const e=4842,t=`e6bae822b`;export{e as n,t};
3
- //# sourceMappingURL=build-id-C6her8PN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-id-C6her8PN.js","names":[],"sources":["../src/build-id.ts"],"sourcesContent":["// auto-generated by scripts/gen-build-id.mjs — DO NOT EDIT\nexport const BUILD_ID = 4842\nexport const BUILD_BRANCH = 'dev'\nexport const BUILD_HASH = 'e6bae822b'\n"],"mappings":";AACA,MAAa,EAAW,KAEX,EAAa"}
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env node
2
- import{t as e}from"./build-id-C6her8PN.js";import{t}from"./version-CQeP5w1h.js";import{t as n}from"./discover-with-bundled-CF8qFP41.js";import{n as r,r as i,t as a}from"./service-client-Cr4sxDVM.js";import{n as o}from"./extension-DLFCUBJr.js";import{t as s}from"./proxy-evg7ZvoD.js";import{i as c}from"./install-DlVJRHRT.js";import{n as l,t as u}from"./registry-BdCcwyGy.js";import{n as d,t as f}from"./feedback-rhp8Et4E.js";import{createRequire as p}from"node:module";import{arch as m,cpus as h,freemem as g,homedir as _,platform as v,release as ee,totalmem as y}from"node:os";import{execFile as b,execSync as te,spawn as x,spawnSync as S}from"node:child_process";import{DEFAULT_WORKSPACE_KEY as ne,INDUCTOR_PLUGIN_ID as C,InstallManager as w,PLUGIN_MANIFEST_FILENAME as T,POINT as re,buildExtensionContext as ie,checkUpgrades as ae,collectPluginPerfMetrics as oe,defaultPostInstallExecutor as se,detectProjectConfigGating as ce,discoverFileCommands as le,discoverPlugins as ue,dispatch as de,evaluateClaudeTrust as fe,evaluatePluginTrust as pe,findWorkspaceRoot as me,getLastAssistantText as E,grantPluginCapabilities as he,installPluginFromPackage as ge,openTarget as _e,parsePluginManifest as ve,readHighRiskCapabilities as ye,readPluginLogTail as be,readSkillLoopStatus as xe,recordPluginInstalled as Se,recordPluginUninstalled as Ce,resolveActions as we,resolvePackageDir as Te,resolveSessionTitle as Ee,runPluginScript as De,scanInstalledVersions as Oe,trustPlugin as ke,trustProject as Ae,uninstall as je,untrustPlugin as Me,untrustProject as Ne}from"@x-otto/coding";import{checkShellCommand as Pe,openBrowser as Fe,readFileCapped as Ie}from"@x-otto/shared";import{BUILD_ID as Le,OTTO_HOME as Re,SDK_VERSION as ze}from"@x-otto/env";import{dirname as D,join as O,relative as Be,resolve as Ve}from"node:path";import{closeSync as He,existsSync as k,openSync as Ue,readFileSync as A,readSync as We,readdirSync as Ge,statSync as j}from"node:fs";import{FIGURES as M,buildTurnSummary as Ke,createBuiltinThemeRegistry as qe,createReducerState as Je,deriveTurnBoundaries as Ye,detectLanguage as Xe,formatProviderUsageLimitTypeFull as Ze,i18next as N,initI18n as Qe,insertTurnSummaries as $e,reduceToTui as et}from"@x-otto/tui";import{createBuiltinCommands as tt}from"@x-otto/tui/compat";import{MaxToolTurnsError as nt,PromptBudgetExceededError as rt}from"@x-otto/agent";import{readFile as it,readdir as at,stat as ot,unlink as st}from"node:fs/promises";import{DEFAULT_COMPACTION_CONFIG as ct,DEFAULT_PRUNE_CONFIG as lt,estimateTokensHeuristic as ut,resolveContextSize as dt}from"@x-otto/memory";import{classifyAuthErrorType as ft,computeCacheHitRatio as pt,createModelUsabilityGate as P,getProviderDescriptor as mt,getToolCallsByAssistantMessage as ht,isAuthError as gt}from"@x-otto/ai";import{promisify as _t}from"node:util";var vt=Object.defineProperty,yt=(e,t)=>{let n={};for(var r in e)vt(n,r,{get:e[r],enumerable:!0});return t||vt(n,Symbol.toStringTag,{value:`Module`}),n},bt=p(import.meta.url);function xt(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 St(e,t){let n=E(e.session.messages())||t.partialText,r=xt(t);return n?`${n}\n${r}`:r}function Ct(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 wt(e,t){let n=E(e.session.messages())||t.partialText,r=Ct(t);return n?`${n}\n${r}`:r}async function Tt(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 nt||t instanceof rt){let n=t instanceof rt,r=n?Ct(t):xt(t);o?.(n?`budget-exceeded`:`max-tool-turns`,r);let l=o?E(e.session.messages())||t.partialText:n?wt(e,t):St(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}),E(n)}let l=E(e.session.messages());return s(l),l}async function Et(e,t){try{await e.prompt(t)}catch(t){if(t instanceof nt)return{sessionId:e.id,status:`max_turns`,messageCount:e.session.messages().length,response:E(e.session.messages())||t.partialText};if(t instanceof rt)return{sessionId:e.id,status:`budget_exceeded`,messageCount:e.session.messages().length,response:E(e.session.messages())||t.partialText};throw t}return{sessionId:e.id,status:e.status,messageCount:e.session.messages().length,response:E(e.session.messages())}}var Dt=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=tt()}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=Pe(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=te(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 Tt(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 Tt(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 Ot(){return Xe()}function kt(e=`auto`){let t=e===`auto`?Xe():e;return Qe(t),t}const At=`@x-otto/cli`;async function jt(e){try{let t=new AbortController,n=setTimeout(()=>t.abort(),5e3),r=await fetch(`https://registry.npmjs.org/%40x-otto%2Fcli`,{signal:t.signal});if(clearTimeout(n),!r.ok)return null;let i=(await r.json())?.[`dist-tags`];if(!i)return null;let a=[i.alpha,i.latest].filter(e=>!!e),o=a.length>0?a.reduce((e,t)=>Pt(t,e)>0?t:e):Object.values(i).reduce((e,t)=>e===null||Pt(t,e)>0?t:e,null);return o?{latest:o,current:e,newer:Pt(o,Mt(e))>0}:null}catch{return null}}function Mt(e){let t=/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/.exec(e.trim());return t?t[0]:e}function Nt(e){let t=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(e.trim());return t?{core:[Number(t[1]),Number(t[2]),Number(t[3])],prerelease:t[4]?t[4].split(`.`):null}:null}function Pt(e,t){let n=Nt(e),r=Nt(t);if(!n||!r)return 0;for(let e=0;e<3;e++)if(n.core[e]!==r.core[e])return n.core[e]-r.core[e];if(n.prerelease===null&&r.prerelease===null)return 0;if(n.prerelease===null)return 1;if(r.prerelease===null)return-1;let i=Math.max(n.prerelease.length,r.prerelease.length);for(let e=0;e<i;e++){let t=n.prerelease[e],i=r.prerelease[e];if(t===void 0)return-1;if(i===void 0)return 1;if(t===i)continue;let a=/^\d+$/.test(t),o=/^\d+$/.test(i);return a&&o?Number(t)-Number(i):a?-1:o?1:t<i?-1:1}return 0}async function Ft(e){return new Promise(t=>{try{let n=x(process.platform===`win32`?`npm.cmd`:`npm`,[`install`,`-g`,e?`${At}@${e}`:`${At}@latest`],{stdio:`inherit`,shell:!0});n.on(`error`,e=>{t({ok:!1,error:e.message})}),n.on(`exit`,e=>{if(e!==0){t({ok:!1,error:`npm install exited with code ${e}`});return}t({ok:!0})})}catch(e){t({ok:!1,error:e.message})}})}function It(e){return e?Date.now()-e>216e5:!0}async function Lt(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||!It(e.lastCheck)?null:jt(e.currentVersion).then(async t=>t&&(e.persistLastCheck().catch(()=>{}),t.newer)?{...t,forced:!1}:null).catch(()=>null)}const Rt=ut;let zt,Bt;function Vt(e){let t=e.map(e=>e.name).sort().join(`,`);if(zt!==void 0&&Bt===t)return zt;let n=e=>typeof e==`function`?`[fn]`:typeof e==`string`?e:``;return zt=Rt(JSON.stringify(e.map(e=>({name:e.name,description:n(e.description),parameters:e.parameters})))),Bt=t,zt}let Ht,Ut;function Wt(e){return Ht!==void 0&&Ut===e?Ht:(Ht=Rt(e),Ut=e,Ht)}function Gt(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=Wt(t)+Vt(n),h=a+o+r+i+p,g=Math.max(0,h-m),_=Math.max(0,s-m-g),v=dt(lt.trigger,s),ee=dt(ct.trigger,s);return{modelName:c,contextWindow:s,contextPercent:s>0?h/s*100:0,overheadTokens:m,messageTokens:g,messageCount:f,totalUsed:h,free:_,pruneLine:v,compactLine:ee,lastInput:r,lastOutput:i,totalInput:l,totalOutput:u,cost:d,live:p>0}}const Kt={openai:`OpenAI`};function qt(e){let t=[`confirm`,`auto`,`bypass`];return t[(t.indexOf(e)+1)%t.length]??`confirm`}function Jt(e){return e===`error`?`error`:e===`approval_required`||e===`input_required`?`warning`:`info`}function Yt(e,t,n){let r=t===void 0?void 0:{code:t},i=r!==void 0&&gt(r),a=i&&ft(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 Xt(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=Xt(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 Qt(e,t){let n=[...le(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 $t(e){return{id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}}function en(e){return{type:`thinking`,thinking:e.text}}function tn(e){return{type:`text`,text:e.text}}function nn(e){return{type:`a2ui`,version:e.version,components:e.components}}function rn(e){let t=[],n=[];for(let r of e)switch(r.type){case`text`:r.text.trim()&&t.push(tn(r));break;case`thinking`:r.text.trim()&&t.push(en(r));break;case`tool_call`:n.push($t(r));break;case`a2ui`:t.push(nn(r));break}return{content:t,toolCalls:n}}function an(e){return typeof e==`string`?e.trim():e.filter(e=>e.type===`text`).map(e=>e.text).join(``).trim()}function on(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=an(e.content);t&&i.push({role:`user`,content:t});continue}if(e.role===`assistant`){let{content:t}=rn(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:on(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:on(r),argsObj:r,result:an(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 sn=_t(b);function cn(e,t,n){for(let r of e){if(r.role!==`assistant`)continue;let e=ht(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 ln(e,t){let n=D(e),r=e=>{let t=S(`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=A(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 un(e,t){let n=D(e),r=async e=>{try{let{stdout:t}=await sn(`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 it(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 dn(e){return[...e].sort((e,t)=>t.savedAt-e.savedAt)}function fn(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 pn(e,t,n){let r=Date.now();return{id:`${r.toString(36)}-${Math.random().toString(36).slice(2,6)}`,name:fn(e,n),text:t,savedAt:r}}function mn(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:$e(t,n,e.session.getTurnCount()??t.filter(e=>e.role===`user`).length)}function hn(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?N.t(`cmd.titleSessionResumed`):N.t(`cmd.titleSession`),t.replace(/^↻ /,``)),gn({session:r,projState:i,tui:a,chatMsgs:o})}function gn(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(N.t(`cmd.titleSession`),N.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(Ye(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?cn(e,t.toolCallId,n):{};return r.oldContent===void 0&&r.newContent===void 0&&(r=ln(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(dn(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 _n(e){return R.get(e)}function z(e){R.delete(e);let t=V.get(e);t&&(clearTimeout(t),V.delete(e))}function vn(){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 yn(e,t){let n=R.get(e);n&&(n.transcript=I(t),n.lastActivityAt=Date.now())}const bn=new Set;function xn(e){return bn.add(e),()=>{bn.delete(e)}}const V=new Map;function Sn(e){let t=V.get(e.id);t&&clearTimeout(t),V.set(e.id,setTimeout(()=>{V.delete(e.id);for(let t of bn)t(e)},300))}function Cn(e,t){let n=``,r=t=>{e.status!==t&&(e.status=t,Sn(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`),yn(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(),Sn(e);return}},()=>e]}function wn(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 Tn(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${wn(s)}`}]}),t.tui.info.showToast(`/session inspect`,`已查看会话 ${s.session.id}(只读快照;如需实时参与该会话请用 otto --attach ${s.session.id})`)}function En(e){let t=e.trim(),n=(t.split(`
5
- `,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 Dn=e=>`把下面的笔记归纳成一个简短标题(≤6 词)和一句话描述。严格只按此格式输出:\nTITLE: <标题>\nDESC: <一句话描述>\n\n笔记:\n${e}`;function On(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 kn(e,t,n=8e3){let r=En(e);if(!t)return r;let i=new AbortController,a=setTimeout(()=>i.abort(),n);a.unref?.();try{let n=On(await t(Dn(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 An(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 jn(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=En(i);await r.record(e),o(`/memory user`,`ok`,N.t(`cmd.memoryUserSaved`,{name:e.name}));return}let a=r.getInjection().trim();t.tui.modal.openModal({kind:`memory`,projectIndex:``,userIndex:a,...An(n,r)});return}if(i===`project`){let e=n?n.getInjection().trim():``;t.tui.modal.openModal({kind:`memory`,projectIndex:e,userIndex:``,...An(n,r)});return}if(i===`forget`){let t=e.slice(1).join(` `).trim();if(!t){o(`/memory forget`,`warn`,N.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?N.t(`cmd.memoryDeleted`,{name:t}):N.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`,N.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,...An(n,r)})}async function Mn(e,t){let n=N.t(`cmd.titleCompact`);if((e[0]??``).toLowerCase()===`log`){t.tui.panes.togglePane(`compactionLog`);return}if(!t.app.storage.memory){t.tui.info.showToast(n,N.t(`compact.unavailable`));return}t.tui.info.showToast(n,N.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,N.t(`compact.edResult`,{before:e.before,after:e.after})),t.callbacks.onContextCompacted()):t.tui.info.showToast(n,N.t(`compact.noop`))}catch(e){t.tui.info.showToast(n,N.t(`cmd.compactFailed`,{msg:e instanceof Error?e.message:String(e)}))}finally{t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!1})}}async function Nn(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=Gt({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(N.t(`cmd.titleCleared`),N.t(`cmd.clearedDone`))}async function Pn(e,t){let n=e.join(` `).replace(/\s+/g,` `).trim();if(!n){t.tui.info.showToast(`/rename`,`Usage: /rename <new title>`);return}t.state.session.renameSession(n),t.tui.lifecycle.setTerminalTitle(n),t.tui.stores.tasks.setSessionTitle(n),t.tui.info.showToast(`✎`,n)}async function Fn(e,t){let n,r,i=!1;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,N.t(`cmd.titleResume`),N.t(`cmd.resumeAlreadyOn`));return}let n=t.app.getSession(e)??await t.app.sessionManager.restore(e);if(!n){l(t,N.t(`cmd.titleResume`),N.t(`cmd.resumeSessionNotFound`,{idShort:e.slice(0,8)}));return}let r=t.state.session;if(t.state.session.isBusy){let[e]=Cn(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 Dt(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=_n(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,N.t(`cmd.titleResume`),N.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,N.t(`cmd.titleResume`),N.t(`cmd.sessionNoMatch`,{arg:n}));return}if(c.length===0){l(t,N.t(`cmd.titleResume`),N.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()||N.t(`cmd.resumeDefaultPinGroup`):N.t(`cmd.resumeRecentGroup`)}function g(e){if(!e)return``;let t=Math.max(0,Math.floor((Date.now()-e.getTime())/1e3));return t<10?N.t(`cmd.agoJustNow`):t<60?N.t(`cmd.agoSeconds`,{n:t}):t<3600?N.t(`cmd.agoMinutes`,{n:Math.floor(t/60)}):t<86400?N.t(`cmd.agoHours`,{n:Math.floor(t/3600)}):N.t(`cmd.agoDays`,{n:Math.floor(t/86400)})}let _=c[0]?.updatedAt?g(c[0].updatedAt):`—`,v=c.reduce((e,t)=>e+(t.messageCount??0),0),ee=r?` [workspace: ${r}]`:``,y=[!i&&s>0?N.t(`cmd.resumeArchivedHiddenHint`,{count:s}):``].filter(Boolean),b=y.length>0?` ${y.join(` `)}`:``,te=new Map(vn().map(e=>[e.id,e])),x=0,S=0,ne=e=>{if(e.id===d)return``;let n=te.get(e.id);return n?n.status===`busy`?(x++,`● ${N.t(`cmd.resumeStatusBusy`)} · `):n.status===`needs-input`?(S++,`● ${N.t(`cmd.resumeStatusNeedsInput`)} · `):`· ${N.t(`cmd.resumeStatusIdle`)} · `:t.app.getSession(e.id)?.isBusy?(x++,`● ${N.t(`cmd.resumeStatusBusy`)} · `):``},C=[x>0?`${x} ${N.t(`cmd.resumeStatusBusy`)}`:``,S>0?`${S} ${N.t(`cmd.resumeStatusNeedsInput`)}`:``].filter(Boolean).join(`, `),w=C?` · ${C}`:``,T=N.t(`cmd.resumeSubtitle`,{sessions:c.length,msgs:v,recent:_})+w+b,re=i?N.t(`cmd.resumeArchivedOnlyTitle`,{n:c.length}):N.t(`cmd.resumeSelectTitle`,{n:c.length});t.tui.modal.openModal({kind:`select`,title:re+ee,subtitle:T,searchable:!0,maxVisible:13,options:m.map(e=>{let t=e.id===d?`●`:` `,n=e.pinned?N.t(`cmd.resumePinnedPrefix`):``,r=e.title||e.id.slice(0,8),i=e.status===`archived`?N.t(`cmd.resumeArchivedSuffix`):``,a=e.writeLocked?N.t(`cmd.resumeReadOnlySuffix`):``,o=`${n}${r}${i}`,s=g(e.updatedAt),c=[ne(e).trim(),s,N.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,N.t(`cmd.titleResume`),N.t(`cmd.resumeFailed`,{msg:e instanceof Error?e.message:String(e)})))},onCancel:()=>{}})}async function In(e,t){t.app.reloadCapabilities().then(e=>{t.tui.plugins.setPluginRegistrations(t.app.getPluginRegistrations()),t.tui.info.showToast(N.t(`cmd.titleReload`),N.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:N.t(`cmd.reloadFailed`,{msg:e instanceof Error?e.message:String(e)})}))}async function Ln(e,t){let n=t.app.diagnoser.propose();if(n.length===0){t.tui.info.showToast(N.t(`cmd.titleDiagnose`),N.t(`cmd.diagnoseNone`));return}let r=n.map((e,t)=>N.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:N.t(`cmd.diagnoseSummary`,{count:n.length}),detail:r.join(`
6
- `)})}async function Rn(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(N.t(`cmd.titleArchive`),N.t(`cmd.sessionNoMatch`,{arg:n}));return}if(r.status===`archived`){let e=t.app.getSession(r.id);if(!e){t.tui.info.showToast(N.t(`cmd.titleUnarchive`),N.t(`cmd.unarchiveNotLoaded`,{idShort:r.id.slice(0,8)}));return}e.unarchive(),t.tui.info.showToast(N.t(`cmd.titleUnarchive`),N.t(`cmd.unarchiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}));return}if(!await t.app.archiveSession(r.id)){t.tui.info.showToast(N.t(`cmd.titleArchive`),N.t(`cmd.archiveCannot`,{idShort:r.id.slice(0,8)}));return}t.tui.info.showToast(N.t(`cmd.titleArchive`),N.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(N.t(`cmd.titleUnarchive`),N.t(`cmd.unarchiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}));return}r.archive(),t.tui.info.showToast(N.t(`cmd.titleArchive`),N.t(`cmd.archiveDone`,{idShort:r.id.slice(0,8),title:r.title??``}))}async function zn(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(N.t(`cmd.titlePin`),N.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(N.t(`cmd.titleUnpin`),N.t(`cmd.unpinDone`,{idShort:e.id.slice(0,8),title:e.title??``}))):(e.pin(),t.tui.info.showToast(N.t(`cmd.titlePin`),N.t(`cmd.pinDone`,{idShort:e.id.slice(0,8),title:e.title??``}))),H(t);return}if(r.length===0){Bn(t.state.session.id,n,t),H(t);return}if(r.length===1){Bn(r[0],n,t),H(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(N.t(`cmd.titlePin`),N.t(`cmd.pinBatchSummary`,{seg:o.length>0?`${a} pinned (${o.length} not found: ${o.join(`, `)})`:`${a} pinned`})),H(t)}function H(e){let t=e.callbacks.refreshSlashCommands();e.tui.plugins.setCommands(t)}function Bn(e,t,n){if(e===n.state.session.id){Vn(n.state.session,t,n);return}let r=n.app.listSessions(),i=r.find(t=>t.id===e)??r.find(t=>t.id.startsWith(e))??r.find(t=>t.id.includes(e));if(!i){n.tui.info.showToast(N.t(`cmd.titlePin`),N.t(`cmd.sessionNoMatch`,{arg:e}));return}let a=n.app.getSession(i.id);if(!a){n.tui.info.showToast(N.t(`cmd.titlePin`),N.t(`cmd.pinNotLoaded`,{idShort:i.id.slice(0,8)}));return}Vn(a,t,n)}function Vn(e,t,n){let r=e.id.slice(0,8),i=e.title??``;if(e.pinned){if(t===void 0||(e.pinGroup??``).toLowerCase()===t.toLowerCase()){e.unpin(),n.tui.info.showToast(N.t(`cmd.titleUnpin`),N.t(`cmd.unpinDone`,{idShort:r,title:i}));return}e.pin(t),n.tui.info.showToast(N.t(`cmd.titlePin`),N.t(`cmd.pinGroupDone`,{idShort:r,title:i,group:t}));return}e.pin(t),t===void 0?n.tui.info.showToast(N.t(`cmd.titlePin`),N.t(`cmd.pinDone`,{idShort:r,title:i})):n.tui.info.showToast(N.t(`cmd.titlePin`),N.t(`cmd.pinGroupDone`,{idShort:r,title:i,group:t}))}async function Hn(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=Gt({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`})}async function U(e,t){let n=e[0];if(n===`fork`){await Un(e.slice(1),t);return}if(n===`kill`){await Jn(e.slice(1),t);return}if(n===`pin`||n===`unpin`){await zn(e.slice(1),t);return}if(n===`archive`||n===`unarchive`){await Rn(e.slice(1),t);return}if(n===`resume`){await Fn(e.slice(1),t);return}if(n===`compact`){await Mn(e.slice(1),t);return}if(n===`context`){await Hn(e.slice(1),t);return}if(n===`inspect`){await Tn(e.slice(1),t);return}if(n!==`unlock`){t.tui.info.showToast(N.t(`cmd.titleSessionCmd`),`Usage: /session fork | unlock <id> [--force] | kill <id> | inspect <id> | pin [<id>...] | archive [<id>] | resume [<id>] | compact | context`);return}let r=e.slice(1),i=r.includes(`--force`),a=r.find(e=>e!==`--force`);if(!a){t.tui.info.showToast(N.t(`cmd.titleSessionUnlock`),N.t(`cmd.unlockUsage`));return}let o=t.app.sessionManager.inspectSessionWriteLease(a),s=a.slice(0,8);if(!o.locked){t.tui.info.showToast(N.t(`cmd.titleSessionUnlock`),N.t(`cmd.unlockNotLocked`,{idShort:s}));return}let c=o.alive===!0?N.t(`cmd.unlockAliveConfirmed`):o.alive===!1?N.t(`cmd.unlockDeadConfirmed`):N.t(`cmd.unlockUnknownAlive`),l=Math.round((o.mtimeAgoMs??0)/1e3);if(!i){t.tui.messages.pushMessage({role:`command_echo`,command:`/session unlock`,summary:N.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:N.t(`cmd.unlockHungWarning`,{idShort:s})}),t.tui.modal.openModal({kind:`confirm`,title:N.t(`cmd.unlockConfirmTitle`),message:N.t(`cmd.unlockConfirmMessage`,{idShort:s,pid:o.pid,hostname:o.hostname}),confirmLabel:N.t(`cmd.unlockConfirmLabel`),cancelLabel:N.t(`cmd.unlockCancelLabel`),dangerous:!0,onConfirm:()=>{t.app.sessionManager.forceReleaseSessionWriteLease(a),t.tui.info.showToast(N.t(`cmd.titleSessionUnlock`),N.t(`cmd.unlockForcedDone`,{idShort:s}))},onCancel:()=>{t.tui.info.showToast(N.t(`cmd.titleSessionUnlock`),N.t(`cmd.unlockCancelled`))}});return}(o.mtimeAgoMs??0)<5e3&&t.tui.messages.pushMessage({role:`command_echo`,command:`/session unlock --force`,status:`warn`,summary:N.t(`cmd.unlockRecentReleaseHint`,{idShort:s})}),t.app.sessionManager.forceReleaseSessionWriteLease(a),t.tui.info.showToast(N.t(`cmd.titleSessionUnlock`),N.t(`cmd.unlockForcedDone`,{idShort:s}))}async function Un(e,t){let n=t.state.session.id,r=await t.app.sessionManager.forkSession(n);if(!r){t.tui.info.showToast(N.t(`cmd.titleSessionFork`),N.t(`cmd.forkFailed`));return}let i=t.state.session;if(t.state.session.isBusy){let[e]=Cn(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 Dt(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(N.t(`cmd.titleSessionFork`),N.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 Gn(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=O(o,`trace`),d=[];for(let e of l){let t=O(u,`${encodeURIComponent(e.id)}.jsonl`);try{let n=await ot(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} | 预估回收: ${Kn(e)}`,i=[`会话 ID 大小 最后活跃 标题`,...d.map(e=>` ${e.session.id.slice(0,8)} ${Kn(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(`
7
- `)});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 st(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 文件,回收 ${Kn(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 Kn(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 qn(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??O(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 Jn(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`,N.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 Yn(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(N.t(`cmd.titleSessionFork`),N.t(`cmd.forkFailed`));return}let a=`${r} (fork)`,o=(await t.tui.modal.openModal({kind:`input`,title:N.t(`cmd.forkNameTitle`),placeholder:a,defaultValue:a})??``).trim()||a;i.renameSession(o);let s=t.state.session;if(t.state.session.isBusy){let[e]=Cn(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 Dt(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(N.t(`cmd.titleSessionFork`),N.t(`cmd.forkSuccessNamed`,{title:o}))}function Xn(e){switch(e){case`global`:return N.t(`cmd.scopeGlobal`);case`repository`:return N.t(`cmd.scopeRepository`);default:return N.t(`cmd.scopeProject`)}}function Zn(e,t,n){return{workspaceDir:e.app.workspaceDir,workspaceRoot:t===`repository`?me(e.app.workspaceDir):void 0,global:t===`global`,dryRun:n}}async function Qn(e){let{name:t,type:n,scope:r,ctx:i,onDone:a}=e,o=i.app.settings.get(`mcp_servers`),s=await je(t,n,Zn(i,r,!0),()=>o,async()=>{});if(!s.success){i.tui.info.showToast(N.t(`cmd.titleUninstall`),N.t(`cmd.uninstallFailed`,{err:s.error??N.t(`cmd.unknownError`)})),a?.();return}let c=s.plan??[];i.tui.modal.openModal({kind:`confirm`,title:N.t(`cmd.uninstallConfirmTitle`,{type:n,name:t}),message:[N.t(`cmd.uninstallConfirmScope`,{scopeLabel:Xn(r)}),...c].join(`
8
- `),confirmLabel:N.t(`cmd.uninstallConfirmYes`),dangerous:!0,onConfirm:()=>{$n(e)},onCancel:()=>a?.()})}async function $n(e){let{name:t,type:n,scope:r,ctx:i,onDone:a}=e,o=i.app.settings.get(`mcp_servers`),s=await je(t,n,Zn(i,r,!1),()=>o,async e=>{await i.app.settings.persist({mcp_servers:e})});if(!s.success){i.tui.info.showToast(N.t(`cmd.titleUninstall`),N.t(`cmd.uninstallFailed`,{err:s.error??N.t(`cmd.unknownError`)})),a?.();return}i.tui.info.showToast(N.t(`cmd.titleUninstall`),N.t(`cmd.uninstalled`,{type:n,name:t,scope:Xn(r)})),n===`plugin`&&await Ce(i.app.settings,t);try{await i.app.reloadCapabilities(),i.tui.plugins.setPluginRegistrations(i.app.getPluginRegistrations()),n===`plugin`&&i.app.pluginModuleManager.emitMonitorEvent({type:`plugin.uninstalled`,pluginId:t}),i.tui.info.showToast(N.t(`cmd.titleUninstall`),N.t(`cmd.uninstallRefreshed`))}catch(e){i.tui.messages.pushMessage({role:`command_echo`,command:`/extension`,status:`error`,summary:N.t(`cmd.uninstalledRefreshErr`,{err:e instanceof Error?e.message:String(e)})})}a?.()}async function er(e,t){let n=t.app.settings.get(`keybinding_overrides`),r=()=>{t.tui.info.showToast(N.t(`cmd.keybindTitle`),N.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 tr(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 nr(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 rr(e,t){nr(e,`model`,t)}function ir(e,t){nr(e,`effort`,t)}function ar(e,t){tr(e,`retry.queued`,{attempt:t.attempt,max:t.max,...t.mode===void 0?{}:{mode:t.mode},...t.reason===void 0?{}:{reason:t.reason}})}function or(e,t){tr(e,`retry.cancelled`,{attempt:t.attempt})}function sr(e){tr(e,`retry.reset`,{})}function cr(e,t,n){tr(e,`pause.${t}`,{...n===void 0?{}:{source:n}})}const lr=(e,t,n)=>{let r=Xt(n),i=r?`${e}·${r}`:e;return t?`${i} (${t>=1e6?`${(t/1e6).toFixed(1)}M`:`${Math.round(t/1e3)}K`})`:i},W=[`low`,`medium`,`high`,`xhigh`,`max`];function ur(e,t){return[t,...e.filter(e=>e!==t)].slice(0,5)}function dr(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 fr(e,t){let n=dr(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 pr(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 mr(e,t){let n=pr(e),r=n.levels.at(-1);return r&&(W.includes(r)?r!==t.currentEffort&&t.applyEffort(r):t.onInvalidLevel?.(r)),n.text}function hr(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=ur(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),rr({tui:i.value??{messages:{pushMessage:()=>{}}},session:f,traceStore:o.storage.traceStore},{from:p,to:m.id,label:lr(m.id,m.contextWindow,f.thinkingLevel)})),m.api.includes(`:`)&&o.firePluginActivationEvent?.(`onProvider:${m.api}`),u?.({kind:`setModel`,modelId:e}),i.value?.stores.tasks.setModelName(lr(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(N.t(`cmd.titleModel`),N.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(N.t(`cmd.titleModel`),N.t(`model.switchedTo`,{label:l(e)})),`Model → ${e} (active next turn).`}return f.model&&(i.value?.stores.tasks.setModelName(lr(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 gr(e){let{getSession:t,app:n,tuiRef:r,options:i,fmtDisplayModel:a,applyModel:o}=e,s=!1,c=P(n.authStore,`delegation`),l=P(n.authStore,`main-session`);return async()=>{if(s)return`proceed`;s=!0;let u=t().model;if(!u)return`proceed`;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`proceed`;let m=n.modelRegistry.find(p);if(m&&await f(m))return m.id!==u.id&&await o(m.id),`proceed`;let h=m?N.t(`model.reasonUnauthenticated`,{provider:m.provider}):N.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;return r.value?await new Promise(t=>{r.value?.modal.openModal({kind:`confirm`,title:N.t(`model.title`),message:[`${a(p)} → ${a(g.id)}`,``,h,``,N.t(`model.hint`)],confirmLabel:N.t(`model.permanent`),extraLabel:N.t(`model.login`),cancelLabel:N.t(`model.dismiss`),onConfirm:()=>{o(_,{persist:!0}).then(()=>t(`proceed`),()=>t(`proceed`))},onExtra:()=>{e.onLogin&&m?.provider?e.onLogin(m.provider):r.value?.info.showToast(N.t(`model.login`),N.t(`model.fallbackLoginToast`,{provider:m?.provider??``})),t(`abort`)},onCancel:()=>{e.onExitSession?.(),t(`abort`)}})}):`proceed`}}function _r(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 vr(e){let t=e.trim().split(`
13
- `)[0].replace(/\s+/g,` `).trim();return t.length>40?`${t.slice(0,39)}…`:t}function yr(e){e.pluginInput.unregisterBySource(`shortcut`);let t=(e.settings.get(`shortcuts`)??[]).map(e=>({label:`@${e.name}`,value:`[@shortcut:${e.name.replace(/]/g,`\\]`)}]`,description:vr(e.text),kind:`shortcut`,source:`shortcut`}));t.length&&e.pluginInput.register(t)}function br(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 xr={low:`cmd.effortDescLow`,medium:`cmd.effortDescMedium`,high:`cmd.effortDescHigh`,xhigh:`cmd.effortDescXhigh`,max:`cmd.effortDescMax`};function Sr(e){let t=W.map(e=>({label:Xt(e),value:`[@effort:${e}]`,description:N.t(xr[e]??`cmd.effortDescLow`),kind:`effort`,source:`builtin-effort`}));e.pluginInput.unregisterBySource(`builtin-effort`),e.pluginInput.register(t)}async function Cr(e,t){t.tui.modal.openModal({kind:`shortcutsPanel`,shortcuts:t.app.getShortcuts(),onSave:(e,n,r)=>{t.app.saveShortcut(e,n,r).then(()=>yr(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(()=>yr(t.app)).catch(e=>{t.tui.info.showToast(`Shortcuts`,`Delete failed: ${e instanceof Error?e.message:String(e)}`)})}})}const wr={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 Tr(e){let t=Math.round(e*8);return`━`.repeat(Math.max(0,t))+`╌`.repeat(Math.max(0,8-t))}async function Er(e,t){let n=e[0]?.toLowerCase();if(n&&W.includes(n)){Dr(t,n);return}if(n){t.tui.info.showToast(N.t(`cmd.titleEffort`),N.t(`cmd.effortUnknown`,{arg:n,levels:W.join(` / `)}));return}let r=t.state.session.thinkingLevel;t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.selectEffortTitle`),options:W.map(e=>{let t=wr[e],n=e===r,i=Tr(t.intensity);return{label:t.label,value:e,detail:`${i} ${t.desc}${n?` · 当前`:``}`}}),onSelect:e=>Dr(t,e),onCancel:()=>{}})}function Dr(e,t){let n=e.state.session,r=n.thinkingLevel;n.thinkingLevel=t,e.app.settings.persist({thinking_level:t}),r!==t&&ir({tui:e.tui,session:n,traceStore:e.app.storage.traceStore},{from:r,to:t,label:Xt(t)}),n.model?.id&&e.tui.stores.tasks.setModelName(F(e.app,n.model.id,t)),e.tui.info.showToast(N.t(`cmd.titleEffort`),t)}async function G(e,t){let n=e[0]?.toLowerCase();if(n===`general`||n===`gen`){K(t);return}if(n===`lang`||n===`language`){zr(e.slice(1),t);return}if(n===`theme`){Br(e.slice(1),t);return}if(n===`keybindings`||n===`kb`){er(e.slice(1),t);return}if(n===`shortcuts`){Cr(e.slice(1),t);return}if(n===`effort`){Er(e.slice(1),t);return}if(n===`proxy`){s(e.slice(1),t);return}if(n){t.tui.info.showToast(N.t(`cmd.titlePreference`),N.t(`cmd.preferenceUsage`));return}Or(t)}function Or(e,t){let n=e.app.settings,r=n.get(`language`),i=r===`zh`?`中文 (zh)`:r===`en`?`English (en)`:`Auto`,a=e.state.themeRegistry??qe(),o=n.get(`theme_preset`)??{},c=a.get(o.dark??`dark`)?.label??o.dark??`dark`;e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.titlePreference`),detailPlacement:`inline`,options:[{label:N.t(`cmd.prefOptionGeneral`),value:`general`,detail:N.t(`cmd.prefDescGeneral`)},{label:N.t(`cmd.prefOptionLang`),trailingLabel:i,value:`lang`,detail:N.t(`cmd.prefDescLang`)},{label:N.t(`cmd.prefOptionTheme`),trailingLabel:c,value:`theme`,detail:N.t(`cmd.prefDescTheme`)},{label:`Keybindings`,value:`keybindings`,detail:`Browse, search, remap, reset shortcuts`},{label:`Shortcuts`,value:`shortcuts`,detail:`Manage custom @ text shortcuts`},{label:`Effort`,value:`effort`,detail:`Switch reasoning effort (low|medium|high|xhigh|max)`},{label:`Proxy`,value:`proxy`,detail:`Configure HTTP proxy`}],defaultSelectedValue:t,onSelect:t=>{t===`general`?K(e):t===`lang`?zr([],e):t===`theme`?Br([],e):t===`keybindings`?er([],e):t===`shortcuts`?Cr([],e):t===`effort`?Er([],e):t===`proxy`&&s([],e)},onCancel:()=>{}})}let kr;function K(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===C),f={on:M.toggleOn,off:M.toggleOff},p={on:N.t(`cmd.toggleOn`),off:N.t(`cmd.toggleOff`)},m=e=>Zt(e,f,p);e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.selectGeneralTitle`),detailPlacement:`inline`,subtitle:t,replace:r,options:[{label:N.t(`cmd.genNickname`),trailingLabel:o||`—`,value:`nickname`,detail:N.t(`cmd.genNicknameDesc`)},{label:N.t(`cmd.genCompletionNotice`),trailingLabel:m(s),value:`completion`,detail:N.t(`cmd.genCompletionNoticeDesc`)},{label:N.t(`cmd.genSound`),trailingLabel:m(c),value:`sound`,detail:N.t(`cmd.genSoundDesc`)},{label:N.t(`cmd.genUpdateCheck`),trailingLabel:m(l),value:`updateCheck`,detail:N.t(`cmd.genUpdateCheckDesc`)},{label:N.t(`cmd.genSkillLoop`),trailingLabel:d?m(u):N.t(`cmd.genSkillLoopMissing`),value:`skillLoopPanel`,detail:N.t(`cmd.genSkillLoopEntryDesc`)}],defaultSelectedValue:n??kr,onHighlight:e=>{kr=e},onSelect:t=>{if(t===`nickname`){Ar(e);return}if(t===`skillLoopPanel`){q(e);return}Rr(e,t)},onCancel:()=>{Or(e,`general`)}})}async function Ar(e){let t=await e.tui.modal.openModal({kind:`input`,title:N.t(`cmd.genNicknameInputTitle`),placeholder:N.t(`cmd.genNicknamePlaceholder`)});if(t==null){K(e);return}let n=t.trim();await e.app.settings.persist({nickname:n}),K(e,N.t(`cmd.genSaved`))}const jr=[4,6,12,20];function Mr(e){let t=typeof e==`number`?e:6,n=jr.includes(t)?`genSkillLoopThr${t}`:``;return n?N.t(`cmd.${n}`):String(t)}function Nr(e){let t=e.app.settings,n=t.get(`skill_loop`)?.min_messages??6;e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.genSkillLoopThresholdTitle`),detailPlacement:`inline`,options:jr.map(e=>({label:N.t(`cmd.genSkillLoopThr${e}`),value:String(e),detail:N.t(`cmd.genSkillLoopThr${e}Desc`),trailingLabel:e===n?M.toggleOn:void 0})),onSelect:n=>{(async()=>{let r={...t.get(`skill_loop`)??{}};r.min_messages=Number(n),await t.persist({skill_loop:r}),q(e,N.t(`cmd.genSaved`),`threshold`)})()},onCancel:()=>{q(e,void 0,`threshold`)}})}const Pr=[3,14,30,365];function Fr(e){let t=typeof e==`number`?e:14;return Pr.includes(t)?N.t(`cmd.genSkillLoopCd${t}`):N.t(`cmd.genSkillLoopCdDays`,{n:t})}function Ir(e){let t=e.app.settings,n=t.get(`skill_loop`)?.dismiss_cooldown_days??14;e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.genSkillLoopCooldownTitle`),detailPlacement:`inline`,options:Pr.map(e=>({label:N.t(`cmd.genSkillLoopCd${e}`),value:String(e),detail:N.t(`cmd.genSkillLoopCd${e}Desc`),trailingLabel:e===n?M.toggleOn:void 0})),onSelect:n=>{(async()=>{let r={...t.get(`skill_loop`)??{}};r.dismiss_cooldown_days=Number(n),await t.persist({skill_loop:r}),q(e,N.t(`cmd.genSaved`),`cooldown`)})()},onCancel:()=>{q(e,void 0,`cooldown`)}})}function q(e,t,n){let r=e.app.settings,i=r.get(`skill_loop`)?.enabled===!0,a=e.app.activePlugins().some(e=>e.id===C),o={on:M.toggleOn,off:M.toggleOff},s={on:N.t(`cmd.toggleOn`),off:N.t(`cmd.toggleOff`)};if(!a){e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.skillLoopPanelTitle`),detailPlacement:`inline`,subtitle:N.t(`cmd.genSkillLoopMissingHint`),options:[{label:N.t(`cmd.genSkillLoopMissing`),value:`noop`,detail:``}],onSelect:()=>{K(e,void 0,`skillLoopPanel`)},onCancel:()=>{K(e,void 0,`skillLoopPanel`)}});return}e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.skillLoopPanelTitle`),detailPlacement:`inline`,subtitle:t,defaultSelectedValue:n,options:[{label:N.t(`cmd.skillLoopOnOff`),trailingLabel:Zt(i,o,s),value:`toggle`,detail:N.t(`cmd.genSkillLoopEntryDesc`)},...i?[{label:N.t(`cmd.genSkillLoopThreshold`),trailingLabel:Mr(r.get(`skill_loop`)?.min_messages),value:`threshold`,detail:N.t(`cmd.genSkillLoopThresholdDesc`)},{label:N.t(`cmd.genSkillLoopCooldown`),trailingLabel:Fr(r.get(`skill_loop`)?.dismiss_cooldown_days),value:`cooldown`,detail:N.t(`cmd.genSkillLoopCooldownDesc`)},{label:N.t(`cmd.genSkillLoopStatus`),value:`status`,detail:N.t(`cmd.genSkillLoopStatusDesc`)}]:[]],onSelect:t=>{if(t===`threshold`){Nr(e);return}if(t===`cooldown`){Ir(e);return}if(t===`status`){Lr(e);return}(async()=>{let t={...r.get(`skill_loop`)??{}},n=t.enabled!==!0;t.enabled=n,await r.persist({skill_loop:t}),q(e,n?N.t(`cmd.genSkillLoopOn`):N.t(`cmd.genSkillLoopOff`),`toggle`)})()},onCancel:()=>{K(e,void 0,`skillLoopPanel`)}})}function Lr(e){let t=e.app.settings,n=e.app.activePlugins().some(e=>e.id===C),r=xe({workspaceKey:e.app.workspaceRef?.key??ne,now:Date.now(),cooldownDays:t.get(`skill_loop`)?.dismiss_cooldown_days,pluginInstalled:n}),i=e=>N.t(`cmd.skillLoopStatusCount`,{n:e}),a=[];if(!n)a.push({label:N.t(`cmd.skillLoopStatusNotInstalled`),value:`noop`,detail:N.t(`cmd.genSkillLoopMissingHint`)});else{a.push({label:N.t(`cmd.skillLoopStatusEpisodes`),trailingLabel:i(r.episodeCount),value:`noop`,detail:N.t(`cmd.skillLoopStatusSuccess`)+` `+i(r.successCount)},{label:N.t(`cmd.skillLoopStatusPending`),trailingLabel:i(r.pendingCount),value:`noop`,detail:i(r.candidateCount)+` `+N.t(`cmd.skillLoopStatusCandidates`)+` · `+i(r.coolingCount)+` `+N.t(`cmd.skillLoopStatusCooling`)});for(let e of r.pending)a.push({label:e.taskSignature,trailingLabel:N.t(`cmd.skillLoopStatusTimes`,{n:e.size}),value:`noop`,detail:N.t(`cmd.skillLoopStatusGroupPending`)});for(let e of r.recentSignatures)a.push({label:e,value:`noop`,detail:N.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:N.t(`cmd.skillLoopStatusTitle`),detailPlacement:`inline`,subtitle:o?N.t(o):void 0,options:a,onSelect:()=>{q(e,void 0,`status`)},onCancel:()=>{q(e,void 0,`status`)}})}async function Rr(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}),K(e,N.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}),K(e,N.t(`cmd.genSaved`),t,!0)}function zr(e,t){let n=e[0]?.toLowerCase();if(n===`en`||n===`zh`||n===`auto`){Ur(t,n);return}if(n){t.tui.info.showToast(N.t(`cmd.titlePreference`),N.t(`pref.languageUsage`));return}t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.selectLanguageTitle`),detailPlacement:`inline`,options:[{label:`中文 (zh)`,value:`zh`,detail:N.t(`cmd.langDescZh`)},{label:`English (en)`,value:`en`,detail:N.t(`cmd.langDescEn`)},{label:`Auto`,value:`auto`,detail:N.t(`cmd.langDescAuto`)}],onSelect:e=>Ur(t,e),onCancel:()=>{Or(t,`lang`)}})}function Br(e,t){Vr(t)}function Vr(e){let t=e.state.themeRegistry??qe(),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:N.t(`cmd.prefOptionTheme`),detailPlacement:`inline`,options:[{label:N.t(`cmd.themeDarkPresetOption`),value:`preset-dark`,detail:N.t(`cmd.themeDarkPresetDesc`),trailingLabel:r?.label},{label:N.t(`cmd.themeLightPresetOption`),value:`preset-light`,detail:N.t(`cmd.themeLightPresetDesc`),trailingLabel:i?.label}],onSelect:t=>{if(t===`preset-dark`){Hr(e,`dark`);return}if(t===`preset-light`){Hr(e,`light`);return}},onCancel:()=>{Or(e,`theme`)}})}function Hr(e,t){let n=e.state.themeRegistry??qe(),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`?N.t(`cmd.themePresetBuiltin`):N.t(`cmd.themePresetFromExtension`,{id:e.source.extensionId}),trailingLabel:e.id===i?`✓`:void 0})),{label:N.t(`cmd.themePresetReset`),value:`__reset__`,detail:N.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`?N.t(`cmd.themePresetTitleDark`):N.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(N.t(`cmd.titlePreference`),N.t(`cmd.themePresetSaved`,{label:s??a??t}))},onCancel:()=>{s(),e.tui.info.showToast(N.t(`cmd.titlePreference`),N.t(`cmd.selectCancelled`))}})}function Ur(e,t){e.state.currentLang=e.tui.lifecycle.setLanguage(t),kt(t),e.tui.plugins.setCommands(e.callbacks.refreshSlashCommands()),e.app.settings.persist({language:t}),e.tui.info.showToast(N.t(`cmd.titleLanguage`),N.t(`pref.languageSwitched`,{l:e.state.currentLang,name:e.state.currentLang===`zh`?`中文`:`English`}))}async function Wr(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(N.t(`cmd.titlePlugin`),N.t(`cmd.pluginUsage`,{seg:(i?`untrust`:`trust`)==`untrust`?`untrust `:``}));return}let o=n({cwd:r,homedir:_()}).find(e=>e.id===a);if(!o){t.tui.info.showToast(N.t(`cmd.titlePlugin`),N.t(`cmd.pluginNotFound`,{id:a}));return}if(i){try{Me(o.dir)}catch(e){t.tui.info.showToast(N.t(`cmd.titlePlugin`),`撤销信任失败,权限未收回:${e instanceof Error?e.message:String(e)}`);return}t.tui.info.showToast(N.t(`cmd.titlePlugin`),N.t(`cmd.pluginUntrusted`,{id:a}))}else oi(t,o);return}if(i===`trust`){Ae(r),t.tui.info.showToast(N.t(`cmd.titleCompat`),N.t(`cmd.compatTrusting`)),t.app.reloadCapabilities().then(e=>{t.tui.plugins.setPluginRegistrations(t.app.getPluginRegistrations()),t.tui.info.showToast(N.t(`cmd.titleCompat`),N.t(`cmd.compatTrusted`,{count:e.mcpTools}))},e=>t.tui.info.showToast(N.t(`cmd.titleCompat`),N.t(`cmd.compatReloadFailed`,{err:e instanceof Error?e.message:String(e)})));return}if(i===`untrust`){Ne(r),t.tui.info.showToast(N.t(`cmd.titleCompat`),N.t(`cmd.compatUntrusted`));return}let a=fe(r),o=ce(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?N.t(`cmd.compatTrustedLabel`):N.t(`cmd.compatUntrustedLabel`);s.push(`${e.join(N.t(`cmd.listSep`))} ${t}`)}if(o.highRiskKeys.length>0){let e=o.highRiskKeys.join(N.t(`cmd.listSep`));s.push(o.gated?N.t(`cmd.compatConfigGated`,{keys:e}):N.t(`cmd.compatConfigActive`,{keys:e}))}let c=n({cwd:r,homedir:_()}).filter(e=>e.scope===`project`||e.scope===`repository`);for(let e of c){let t=pe(e);if(!t.surface.any)continue;let n=t.gated?N.t(`cmd.compatUntrustedLabel`):N.t(`cmd.compatTrustedLabel`);s.push(`plugin:${e.id} ${n}${t.gated?` → /trust plugin ${e.id}`:``}`)}if(s.length===0){t.tui.info.showToast(N.t(`cmd.titleCompat`),N.t(`cmd.compatNone`));return}o.gated?t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleCompat`),lines:s}):t.tui.info.showToast(N.t(`cmd.titleCompat`),s.join(`
14
- `))}async function Gr(e,t){let n=e[0];if(n===`clear`){t.app.clearSessionAlwaysAllow(t.state.session.id),t.tui.info.showToast(N.t(`cmd.titlePermissions`),N.t(`cmd.permsCleared`));return}if(n===`add`||n===`remove`){let r=e.slice(1).join(` `).trim();if(!r){t.tui.info.showToast(N.t(`cmd.titlePermissions`),N.t(`cmd.permsManageHint`));return}if(n===`add`){if(!t.app.isWellFormedAllowEntry(r)){t.tui.info.showToast(N.t(`cmd.titlePermissions`),N.t(`cmd.permsInvalidEntry`,{entry:r}));return}await t.app.allowToolAlways(r),t.tui.info.showToast(N.t(`cmd.titlePermissions`),N.t(`cmd.permsAdded`,{entry:r}))}else{let e=await t.app.disallowToolAlways(r);t.tui.info.showToast(N.t(`cmd.titlePermissions`),e?N.t(`cmd.permsRemoved`,{entry:r}):N.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(`, `):N.t(`cmd.permsEmpty`)}`;t.tui.modal.openModal({kind:`permissions`,lines:[a(N.t(`cmd.permsSessionLabel`),r),a(N.t(`cmd.permsProjectLabel`),i),``,N.t(`cmd.permsClearHint`),N.t(`cmd.permsManageHint`)]})}async function Kr(e,n){let r=t();n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeChecking`,{current:r}));let i=await jt(r);if(!i){n.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleUpgrade`),lines:[N.t(`cmd.upgradeNoNetwork`)]});return}if(!i.newer){n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeLatest`,{current:r}));return}n.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleUpgrade`),lines:N.t(`cmd.upgradeAvailableLines`,{returnObjects:!0,current:r,latest:i.latest})})}async function qr(e,n){if(!e.includes(`--force`))return!1;n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgrading`));let r=await jt(t());if(!r)return n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeNoNetwork`)),!0;if(!r.newer)return n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeLatest`,{current:t()})),!0;let{ok:i,error:a}=await Ft(r.latest);return i?(n.state.restartRequested=!0,n.tui.lifecycle.stop(),!0):(n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeFailed`,{err:a??N.t(`cmd.unknownError`)})),!0)}async function Jr(e,t,n){let r=N.t(`cmdDesc`,{returnObjects:!0}),i={session:N.t(`cmd.helpGroupSession`),model:N.t(`cmd.helpGroupModel`),agent:N.t(`cmd.helpGroupAgent`),debug:N.t(`cmd.helpGroupDebug`),ui:N.t(`cmd.helpGroupUi`),other:N.t(`cmd.helpGroupOther`)},a=[];for(let e of Ha){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=`${N.t(`cmd.helpPrefixes`)} !<cmd> ${N.t(`cmd.helpPrefixShell`)} · @<file> ${N.t(`cmd.helpPrefixFile`)}`;t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.titleCommands`),subtitle:o,searchable:!0,options:a,onSelect:e=>{Ka(e,[],t)},onCancel:()=>{}})}async function Yr(e,t){t.tui.panes.togglePane(`history`)}async function Xr(e,t){t.tui.panes.togglePane(`notifications`)}async function Zr(e,t){t.tui.panes.togglePane(`prompts`)}async function Qr(e,t){t.tui.panes.setServices(!0)}async function $r(e,t){t.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeCheckScanning`));try{let e=Oe({workspaceDir:t.app.workspaceDir,workspaceRoot:me(t.app.workspaceDir),scope:`all`});if(e.length===0){t.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeCheckNoVersioned`));return}let n=await ae(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(N.t(`cmd.upgradeCheckLineUpdate`,{tag:t,name:e.name,installed:e.installed,latest:e.latest??``}))):r.push(N.t(`cmd.upgradeCheckLineLatest`,{tag:t,name:e.name,installed:e.installed}))}i>0&&(r.push(``),r.push(N.t(`cmd.upgradeCheckSummary`,{count:i}))),t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleUpgradeCheck`),lines:r})}catch(e){t.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeCheckFailed`,{err:e instanceof Error?e.message:String(e)}))}}var ei=yt({confirmHighRiskCapabilities:()=>si,formatPluginContributionsSummary:()=>ii,handleDelegatesToggle:()=>li,handleExtension:()=>J,handleJobStart:()=>ui,pluginCapabilityLabel:()=>ai,promptPluginTrust:()=>oi,runPluginInstall:()=>ci});function ti(e){return!e.endsWith(O(`.claude`,`skills`))}function ni(e,t){return ti(t)?e===`project`?`project`:e===`global`?`global`:null:null}function ri(e,t){let n={project:`project`,global:`global`,plugin:`plugin`,inline:`inline`}[e]??e;return t?`${n} (${t})`:n}function ii(e){let t=[];return e.providerApis>0&&t.push(`provider(${e.providerApis})`),e.tools>0&&t.push(`tools(${e.tools})`),e.renderers>0&&t.push(`renderers(${e.renderers})`),e.statusItems>0&&t.push(`statusItems(${e.statusItems})`),e.fileViewers&&e.fileViewers>0&&t.push(`fileViewers(${e.fileViewers})`),t.length?t.join(`, `):void 0}function ai(e){switch(e){case`provider`:return N.t(`cmd.pluginCapabilityProvider`);case`tools`:return N.t(`cmd.pluginCapabilityTools`);case`tui.renderer`:return N.t(`cmd.pluginCapabilityTuiRenderer`);case`network`:return N.t(`cmd.pluginCapabilityNetwork`);case`wire-protocol`:return N.t(`cmd.pluginCapabilityWireProtocol`);case`a2ui.component`:return N.t(`cmd.pluginCapabilityA2uiComponent`);case`panel.backend`:return N.t(`cmd.pluginCapabilityPanelBackend`);case`input.resolver`:return N.t(`cmd.pluginCapabilityInputResolver`);case`a2ui.renderer`:return N.t(`cmd.pluginCapabilityA2uiRenderer`);default:return}}function oi(e,t){let n=pe(t),r=n.pendingCapabilities,i=()=>{ke(t.dir),r.length>0&&he(t.dir,r),e.tui.info.showToast(N.t(`cmd.titlePlugin`),N.t(`cmd.pluginTrusting`,{id:t.id})),e.app.reloadCapabilities().then(n=>{e.tui.plugins.setPluginRegistrations(e.app.getPluginRegistrations()),e.tui.info.showToast(N.t(`cmd.titlePlugin`),N.t(`cmd.pluginTrusted`,{id:t.id,count:n.mcpTools}))},t=>e.tui.info.showToast(N.t(`cmd.titlePlugin`),N.t(`cmd.compatReloadFailed`,{err:t instanceof Error?t.message:String(t)})))},a=n.surface;if(!a.any&&r.length===0){i();return}let o=[N.t(`cmd.pluginTrustConfirmIntro`)];if(a.mcpJson&&o.push(`• ${N.t(`cmd.pluginSurfaceMcp`)}`),a.commands&&o.push(`• ${N.t(`cmd.pluginSurfaceCommands`)}`),a.scripts&&o.push(`• ${N.t(`cmd.pluginSurfaceScripts`)}`),a.panels&&o.push(`• ${N.t(`cmd.pluginSurfacePanels`)}`),a.skills&&o.push(`• ${N.t(`cmd.pluginSurfaceSkills`)}`),a.agents&&o.push(`• ${N.t(`cmd.pluginSurfaceAgents`)}`),r.length>0){o.push(``,N.t(`cmd.pluginCapabilityIntro`));for(let e of r){let t=ai(e);t&&o.push(`• ${t}`)}}o.push(``,N.t(`cmd.pluginTrustConfirmHint`)),e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.pluginTrustConfirmTitle`,{id:t.id}),subtitle:o.join(`
15
- `),layout:`buttons`,options:[{label:N.t(`cmd.pluginTrustConfirmAction`),value:`trust`,color:`accent`},{label:N.t(`cmd.commonCancel`),value:`cancel`,color:`gray`}],onSelect:e=>{e===`trust`&&i()},onCancel:()=>{}})}async function si(e,t,n){if(t.length===0)return!0;let r=[N.t(`cmd.pluginCapabilityIntro`)];for(let e of t){let t=ai(e);t&&r.push(`• ${t}`)}return new Promise(t=>{n.tui.modal.openModal({kind:`select`,title:N.t(`cmd.pluginInstallConfirmTitle`,{name:e}),subtitle:r.join(`
16
- `),layout:`buttons`,options:[{label:N.t(`cmd.pluginInstallConfirmAction`),value:`install`,color:`accent`},{label:N.t(`cmd.commonCancel`),value:`cancel`,color:`gray`}],onSelect:e=>t(e===`install`),onCancel:()=>t(!1)})})}async function ci(e,t,n){let r=n?.autoTrust??!1,i=n?.onProgress,a=n?.onPendingCapabilities;if(e.includes(`..`)||e.startsWith(`/`)||e.startsWith(`./`)||e.startsWith(`~/`))return r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallInvalidName`,{name:e})),!1;let s=o[e]?.pkg??e,c=Te(s),l;if(!c)try{i?.(`Downloading from npm registry`);let e=await new w().install(s,{global:!0,as:`plugin`,postInstallExecutor:se});e.success&&e.targetPath?(c=e.targetPath,l={id:e.name??s,dir:e.targetPath,created:!0,compileWarnings:[],version:e.manifest?.version}):r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallFailed`,{err:e.error??`未知错误`}))}catch(e){r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallFailed`,{err:e instanceof Error?e.message:String(e)}))}if(!c)return r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallNotFound`,{pkg:s})),!1;let u=ye(c);if(!r&&!await si(e,u,t))return t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallCancelled`)),!1;let d;if(l)d=l;else try{i?.(`Installing plugin`),d=await ge({pkg:s})}catch(e){return r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallFailed`,{err:e instanceof Error?e.message:String(e)})),!1}r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstalled`,{seg:d.created?`Installed ${d.id}`:`${d.id} already up to date`})),await Se(t.app.settings,{id:d.id,source:`npm`,sourceSpec:s,version:d.version,scope:`global`,capabilities:u}),t.app.pluginModuleManager.emitMonitorEvent({type:`plugin.installed`,pluginId:d.id});for(let e of d.compileWarnings)r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallFailed`,{err:e}));u.length>0&&(i?.(`Authorizing capabilities`),ke(d.dir),he(d.dir,u));try{i?.(`Reloading capabilities`),(await t.app.reloadCapabilities()).pendingProviderCapabilities.includes(d.id)&&(r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.pluginInstallPendingCaps`,{id:d.id})),a?.(d.id))}catch(e){r||t.tui.info.showToast(N.t(`cmd.titleInstall`),N.t(`cmd.compatReloadFailed`,{err:e instanceof Error?e.message:String(e)}))}if(await t.callbacks.refreshModelsNow().catch(()=>{}),e===`plugin-feishu-use`){try{let{launchFeishuSetup:e}=await import(`./feishu-setup-B6ETf-8Y.js`);await e(t)}catch{}return!0}if(!r){await new Promise(e=>setImmediate(e));let{handleModel:e}=await Promise.resolve().then(()=>di);await e([],t)}return!0}async function li(e,t){t.tui.panes.togglePane(`backgroundTasks`)}async function ui(e,t){let n=e.join(` `);if(!n){t.tui.info.showToast(N.t(`cmd.titleJob`),N.t(`cmd.jobUsage`));return}let r=/^revert\s+(\S+)$/.exec(n);if(r){let e=r[1],n=t.app.agentJobs.revert(e);if(n.applied)t.tui.info.showToast(N.t(`cmd.titleReverted`),N.t(`cmd.jobReverted`,{id:e,msg:n.message}));else{let r=n.conflictPaths.length?N.t(`cmd.jobConflictFiles`,{joinedPaths:n.conflictPaths.join(`
17
- `)}):``;t.tui.messages.pushMessage({role:`command_echo`,command:`/go revert ${e}`,status:`error`,summary:N.t(`cmd.jobRevertFailed`,{id:e,status:n.status,msg:n.message,conflicts:r})})}return}try{let e=t.app.agentJobs.start({title:n.slice(0,60),prompt:n,sessionId:t.state.session.id,origin:`user`});t.tui.info.showToast(N.t(`cmd.titleDelegated`),N.t(`cmd.delegated`,{title:e.title}))}catch(e){t.tui.messages.pushMessage({role:`command_echo`,command:`/go`,status:`error`,summary:N.t(`cmd.delegateFailed`,{err:e instanceof Error?e.message:String(e)})})}}async function J(e,t){let r=e[0]?.toLowerCase();if(r===`trust`)return Wr(e.slice(1),t);if(r===`install`)return c(e.slice(1),t);if(r===`registry`)return u(e.slice(1),t);if(r===`search`)return l(e.slice(1),t);if(r===`update`)return $r([`--check`],t);let i=(e,n)=>t.tui.info.showToast(e,n),a=e=>t.tui.messages.pushMessage({role:`command_echo`,command:`/extension`,status:`error`,summary:e}),o=()=>{let e=t.app.extensions.list(),n=t.app.getGlobalMenuItems?.()??[],r=new Map(n.map(e=>[e.id,e.command]));t.tui.modal.openModal({kind:`extensionsList`,entries:e.map(e=>({category:e.category,id:e.id,name:e.name,enabled:e.enabled,description:e.description,applies:e.applies})),menuContributions:[{id:`__discover__`,title:`Discover plugins (search registries)…`},...n.map(e=>({id:e.id,title:e.title}))],onSelect:e=>{if(!e)return;if(e===`contrib:__discover__`){s();return}if(e.startsWith(`contrib:`)){let n=e.slice(8),a=r.get(n);if(!a)return;de(a,{open:e=>_e(e),runCommand:async(e,n)=>{let{dispatchSlashCommand:r}=await Promise.resolve().then(()=>Va);await r(e,n?n.split(/\s+/).filter(Boolean):[],t)}}).catch(e=>i(N.t(`cmd.titlePlugin`),e instanceof Error?e.message:String(e)));return}let n=e.indexOf(`:`);p(e.slice(0,n),e.slice(n+1))},onCancel:()=>{}})},s=async()=>{let e=await t.tui.modal.openModal({kind:`input`,title:`Discover plugins`,description:[`搜索已注册 registry(/registry list 查看源;/registry add 注册第三方源)`],placeholder:`keyword… (e.g. weather / oauth / provider)`});if(!e?.trim()){o();return}let{searchRegistries:n}=await import(`./registry-BOX7DaxS.js`),{hits:r,warnings:a}=await n(t,e.trim());if(r.length===0){i(N.t(`cmd.titlePlugin`),`No registry entries match '${e.trim()}'${a.length?` (${a.length} source warning)`:``}`),o();return}t.tui.modal.openModal({kind:`select`,title:`Discover: '${e.trim()}' (${r.length})`,subtitle:a.length>0?`⚠ ${a.join(` · `)}`:void 0,options:r.map((e,t)=>({label:`${e.entry.id} (${e.entry.type}) [${(e.entry.capabilities??[]).join(`, `)||`-`}] @${e.sourceName}${e.stale?` (stale)`:``}`,description:e.entry.description,value:String(t)})),onSelect:e=>{let n=r[Number(e)];if(!n)return;let a=[`--as`,n.entry.type,...n.entry.subPath?[`--sub-path`,n.entry.subPath]:[],n.entry.source];(async()=>{let{dispatchSlashCommand:e}=await Promise.resolve().then(()=>Va);await e(`extension`,[`install`,...a],t)})().catch(e=>i(N.t(`cmd.titlePlugin`),e instanceof Error?e.message:String(e)))},onCancel:()=>o()})},d=e=>{let n=t.app.skillRegistry?.get(e);if(!n){o();return}let r=n.status!==`disabled`,s=n.definition.metadata,c=[{kind:`group`,title:N.t(`cmd.extSkillGroupOverview`)},{kind:`row`,label:N.t(`cmd.extSkillLabelDesc`),value:s.description||`—`},{kind:`row`,label:N.t(`cmd.extSkillLabelStatus`),value:n.status,tone:n.status===`error`||n.status===`disabled`?`error`:`success`},{kind:`row`,label:N.t(`cmd.extSkillLabelSource`),value:N.t(`cmd.extSkillSourceLabel`,{seg:ri(n.source.type,n.source.id)}),tone:`muted`},...ti(n.source.root)?[]:[{kind:`text`,value:N.t(`cmd.extSkillManagedExternally`,{root:n.source.root}),tone:`muted`}],{kind:`group`,title:N.t(`cmd.extSkillGroupTrigger`)},{kind:`row`,label:N.t(`cmd.extSkillLabelTriggerMode`),value:s.trigger===`manual`?N.t(`cmd.extSkillTriggerManual`):N.t(`cmd.extSkillTriggerAuto`)},...s.priority===void 0?[]:[{kind:`row`,label:N.t(`cmd.extSkillLabelPriority`),value:String(s.priority)}],{kind:`group`,title:N.t(`cmd.extSkillGroupDependencies`)},{kind:`row`,label:N.t(`cmd.extSkillLabelDependencies`),value:s.dependencies?.length?s.dependencies.join(`, `):N.t(`cmd.extSkillNoDependencies`),tone:s.dependencies?.length?void 0:`muted`},{kind:`group`,title:N.t(`cmd.extSkillGroupTags`)},{kind:`row`,label:N.t(`cmd.extSkillLabelTags`),value:s.tags?.length?s.tags.join(`, `):N.t(`cmd.extSkillNoTags`),tone:s.tags?.length?void 0:`muted`}];n.status===`error`&&n.error&&c.push({kind:`group`,title:N.t(`cmd.extSkillGroupError`)},{kind:`text`,value:n.error,tone:`error`}),t.tui.modal.openModal({kind:`extensionDetail`,title:N.t(`cmd.extSkillTitle`,{name:e,state:r?`enabled`:`disabled`}),meta:`skill · ${n.source.type}`,metaStatus:{label:r?N.t(`cmd.extEnableLabel`):N.t(`cmd.extDisableLabel`),enabled:r},actions:[{label:r?N.t(`cmd.extDisableLabel`):N.t(`cmd.extEnableLabel`),value:`toggle`,color:r?`amber`:`green`},{label:N.t(`cmd.extViewFullTextLabel`),value:`view-full-text`,color:`gray`},...ni(n.source.type,n.source.root)?[{label:N.t(`cmd.uninstallActionLabel`),value:`uninstall`,color:`red`}]:[]],dataListEntries:c,fullText:{title:N.t(`cmd.extSkillFullTextTitle`,{name:e}),content:n.definition.body||N.t(`cmd.extSkillNoBody`)},onAction:async s=>{if(s===`toggle`){try{await t.app.extensions.setEnabled(`skill`,e,!r),i(N.t(`cmd.titleExtension`),N.t(`cmd.extToggled`,{name:e,verb:r?`Disabled`:`Enabled`,seg:` — applies next turn`}))}catch(e){a(N.t(`cmd.extToggleFailed`,{err:e instanceof Error?e.message:String(e)}))}d(e);return}if(s===`uninstall`){let r=ni(n.source.type,n.source.root);if(!r)return;await Qn({name:e,type:`skill`,scope:r,ctx:t,onDone:()=>o()})}},onClose:()=>o()})},f=e=>{let n=t.app.declarativeAgentProfiles.find(t=>t.name===e);if(!n){o();return}let r=!new Set(t.app.settings.get(`disabled_agents`)??[]).has(e),s=[{kind:`group`,title:N.t(`cmd.extAgentGroupOverview`)},{kind:`row`,label:N.t(`cmd.extAgentLabelDesc`),value:n.description||`—`},{kind:`row`,label:N.t(`cmd.extAgentLabelStatus`),value:r?N.t(`cmd.extEnableLabel`):N.t(`cmd.extDisableLabel`),tone:r?`success`:`error`},{kind:`group`,title:N.t(`cmd.extAgentGroupCapabilities`)},{kind:`row`,label:N.t(`cmd.extAgentLabelTaskTypes`),value:n.taskTypes.length?n.taskTypes.join(`, `):N.t(`cmd.extAgentNoTaskTypes`),tone:n.taskTypes.length?void 0:`muted`},{kind:`row`,label:N.t(`cmd.extAgentLabelCapabilities`),value:n.capabilities.length?n.capabilities.join(`, `):N.t(`cmd.extAgentNoCapabilities`),tone:n.capabilities.length?void 0:`muted`},{kind:`group`,title:N.t(`cmd.extAgentGroupTools`)},{kind:`row`,label:N.t(`cmd.extAgentLabelDefaultTools`),value:n.defaultTools?.length?n.defaultTools.join(`, `):N.t(`cmd.extAgentAllTools`),tone:n.defaultTools?.length?void 0:`muted`},{kind:`row`,label:N.t(`cmd.extAgentLabelDisallowedTools`),value:n.disallowedTools?.length?n.disallowedTools.join(`, `):N.t(`cmd.extAgentNoDisallowedTools`),tone:n.disallowedTools?.length?void 0:`muted`},{kind:`group`,title:N.t(`cmd.extAgentGroupExecution`)},{kind:`row`,label:N.t(`cmd.extAgentLabelPromptMode`),value:n.promptMode??`append`,tone:`muted`},...n.preferredModelTier?[{kind:`row`,label:N.t(`cmd.extAgentLabelModelTier`),value:n.preferredModelTier}]:[],{kind:`row`,label:N.t(`cmd.extAgentLabelAllowSubagents`),value:n.allowSubagents?N.t(`cmd.extEnableLabel`):N.t(`cmd.extDisableLabel`),tone:n.allowSubagents?void 0:`muted`}];t.tui.modal.openModal({kind:`extensionDetail`,title:N.t(`cmd.extAgentTitle`,{name:e,state:r?`enabled`:`disabled`}),meta:`agent`,metaStatus:{label:r?N.t(`cmd.extEnableLabel`):N.t(`cmd.extDisableLabel`),enabled:r},actions:[{label:r?N.t(`cmd.extDisableLabel`):N.t(`cmd.extEnableLabel`),value:`toggle`,color:r?`amber`:`green`},{label:N.t(`cmd.extViewFullTextLabel`),value:`view-full-text`,color:`gray`}],dataListEntries:s,fullText:{title:N.t(`cmd.extAgentFullTextTitle`,{name:e}),content:n.systemPromptTemplate||N.t(`cmd.extSkillNoBody`)},onAction:async n=>{if(n===`toggle`){try{await t.app.extensions.setEnabled(`agent`,e,!r),i(N.t(`cmd.titleExtension`),N.t(`cmd.extToggled`,{name:e,verb:r?`Disabled`:`Enabled`,seg:` — applies next turn`}))}catch(e){a(N.t(`cmd.extToggleFailed`,{err:e instanceof Error?e.message:String(e)}))}f(e)}},onClose:()=>o()})},p=(e,n)=>{let r=t.app.extensions.list().find(t=>t.category===e&&t.id===n);if(!r){o();return}let s={label:r.enabled?N.t(`cmd.extDisableLabel`):N.t(`cmd.extEnableLabel`),value:`toggle`};if(e===`mcp`){let c=t.app.mcpManager?.getServerInfos().find(e=>e.name===n),l=r.enabled?c?String(c.status):`disconnected`:`disabled`;t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.extMcpTitle`,{name:r.name,status:l}),options:[{label:N.t(`cmd.extReconnectLabel`),value:`reconnect`},s,...r.readonly?[]:[{label:N.t(`cmd.uninstallActionLabel`),value:`uninstall`}]],onSelect:async s=>{if(s===`toggle`){try{await t.app.extensions.setEnabled(r.category,n,!r.enabled),i(N.t(`cmd.titleExtension`),N.t(`cmd.extToggled`,{name:r.name,verb:r.enabled?`Disabled`:`Enabled`,seg:``}))}catch(e){a(N.t(`cmd.extToggleFailed`,{err:e instanceof Error?e.message:String(e)}))}p(e,n);return}if(s===`reconnect`){let r=t.app.mcpManager,o=(t.app.settings.get(`mcp_servers`)??{})[n];if(!r||!o){i(N.t(`cmd.titleExtension`),N.t(`cmd.extReconnectUnavailable`,{id:n})),p(e,n);return}try{await r.disconnect(n).catch(()=>{}),await r.connect(n,o),i(N.t(`cmd.titleExtension`),N.t(`cmd.extReconnected`,{id:n}))}catch(e){a(N.t(`cmd.extReconnectFailed`,{id:n,err:e instanceof Error?e.message:String(e)}))}p(e,n);return}if(s===`uninstall`){await Qn({name:n,type:`mcp`,scope:`project`,ctx:t,onDone:()=>o()});return}},onCancel:()=>o()})}else e===`plugin`?m(n,r.enabled,r.name,r.description):e===`skill`?d(n):e===`agent`?f(n):t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.extItemTitle`,{name:r.name}),options:[s],onSelect:async o=>{if(o===`toggle`){try{await t.app.extensions.setEnabled(r.category,n,!r.enabled),i(N.t(`cmd.titleExtension`),N.t(`cmd.extToggled`,{name:r.name,verb:r.enabled?`Disabled`:`Enabled`,seg:r.applies===`live`?``:` — applies next turn`}))}catch(e){a(N.t(`cmd.extToggleFailed`,{err:e instanceof Error?e.message:String(e)}))}p(e,n);return}},onCancel:()=>o()})},m=(e,r,s,c,l)=>{let u=t.app.workspaceDir??process.cwd(),d=n({cwd:u,homedir:_()}).find(t=>t.id===e);if(!d){o();return}let f=pe(d),p=f.surface.any?f.gated?N.t(`cmd.extPluginUntrusted`):f.pendingCapabilities.length>0?N.t(`cmd.extPluginCapabilityPending`,{caps:f.pendingCapabilities.join(`, `)}):N.t(`cmd.extPluginTrusted`):N.t(`cmd.extPluginNoSurface`),h=f.surface,g=[[h.mcpJson,`mcp`],[h.commands,`commands`],[h.scripts,`scripts`],[h.panels,`panels`],[h.skills,`skills`],[h.agents,`agents`]].filter(([e])=>e).map(([,e])=>e),v=g.length?` ${g.join(`, `)}`:` —`,ee=(t.app.getPluginPanelRegistrations?.()??[]).filter(t=>t.pluginId===e),y=ii({providerApis:t.app.providerRegistry.getApisBySource(e).length,tools:t.app.toolRegistry.getAll().filter(t=>t.metadata.source===e).length,renderers:t.app.getPluginRenderers().filter(t=>t.pluginId===e).length,statusItems:t.app.getPluginStatusItems().filter(t=>t.id.startsWith(`${e}:`)).length,fileViewers:(t.app.getPluginFileViewers?.()??[]).filter(t=>t.pluginId===e).length}),b=d.scope===`builtin`?[]:[{label:r?N.t(`cmd.extDisableLabel`):N.t(`cmd.extEnableLabel`),value:`toggle`,color:r?`amber`:`green`}];if(f.surface.any&&(d.scope===`project`||d.scope===`repository`||f.pendingCapabilities.length>0)){let e=d.scope===`project`||d.scope===`repository`?!f.trusted:f.pendingCapabilities.length>0;b.push({label:e?N.t(`cmd.extPluginTrustLabel`):N.t(`cmd.extPluginUntrustLabel`),value:e?`trust`:`untrust`,color:e?`accent`:`gray`})}b.push({label:N.t(`cmd.extReloadLabel`),value:`reload`}),d.scope!==`builtin`&&b.push({label:N.t(`cmd.uninstallActionLabel`),value:`uninstall`,color:`red`});let te=ie(d,{"extension.id":e,"extension.enabled":r,"extension.trusted":f.trusted,"extension.scope":d.scope,"extension.category":`plugin`}),x=d.manifest.contributes,S=we(re.extensionDetailActions,x?.menus,x?.actions,te),ne=new Map(S.map(e=>[e.id,e.command]));for(let e of S){let n=`${d.id}:action.${e.id}.title`,r=t.app.i18nRegistry.t(n),i=r===n?e.title:r;b.push({label:i,value:`contrib:${e.id}`,color:e.color})}let C={open:e=>_e(e),runCommand:async(e,n)=>{let{dispatchSlashCommand:r}=await Promise.resolve().then(()=>Va);await r(e,n?n.split(/\s+/).filter(Boolean):[],t)},runScript:async e=>{if(pe(d).gated){i(N.t(`cmd.titlePlugin`),N.t(`cmd.extPluginUntrusted`));return}await De(d,e)}},w=ee[0];w&&t.app.firePluginActivationEvent?.(`onView:${w.id}`);let T;if(e===`plugin-feishu-use`){let e=O(u,`.otto`,`feishu-use.json`),t=!1;try{if(k(e)){let n=JSON.parse(A(e,`utf8`));if(n.app_id){t=!0;let r=typeof n.app_id==`string`&&n.app_id.length>12?n.app_id.slice(0,8)+`***`+n.app_id.slice(-4):String(n.app_id),i=Array.isArray(n.allowed_chats)?n.allowed_chats.length:0,a=Array.isArray(n.trusted_chats)?n.trusted_chats.length:0,o=d.scope===`user`?`全局`:d.scope===`repository`?`仓库`:`项目`;T=[{kind:`row`,label:`App ID`,value:r},{kind:`row`,label:`消息白名单`,value:i>0?`${i} 个`:`空 — 拒绝所有消息`,tone:i>0?void 0:`warning`},...a>0?[{kind:`row`,label:`可信任 chat`,value:`${a} 个`}]:[],{kind:`row`,label:`配置`,value:`${o}级 · ${e}`,tone:`muted`}]}}}catch{}t||(T=[{kind:`text`,value:`未配置 — 点击 [重新配置] 引导设置`,tone:`warning`},{kind:`row`,label:`预期配置路径`,value:e,tone:`muted`}]),b.push({label:`重新配置`,value:`feishu-reconfigure`,color:`amber`})}let ae=()=>{let n=t.app.pluginHealthTracker?.query(e)??{hookTimeouts:0,toolTimeouts:0},r=be(e);return{healthStats:{hookTimeouts:n.hookTimeouts,toolTimeouts:n.toolTimeouts,lastError:n.lastError},logEntries:r.map(e=>({ts:e.ts,level:e.level,msg:e.msg}))}},oe=[{kind:`group`,title:N.t(`cmd.extPluginGroupTitle`)},{kind:`row`,label:N.t(`cmd.extPluginLabelDesc`),value:c},{kind:`row`,label:N.t(`cmd.extPluginLabelScope`),value:d.scope},{kind:`row`,label:N.t(`cmd.extPluginLabelTrust`),value:p},{kind:`row`,label:N.t(`cmd.extPluginLabelSurfaces`),value:v.trim()||`—`},...y?[{kind:`row`,label:N.t(`cmd.extPluginLabelContributions`),value:y}]:[],{kind:`row`,label:N.t(`cmd.extPluginLabelStatus`),value:r?N.t(`cmd.extEnableLabel`):N.t(`cmd.extDisableLabel`),tone:r?`success`:`error`}],se=l?[{kind:`text`,value:l.message,tone:l.kind===`success`?`success`:`error`}]:[];t.tui.modal.openModal({kind:`extensionDetail`,title:N.t(`cmd.extPluginTitle`,{name:s,state:r?`enabled`:`disabled`}),meta:`plugin · ${d.scope}`,metaStatus:{label:r?N.t(`cmd.extEnableLabel`):N.t(`cmd.extDisableLabel`),enabled:r},metaSuffix:p,actions:b,panelInfo:w?{title:w.title,modulePath:w.modulePath,exportName:w.exportName,pluginId:e}:void 0,dataListEntries:[...se,...T??oe],...ae(),onRefresh:()=>m(e,r,s,c),onAction:async n=>{if(n.startsWith(`contrib:`)){let t=ne.get(n.slice(8));if(t)try{await de(t,C)}catch(e){a(N.t(`cmd.extToggleFailed`,{err:e instanceof Error?e.message:String(e)}))}m(e,r,s,c)}else if(n===`trust`)oi(t,d);else if(n===`untrust`){try{Me(d.dir)}catch(t){m(e,r,s,c,{kind:`error`,message:`撤销信任失败,权限未收回:${t instanceof Error?t.message:String(t)}`});return}t.app.reloadCapabilities?.().then(()=>{t.tui.plugins.setPluginRegistrations(t.app.getPluginRegistrations())}).finally(()=>{m(e,r,s,c,{kind:`success`,message:N.t(`cmd.pluginUntrusted`,{id:e})})})}else if(n===`toggle`)try{await t.app.extensions.setEnabled(`plugin`,e,!r);try{await t.app.reloadCapabilities(),m(e,!r,s,c,{kind:`success`,message:N.t(`cmd.extToggled`,{name:s,verb:r?`Disabled`:`Enabled`,seg:``})})}catch(t){m(e,!r,s,c,{kind:`error`,message:N.t(`cmd.extToggleReloadFailed`,{verb:r?`Disabled`:`Enabled`,name:s,err:t instanceof Error?t.message:String(t)})})}}catch(t){m(e,r,s,c,{kind:`error`,message:N.t(`cmd.extToggleFailed`,{err:t instanceof Error?t.message:String(t)})})}else if(n===`feishu-reconfigure`)try{let{launchFeishuSetup:e}=await import(`./feishu-setup-B6ETf-8Y.js`);await e(t),i(`plugin-feishu-use`,`配置完成。`)}catch(e){a(`feishu-use 配置向导失败:${e instanceof Error?e.message:String(e)}`)}else n===`reload`?t.app.reloadCapabilities?.().then(t=>{m(e,r,s,c,{kind:`success`,message:N.t(`cmd.pluginTrusted`,{id:e,count:t.mcpTools})})}).catch(t=>{m(e,r,s,c,{kind:`error`,message:N.t(`cmd.compatReloadFailed`,{err:t instanceof Error?t.message:String(t)})})}):n===`uninstall`&&await Qn({name:e,type:`plugin`,scope:d.scope===`project`||d.scope===`repository`?d.scope:`global`,ctx:t,onDone:()=>o()})},onClose:()=>o()})};o()}var di=yt({handleLogout:()=>vi,handleModel:()=>gi,handleProviderAuth:()=>Y,handleProviderLogout:()=>_i,handleServiceLogin:()=>yi,handleServiceLogout:()=>bi});const fi=`__otto_model_login__`,pi=`__otto_model_setkey__`,mi=`__otto_model_grant_capability__`,hi=`__otto_model_install_plugin__`;async function gi(e,t,n){let r=e[0];if(r===`refresh`||r===`--refresh`){let e=await t.app.refreshModels();t.state.models=t.app.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow}));for(let n of e)for(let e of n.availableIds??[])t.state.availableModelIds.add(e);t.callbacks.persistAvailable();let n=Math.max(...e.map(e=>e.provider.length),0),r=e=>e.padEnd(n),i={},a=e.map((e,t)=>e.status===`ok`?(i[t]=`success`,N.t(`cmd.modelRefreshLineOk`,{provider:r(e.provider),added:e.added,kept:e.kept,total:e.total})):e.status===`skipped`&&e.reason===`not authenticated`?(i[t]=`muted`,N.t(`cmd.modelRefreshLineMuted`,{provider:r(e.provider),reason:N.t(`cmd.modelRefreshReasonNotAuthenticated`)})):e.reason?.includes(`capability not granted`)?(i[t]=`warning`,N.t(`cmd.modelRefreshLineWarning`,{provider:r(e.provider),reason:N.t(`cmd.modelRefreshReasonPendingCapability`)})):(i[t]=`warning`,N.t(`cmd.modelRefreshLineErr`,{provider:r(e.provider),status:e.status,reason:e.reason}))),o=e.some(e=>e.status===`skipped`&&e.reason?.includes(`capability not granted`));t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleModels`),lines:[...a,``,N.t(`cmd.modelRefreshHint`)],action:o?{kind:`extension`,run:()=>{J([],t)}}:void 0,lineTones:i});return}if(r){let e=t.state.models.find(e=>e.id===r||e.name===r);if(!e){let e=r.includes(`/`)?r.split(`/`)[0]:r;if(!t.state.models.some(t=>t.provider.toLowerCase()===e.toLowerCase())&&/^[a-z0-9][\w-]*$/i.test(e)){t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.modelDelegateProviderTitle`,{cand:e}),options:[{label:N.t(`cmd.modelDelegateProviderYes`,{cand:e}),value:`yes`},{label:N.t(`cmd.commonNo`),value:`no`}],onSelect:n=>{if(n!==`yes`)return;let r=`为 "${e}" 实现一个 provider 适配器:参照 packages/ai/src 下现有 provider 的实现,接 model-fetch 的 resolveModelsRequest、注册进 provider/model registry,并写测试跑绿。`;try{t.app.agentJobs.start({title:`write provider: ${e}`,prompt:r,sessionId:t.state.session.id,origin:`user`}),t.tui.info.showToast(N.t(`cmd.titleDelegated`),N.t(`cmd.modelProviderDelegated`,{cand:e}))}catch(e){t.tui.messages.pushMessage({role:`command_echo`,command:`/model`,status:`error`,summary:N.t(`cmd.delegateFailed`,{err:e instanceof Error?e.message:String(e)})})}},onCancel:()=>{}});return}t.tui.info.showToast(N.t(`cmd.titleModel`),N.t(`cmd.modelNotFoundUse`,{arg:r}));return}t.tui.info.showToast(N.t(`cmd.titleModel`),await t.callbacks.applyModel(e.id)),t.state.session.model?.id===e.id&&n?.afterSwitch?.();return}t.state.models=t.app.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow}));let i=e=>t.state.availableModelIds.has(e),a=[...new Set(t.state.models.map(e=>t.callbacks.apiCredentialId(e.api??``,e.provider)))],o=new Map(await Promise.all(a.map(async e=>[e,await t.app.authStore.getAuthSource(e).catch(()=>null)]))),s=e=>{let n=t.callbacks.apiCredentialId(e.api??``,e.provider),r=o.get(n);if(!r)return``;let i=N.t(`pref.authModeLabel`,{context:r});return`${i===r?``:` · `}${i}`},c=[...t.state.models].sort((e,t)=>Number(i(t.id))-Number(i(e.id))||e.provider.localeCompare(t.provider)||e.name.localeCompare(t.name)),l=c.length>0?Math.max(...c.map(e=>e.name.length),8):8,u=e=>e?e>=1e6?`${(e/1e6).toFixed(1)}M`:`${Math.round(e/1e3)}k`:``,d=e=>{let n=i(e.id),r=e.id===t.state.currentModelId?`●`:` `,a=u(e.contextWindow),o=`${r} ${e.name.padEnd(l)}`+(a?` ${a}`:``),c=[s(e).replace(/^ · /,``),e.strengths.length>0?e.strengths.join(`/`):``].filter(Boolean).join(` `);return{isAvail:n,label:o,detail:c&&` ${c}`}},f=t.app.settings.get(`recent_models`)??[],p=new Map(t.state.models.map(e=>[e.id,e])),m=f.map(e=>p.get(e)).filter(e=>e!==void 0).map(e=>{let{isAvail:t,label:n,detail:r}=d(e);return{label:n,value:e.id,disabled:!t,group:N.t(`cmd.modelRecentGroup`),detail:r||void 0,searchText:e.name}}),h=t.state.availableModelIds.size===0,g=!t.app.modelRegistry.hasAnyPluginSourcedModel()&&h,_=(t.app.pendingProviderCapabilities??[]).length,v=[];g&&_>0?(v.push(N.t(`model.noProviderPlugin`)),v.push(N.t(`model.pendingCapabilities`,{count:_}))):g?v.push(N.t(`model.noProviderPlugin`)):h&&v.push(N.t(`model.noneAvailable`)),!g&&_>0&&v.push(N.t(`model.pendingCapabilities`,{count:_})),t.tui.modal.openModal({kind:`select`,searchable:!0,maxVisible:13,title:h?N.t(`cmd.modelSelectTitle`):N.t(`cmd.modelSelectTitleAvail`),subtitle:v.length>0?v.join(` · `):void 0,subtitleTone:_>0?`warning`:`default`,subtitleActions:g||h||_>0?[...g?[{label:N.t(`model.goInstallPlugin`),value:hi}]:h?[{label:N.t(`model.goLogin`),value:fi},{label:N.t(`model.setKey`),value:pi}]:[],..._>0?[{label:N.t(`model.goGrantCapability`),value:mi}]:[]]:void 0,options:[...m,...c.map(e=>{let{isAvail:t,label:n,detail:r}=d(e);return{label:n,value:e.id,disabled:!t,group:e.provider,detail:r||void 0,searchText:e.name}})],onSelect:async e=>{if(e===fi){await Y([],t,{method:`oauth`});return}if(e===pi){await Y([],t,{method:`key`});return}if(e===mi){await J([],t);return}if(e===hi){let{EXTENSION_ALIASES:e}=await import(`./extension-I87MkZYp.js`),{runPluginInstall:n}=await Promise.resolve().then(()=>ei),r=Object.entries(e).filter(([,e])=>e.capabilities.includes(`provider`)).map(([e])=>({label:e,value:e}));if(r.length===1){await n(r[0].value,t);return}t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.modelSelectTitle`),options:r.map(e=>({label:e.label,value:e.value})),onSelect:async e=>{await n(e,t)},onCancel:()=>{}});return}t.tui.info.showToast(N.t(`cmd.titleModel`),await t.callbacks.applyModel(e)),t.state.session.model?.id===e&&n?.afterSwitch?.()}})}async function Y(e,t,n){if(e[0]===`logout`)return _i(e.slice(1),t);if(e.includes(`--service`))return yi(e,t);let r=t.app.authStore,i=e=>new Promise(n=>t.tui.modal.openModal({kind:`select`,...e,title:e.title??N.t(`cmd.commonSelect`),detailPlacement:`inline`,onSelect:n,onCancel:()=>n(null)})),a=r.listProviders();if(a.length===0){t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.loginNoProviders`));return}let o=e[0]||null,s=e=>r.oauth.get(e)?.name??mt(e)?.name??t.callbacks.PROVIDER_DISPLAY_NAMES[e]??e,c=e=>s(e),l=e=>e?N.t(`pref.authModeLabel`,{context:e}):N.t(`cmd.loginNotSet`),u=(e,t)=>{let n=l(t);return s(e).toLowerCase()===e.toLowerCase()?n:`[${e}] · ${n}`};if(!o){let e=await Promise.all(a.map(e=>r.getAuthSource(e)));o=await i({title:N.t(`cmd.loginPickProvider`),options:a.map((t,n)=>({label:c(t),value:t,detail:u(t,e[n]??null)}))})}if(!o)return;let d=r.oauth.get(o)?.name??o,f=!!r.oauth.get(o),p=`key`;if(n?.method)p=n.method===`oauth`&&f?`oauth`:`key`;else if(f){let e=await i({title:N.t(`cmd.loginAuthMethod`,{name:d}),options:[{label:N.t(`cmd.loginMethodOauth`),value:`oauth`},{label:N.t(`cmd.loginMethodKey`),value:`key`}]});if(!e)return;p=e}if(p===`key`){let e=await t.tui.modal.openModal({kind:`input`,title:N.t(`cmd.loginKeyTitle`,{provider:o}),placeholder:N.t(`cmd.loginKeyPlaceholder`),mask:!0});if(!e||!e.trim()){t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.loginCancelledNoKey`));return}await r.setCredentialKey(o,e.trim()),await r.save(),t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.loginKeySaved`,{provider:o})),await t.callbacks.refreshModelsNow(e=>t.tui.info.showToast(N.t(`cmd.titleModels`),e));return}try{let e={};await r.login(o,{onAuth:n=>{if(e=n,n.url)if(Fe(n.url))t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.loginOauthBrowserOpened`));else{let e=[N.t(`cmd.loginOauthUrlAuthorize`),`\n${n.url}`];n.instructions&&e.push(`\n${n.instructions}`),t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.loginOauthTitle`,{provider:o}),lines:e})}if(n.code){let e=[N.t(`cmd.loginOauthCodeIntro`)];n.url&&e.push(`\n${n.url}`),e.push(`\n${N.t(`cmd.loginOauthCode`,{code:n.code})}`),n.instructions&&e.push(`\n${n.instructions}`),t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.loginOauthTitle`,{provider:o}),lines:e})}},onProgress:e=>t.tui.info.showToast(N.t(`cmd.titleLogin`),e),onPrompt:async e=>await t.tui.modal.openModal({kind:`input`,title:e.message,placeholder:e.placeholder})??``,onManualCode:async n=>{let r=[];return e.url&&(r.push(N.t(`cmd.loginOauthUrlAuthorize`)),r.push(` `),r.push(e.url)),e.instructions&&(r.length>0&&r.push(` `),r.push(e.instructions)),await t.tui.modal.openModal({kind:`input`,title:N.t(`cmd.loginOauthPasteCode`,{provider:o}),description:r.length>0?r:void 0,placeholder:`code#state`,signal:n,actionButton:e.url?{label:N.t(`cmd.loginOauthOpenBrowserButton`),onPress:()=>{Fe(e.url)&&t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.loginOauthBrowserOpened`))}}:void 0})??``}}),t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.loginSuccess`,{provider:o})),await t.callbacks.refreshModelsNow(e=>t.tui.info.showToast(N.t(`cmd.titleModels`),e))}catch(e){t.tui.messages.pushMessage({role:`command_echo`,command:`/auth`,status:`error`,summary:N.t(`cmd.loginFailed`,{msg:e.message})})}}async function _i(e,t){let n=t.app.authStore,r=e[0]||null;if(!r){let e=n.listProviders(),i=await Promise.all(e.map(e=>n.getAuthSource(e))),a=e.filter((e,t)=>i[t]===`oauth`||i[t]===`api_key`);if(a.length===0){t.tui.info.showToast(N.t(`cmd.titleLogout`),N.t(`cmd.logoutNoStored`));return}r=await new Promise(r=>t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.logoutPickProvider`),detailPlacement:`inline`,options:a.map(r=>{let a=n.oauth.get(r)?.name??mt(r)?.name??t.callbacks.PROVIDER_DISPLAY_NAMES[r]??r,o=i[e.indexOf(r)];return{label:a.toLowerCase()===r.toLowerCase()?a:`${a} [${r}]`,value:r,detail:o?N.t(`pref.authModeLabel`,{context:o}):void 0}}),onSelect:r,onCancel:()=>r(null)}))}r&&(await n.logout(r),t.tui.info.showToast(N.t(`cmd.titleLogout`),N.t(`cmd.logoutSuccess`,{provider:r})))}async function vi(e,t){e[0]&&e[0]!==`--service`||await bi([],t)}async function yi(e,t){let n=e.indexOf(`--service`),r=e.indexOf(`--token`);if(n===-1||r===-1){t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.serviceLoginUsage`));return}let i=e[n+1],a=e[r+1];if(!i||!a){t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.serviceLoginNeedValues`));return}let o=i.replace(/\/+$/,``);try{let e=await fetch(`${o}/auth/login`,{method:`POST`,headers:{Authorization:`Bearer ${a}`,Accept:`application/json`}});if(!e.ok){let n=(await e.json().catch(()=>({}))).error??e.statusText;t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.serviceLoginFailed`,{err:String(n)}));return}let n=await e.json();if(typeof n.user_id!=`string`||typeof n.token!=`string`){t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.serviceLoginBadResponse`));return}let{OTTO_IDENTITY_PATH:r,isShadowModeEnabled:i}=await import(`@x-otto/env`);if(i()){t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.serviceLoginSuccess`,{url:o,user:n.user_id.slice(0,12)}));return}let{mkdir:s}=await import(`node:fs/promises`),{dirname:c}=await import(`node:path`),{atomicWriteFile:l}=await import(`@x-otto/persistence`),u={userId:n.user_id,token:n.token,serviceUrl:o,loginAt:Date.now()};await s(c(r),{recursive:!0}),await l(r,JSON.stringify(u,null,2)),t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.serviceLoginSuccess`,{url:o,user:n.user_id.slice(0,12)}))}catch(e){t.tui.info.showToast(N.t(`cmd.titleLogin`),N.t(`cmd.serviceLoginFailed`,{err:e instanceof Error?e.message:String(e)}))}}async function bi(e,t){try{let{OTTO_IDENTITY_PATH:e}=await import(`@x-otto/env`),{unlink:n}=await import(`node:fs/promises`);await n(e),t.tui.info.showToast(N.t(`cmd.titleLogout`),N.t(`cmd.logoutAccountRemoved`))}catch(e){if(e.code===`ENOENT`){t.tui.info.showToast(N.t(`cmd.titleLogout`),N.t(`cmd.logoutAccountNotFound`));return}t.tui.info.showToast(N.t(`cmd.titleLogout`),N.t(`cmd.logoutAccountFailed`,{err:e instanceof Error?e.message:String(e)}))}}async function X(e,t){let n=e[0]?.toLowerCase();if(n===`perf`)return Ci(e.slice(1),t);if(n===`cache`||n===`cache-stats`)return wi(e.slice(1),t);if(n===`diagnose`)return Ln(e.slice(1),t);if(n===`services`)return Qr(e.slice(1),t);let r=t.state.session,i=r.session,a=i.messages(),o=0;for(let e=a.length-1;e>=0;e--){let t=a[e]?.usage;if(a[e]?.role===`assistant`&&t){o=(t.cacheReadTokens??0)+(t.cacheWriteTokens??0)+(t.inputTokens??0)+(t.outputTokens??0);break}}let s=r.model?.contextWindow,c=s&&s>0?Math.round(o/s*100):void 0,l=a.reduce((e,t)=>e+(t.usage?.outputTokens??0),0),u=Ee(i.metadata().title,i.messages(),r.id),d=t.callbacks.isWriteLeaseReadOnly(),f=[{kind:`row`,label:N.t(`cmd.statusRowTitle`),value:u},{kind:`row`,label:N.t(`cmd.statusRowSessionId`),value:r.id.slice(0,8)},{kind:`row`,label:N.t(`cmd.statusRowModel`),value:r.model?.id??N.t(`cmd.statusModelUnset`)},{kind:`row`,label:N.t(`cmd.statusRowMsgs`),value:String(a.length)},{kind:`row`,label:N.t(`cmd.statusRowOccupancy`),value:N.t(`cmd.statusValueOccupancy`,{occ:o.toLocaleString(),window:s?.toLocaleString()??`N/A`,seg:c===void 0?``:` (${c}%)`})},{kind:`row`,label:N.t(`cmd.statusRowCumOutput`),value:l.toLocaleString()},{kind:`row`,label:N.t(`cmd.statusRowWriteAccess`),value:d?N.t(`cmd.statusValueWriteLeaseReadOnly`):N.t(`cmd.statusValueWriteLeaseOk`),tone:d?`warning`:void 0}];t.callbacks.isRunPaused()&&f.push({kind:`blank`},{kind:`text`,value:N.t(`cmd.statusLineRunPaused`),tone:`warning`}),t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleStatus`),lines:[],dataListEntries:f})}function xi(){let e=process.env.OTTO_NOTIFY_COALESCE_WARN_RATIO,t=e?Number(e):NaN;return Number.isFinite(t)&&t>=1?t:1.5}function Si(e,t){return t===0?`healthy`:e<xi()?`warning`:`healthy`}async function Ci(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:Si(r,n.coalescedCalls)}});let i=t.app.activePlugins();try{let e=await oe(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 wi(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:pt(t,e.api)}}),i=r.some(e=>e.hitRatio!==null),a={inputTokens:n.totalInputTokens,outputTokens:0,cacheReadTokens:n.totalCacheReadTokens,cacheWriteTokens:n.totalCacheWriteTokens},o=i?pt(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 Ti(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 Ei(e){return new Date(e*1e3).toLocaleString()}async function Di(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:N.t(`cmd.titleUsage`),lines:[N.t(`cmd.usageNotSubscription`)]});return}let r=t.callbacks.getLastProviderUsage();if(!r){t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleUsage`),lines:[N.t(`cmd.usageNoSnapshotYet`)]});return}let i=[],a=n===`anthropic`;if(r.limitType&&i.push(N.t(`cmd.usageLineType`,{type:Ze(r.limitType)})),(a||r.usedPercent!==void 0)&&i.push(N.t(`cmd.usageLineStatus`,{status:r.status})),r.usedPercent!==void 0&&i.push(N.t(`cmd.usageLinePercent`,{pct:Math.round(r.usedPercent)})),r.resetsAt!==void 0&&i.push(N.t(`cmd.usageLineResetsAt`,{when:Ei(r.resetsAt)})),r.standardLimits){let e=r.standardLimits;i.push(N.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(N.t(`cmd.usageSubPoolNotInHeaders`))),t.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleUsage`),lines:i})}const Oi=async(e,t)=>{let n=e[0];switch(n){case`memory-sync`:return ki(e.slice(1),t);default:t.tui.info.showToast(`Workspace`,`/workspace ${n??``} — unknown subcommand. Use: memory-sync [status|enable|disable]`)}};async function ki(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 Ai(t,n){let r=n.state.session,i=r.model?.id??N.t(`cmd.aboutModelNotSet`),a=h().length,o=Math.round(y()/(1024*1024*1024)),s=Math.round(g()/(1024*1024)),c=[{kind:`group`,title:N.t(`cmd.aboutGroupVersion`)},{kind:`row`,label:N.t(`cmd.aboutVersion`),value:`${ze} (build ${Le})`},{kind:`row`,label:N.t(`cmd.aboutBranch`),value:`dev`},{kind:`row`,label:N.t(`cmd.aboutCommit`),value:e},{kind:`group`,title:N.t(`cmd.aboutGroupRuntime`)},{kind:`row`,label:N.t(`cmd.aboutRuntime`),value:`Node.js ${process.version} · ${v()} ${m()} · ${ee()}`,tone:`muted`},{kind:`row`,label:N.t(`cmd.aboutCPU`),value:`${a} cores`,tone:`muted`},{kind:`row`,label:N.t(`cmd.aboutMemory`),value:`${o} GB total / ${Math.round(s)} MB free`,tone:`muted`},{kind:`row`,label:N.t(`cmd.aboutShell`),value:process.env.SHELL??`(unknown)`,tone:`muted`},{kind:`row`,label:N.t(`cmd.aboutTerminal`),value:process.env.TERM??`(unknown)`,tone:`muted`},{kind:`group`,title:N.t(`cmd.aboutGroupSession`)},{kind:`row`,label:N.t(`cmd.aboutModel`),value:i,tone:`secondary`}];r.id&&c.push({kind:`row`,label:N.t(`cmd.aboutSession`),value:r.id.slice(0,8)}),c.push({kind:`blank`},{kind:`text`,value:N.t(`cmd.aboutUpdateHint`),tone:`muted`}),n.tui.modal.openModal({kind:`info`,title:N.t(`cmd.titleAbout`),lines:[],dataListEntries:c})}async function ji(e,t){return e.tui.modal.openModal({kind:`input`,...t})}function Mi(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 Ni(e,t){let n=t.app.feedbackRegistry.get();if(!n){t.tui.info.showToast(N.t(`cmd.titleFeedback`),N.t(`cmd.feedbackUnavailable`));return}let r=e.indexOf(`--repo`),i=r>=0?e[r+1]:void 0,a=await d({configuredRepo:t.app.settings.get(`feedback_repo`),cliRepoArg:i,cwd:t.app.workspaceDir});if(!a){t.tui.info.showToast(N.t(`cmd.titleFeedback`),N.t(`cmd.feedbackRepoUnresolved`));return}let o=await ji(t,{title:N.t(`cmd.feedbackStepTitle`)});if(!o||o.trim().length===0)return;let s=await ji(t,{title:N.t(`cmd.feedbackStepRepro`)})??void 0,c=await ji(t,{title:N.t(`cmd.feedbackStepExpected`)})??void 0,l=await ji(t,{title:N.t(`cmd.feedbackStepActual`)})??void 0,u=f(t.state.session.model?.id),p={title:o.trim(),reproduce:s,expected:c,actual:l,envInfo:u,repo:a},m=[s,c,l].filter(Boolean).join(`
18
- `).slice(0,300);if(!await Mi(t,N.t(`cmd.feedbackConfirmTitle`),N.t(`cmd.feedbackConfirmMessage`,{title:p.title,bodyPreview:m})))return;if(t.tui.info.showToast(N.t(`cmd.titleFeedback`),N.t(`cmd.feedbackChannelSubmitting`)),n.submitIssueViaGh){let e=await n.submitIssueViaGh(p);if(e.ok){t.tui.info.showToast(N.t(`cmd.titleFeedback`),N.t(`cmd.feedbackCreated`,{url:e.url}));return}}let h=n.buildIssueUrl?.(p);if(!h){t.tui.info.showToast(N.t(`cmd.titleFeedback`),N.t(`cmd.feedbackUnavailable`));return}Fe(h),t.tui.info.showToast(N.t(`cmd.titleFeedback`),N.t(`cmd.feedbackCreated`,{url:h}))}function Pi(e,t,n){let r=Te(e,t);if(r)return r;let i=e.split(`/`).pop();if(i)return ue({cwd:t??process.cwd(),homedir:n??_()}).find(e=>e.id===i)?.dir}function Fi(e,t,n){try{let r=Pi(e,t,n);if(!r)return;let i=O(r,T),a=ve(A(i,`utf-8`),i);return a?a.codeProviderIds?.[0]??a.contributes?.providers?.[0]?.id??a.contributes?.oauth?.[0]?.id:void 0}catch{return}}function Ii(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 Li={provider:`install-provider`,authentication:`connect-provider`,model:`choose-model`,ready:`send-first-prompt`,"first-prompt":`none`};function Ri(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 zi(e){let t=Ri(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:Li[t],stage:t,autoOpen:o}}}function Bi(e){return e.stage===`ready`||e.stage===`first-prompt`}function Vi(e,t){return e.get(t)===!0}function Hi(e){return{personalizationSeen:Vi(e,`has_completed_onboarding`),dismissed:Vi(e,`has_completed_wizard`)||Vi(e,`wizard_dont_show_again`),firstPromptSubmitted:typeof e.get(`first_prompt_submitted_at`)==`number`}}const Ui=`__otto_setup__`;async function Wi(e){let t=Hi(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!==Ui),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!==Ui?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 zi({providerInstalled:e.hasProviderPlugin(),...e.providerCandidates?{providerCandidates:e.providerCandidates}:{},connectedProviderIds:r,usableModelIds:a,...o!==void 0&&o!==Ui?{selectedModelId:o}:{},...c===void 0?{}:{selectedModelUsableInMainSession:c},firstPromptSubmitted:t.firstPromptSubmitted,dismissed:t.dismissed})}function Gi(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,...e.isModelUsableInMainSession?{isModelUsableInMainSession:e.isModelUsableInMainSession}:{},getSelectedModelId:e.selectedModelId,settings:{get:t=>e.settings.get(t)},...e.providerCandidates?{providerCandidates:e.providerCandidates}:{}}}var Ki=class{snapshot=null;listeners=new Set;constructor(e){this.deps=e}current(){return this.snapshot}async refresh(){let e=await Wi(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 qi(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 Ji(e,t){return e.map((e,n)=>({provider:e,index:n,rank:qi(e,t)})).sort((e,t)=>e.rank-t.rank||e.index-t.index).map(e=>e.provider)}function Yi(e){try{let{createRequire:t}=bt(`node:module`),{readFileSync:n}=bt(`node:fs`),{dirname:r,join:i}=bt(`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 Xi(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=Zi(t);return t.map(e=>({...e,recommended:e.usable&&e.id===n}))}function Zi(e){return e.find(e=>e.usable)?.id}const Qi={hasReadme:!1,hasPackageManifest:!1,hasTestConfig:!1,isEmpty:!1},$i=new Set([`node_modules`,`.git`,`.hg`,`.svn`,`.venv`,`venv`,`__pycache__`,`.pytest_cache`,`.mypy_cache`,`.tox`,`dist`,`build`,`.next`,`.nuxt`,`.cache`,`.DS_Store`]),ea=/^readme(\.(md|markdown|txt|rst))?$/i,ta=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`]),na=/^(jest\.config|vitest\.config|karma\.conf|\.mocharc)(\.(js|ts|mjs|cjs|json))?$/i,ra=new Set([`pytest.ini`,`tox.ini`,`phpunit.xml`,`phpunit.xml.dist`,`setup.cfg`]);async function ia(e,t){let n;try{n=await t.readdir(e)}catch{return Qi}let r=n.filter(e=>!$i.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&&ea.test(e.name)&&(a=!0),!o&&ta.has(e.name)&&(o=!0),!s&&(ra.has(e.name)||na.test(e.name))&&(s=!0),a&&o&&s)))break;return{hasReadme:a,hasPackageManifest:o,hasTestConfig:s,isEmpty:i}}function aa(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 oa=`oxygen-provider`,sa=new Set([`plugin-oxygen`,oa]);async function ca(e){try{let{makeRegistryClient:t}=await import(`./registry-BOX7DaxS.js`),{registries:n}=await t(e.app).loadAll();return n.some(e=>e.entries.some(e=>sa.has(e.id)||e.source===`@x-otto/plugin-oxygen`||e.source.includes(`/plugin-oxygen`)||e.subPath?.endsWith(`plugin-oxygen`)))}catch{return!1}}async function la(e){let t=e.tui,n=e.app,r=await Wi(Gi({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>e.state.session?.model?.id,isModelUsable:P(n.authStore,`delegation`),isModelUsableInMainSession:P(n.authStore,`main-session`)})),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 ca(e),l=Object.entries(o).filter(([e,t])=>t.capabilities.includes(`provider`)&&(e!==oa||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=Ji(l.map(([e,t])=>({id:e,...Yi(t.pkg)})),process.env).map(({id:e})=>({label:e,value:e,detail:u[e]??o[e]?.pkg??e})),f=e=>Ii(e,n.authStore.oauth,{oauth:{label:N.t(`setup.loginOAuth`),detail:`Open browser, complete authorization — no copy-paste needed.`},apiKey:{label:N.t(`setup.loginApiKey`),detail:`Generate a key on your provider dashboard and paste it here.`}}),p=async()=>{let t=await Wi(Gi({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>e.state.session?.model?.id,isModelUsable:P(n.authStore,`delegation`),isModelUsableInMainSession:P(n.authStore,`main-session`)})),r=P(n.authStore,`delegation`),i=new Set(t.model.usableIds),a=n.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`);return Xi((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=aa(await ia(n.workspaceDir,{readdir:e=>at(e,{withFileTypes:!0})})).map(e=>N.t(e));t.modal.openModal({kind:`wizard`,title:N.t(`setup.title`),welcomeTitle:N.t(`setup.welcomeTitle`),welcomeGreeting:``,welcomeDescription:N.t(`setup.welcomeDescription`),welcomeDontShowAgainLabel:N.t(`setup.welcomeDontShowAgain`),welcomeStartLabel:N.t(`setup.welcomeStart`),welcomeCancelLabel:N.t(`setup.welcomeCancel`),stepNames:[N.t(`setup.stepNameProvider`),N.t(`setup.stepNameLogin`),N.t(`setup.stepNameModel`),N.t(`setup.stepNameStart`)],stepSubtitles:[N.t(`setup.step1Subtitle`),N.t(`setup.step3Subtitle`),N.t(`setup.step4Subtitle`),N.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 Promise.resolve().then(()=>ei),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:N.t(`setup.installFailed`,{reason:t})};let c=[];try{let{readHighRiskCapabilities:e}=await import(`@x-otto/coding`),t=Pi(s);t&&(c=e(t))}catch{}return{ok:!0,providerId:Fi(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 ua(e,t){await la(t)}let da;function fa(e){da=e}const pa=async(e,t)=>{let n=da;if(!n){t.tui.info.showToast(`Schedule`,`Schedule system not available`);return}let r=e[0];switch(r){case void 0:return ma(t);case`list`:return ha(n,t);case`add`:return ga(e.slice(1),n,t);case`remove`:return _a(e[1],n,t);case`run`:return va(e[1],n,t);case`enable`:return ba(e[1],!0,n,t);case`disable`:return ba(e[1],!1,n,t);case`logs`:return xa(e[1],t);case`cancel`:return ya(e[1],t);default:t.tui.info.showToast(`Schedule`,`/schedule ${r} — unknown subcommand. Use: add|list|remove|run|enable|disable|cancel|logs`)}};async function ma(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 ha(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(`
19
- `)}),t.tui.panes.togglePane?.(`schedulePane`)}async function ga(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`),ma(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 _a(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 va(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 ya(e,t){let n=da;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 ba(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 xa(e,t){let n=Ve(Re,`schedule-logs`),r;try{r=Ge(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=A(Ve(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(`
20
- `)})}function Z(e){return dn(e.state.session.session.getDrafts()??[])}function Sa(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 Ca=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return wa(e.slice(1),t);case`save`:return Ta(e.slice(1),t);case`load`:return Ea(e.slice(1),t);case`delete`:case`remove`:return Da(e.slice(1),t);default:t.tui.info.showToast(`Draft`,`/draft ${n} — unknown subcommand. Use: save|list|load|delete`)}};async function wa(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 Ta(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=pn(a,o,s),l=mn([...s,c]);try{Sa(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 Ea(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 Da(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{Sa(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 Oa=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return ka(t);case`remove`:return Aa(e[1],t);case`move`:return ja(e[1],e[2],t);case`clear`:return Ma(t);default:t.tui.info.showToast(`Queue`,`/queue ${n} — unknown subcommand. Use: list|remove|move|clear`)}};async function ka(e){e.tui.panes.togglePane(`queuePane`,!0)}async function Aa(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 ja(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 Ma(e){e.tui.panes.clearQueue(),e.tui.info.showToast(`Queue`,`Queue cleared`)}const Na=async(e,t)=>{let{session:n,agentProcessing:r}=t.state;if(n.isPaused&&!n.isBusy){n.resumeRun(),t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.runResumedByCommand`)),Pa(t);return}if(n.isPaused&&n.isBusy){n.cancelPauseRun()?t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.pauseCancelled`)):(n.resumeRun(),t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.runResumedByCommand`))),Pa(t);return}if(r){n.pauseRun()?t.tui.info.showToast(N.t(`cmd.titlePauseRequested`),N.t(`cmd.runWillPauseAfterTurn`)):t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.noRunningTaskToPause`)),Pa(t);return}t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.nothingToPause`))};function Pa(e){let t=e.callbacks.refreshSlashCommands?.();t&&e.tui.plugins.setCommands(t)}function Fa(e){let t;try{let n=Ue(e,`r`);try{t=Buffer.alloc(512);let e=We(n,t,0,512,0);t=t.subarray(0,e)}finally{He(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 Ia(e){return e>=1048576?`${(e/1048576).toFixed(1)} MB`:e>=1024?`${(e/1024).toFixed(1)} KB`:`${e} B`}function La(e){let t;try{t=Ge(e)}catch{return[]}let n=[];for(let r of t)try{let t=j(O(e,r));n.push({name:r,isDir:t.isDirectory(),size:t.isDirectory()?void 0:t.size})}catch{}return n}function Ra(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=Ra(La(n)),a=Be(t,n),o=a===``?N.t(`cmd.openBrowserSubtitleRoot`):N.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:Ia(e.size??0)}));e.tui.modal.openModal({kind:`select`,title:N.t(`cmd.titleOpen`),subtitle:o,searchable:!0,options:c,initialFilter:r.get(n)??``,onFilterChange:e=>{r.set(n,e)},onSelect:i=>{let a=O(n,i),o;try{o=j(a).isDirectory()}catch{e.tui.info.showToast(N.t(`cmd.titleOpen`),N.t(`cmd.openNotFound`,{path:i}));return}if(o){Q(e,t,a,r);return}za(e,a,i,()=>{Q(e,t,n,r)}).catch(()=>{e.tui.info.showToast(N.t(`cmd.titleOpen`),N.t(`cmd.openNotFound`,{path:i}))})},onCancel:s?()=>Q(e,t,D(n),r):()=>{}})}async function za(e,t,n,r){if(Fa(t)){e.tui.info.showToast(N.t(`cmd.titleOpen`),N.t(`cmd.openBinaryRejected`,{path:n}));return}let{content:i,truncated:a}=await Ie(t);e.tui.modal.openModal({kind:`fileViewer`,path:n,content:i,preTruncated:a,onDismiss:r??(()=>{})})}async function Ba(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=Ve(n,r),o=Be(n,a).startsWith(`..`);if(!k(a)){if(o){t.tui.info.showToast(N.t(`cmd.titleOpen`),N.t(`cmd.openNotFound`,{path:r}));return}let e=D(a);for(;e!==n&&e!==D(e)&&!k(e);)e=D(e);if(k(e)&&j(e).isDirectory()){Q(t,n,e,i);return}t.tui.info.showToast(N.t(`cmd.titleOpen`),N.t(`cmd.openNotFound`,{path:r}));return}if(j(a).isDirectory()){if(o){t.tui.info.showToast(N.t(`cmd.titleOpen`),N.t(`cmd.openNotFound`,{path:r}));return}Q(t,n,a,i);return}await za(t,a,r)}var Va=yt({DISPATCHABLE_COMMAND_NAMES:()=>Ga,ENGINE_BUILTIN_COMMANDS:()=>Wa,HELP_GROUP_ORDER:()=>Ha,SAFE_COMMAND_NAMES:()=>Ua,SLASH_COMMANDS:()=>$,dispatchSlashCommand:()=>Ka,handleMemory:()=>jn});const Ha=[`session`,`model`,`agent`,`debug`,`ui`,`other`],$=[{name:`clear`,handler:Nn,engineBuiltin:!0,group:`session`,description:`Clear screen and reset interface state`},{name:`compact`,handler:(e,t)=>U([`compact`,...e],t),group:`session`,tuiHidden:!0,deprecated:!0,description:`/session compact (deprecated alias)`},{name:`memory`,aliases:[`mem`],handler:jn,group:`session`,description:`Project + user memory: /memory [user|project|<name>|forget <name>]`},{name:`workspace`,handler:Oi,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:X,safe:!0,engineBuiltin:!0,group:`session`,description:`Session status & diagnostics: /status [perf|cache|diagnose|services] (RFC-369)`},{name:`open`,handler:Ba,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:gi,group:`model`,description:`Switch model; /model [<id>|refresh]`},{name:`auth`,aliases:[`login`],handler:Y,group:`model`,description:`Connect a model provider (OAuth or API key); /auth [<provider>], /auth logout [<provider>] clears stored credentials`},{name:`usage`,handler:Di,safe:!0,engineBuiltin:!0,group:`model`,description:`Show provider usage quota snapshot (Anthropic OAuth subscription plans only)`},{name:`logout`,handler:vi,group:`model`,description:`Sign out of your otto account (removes local account identity); /logout`},{name:`job`,handler:ui,safe:!0,group:`agent`,description:`Start a background agent job: /job <directive> (worktree-isolated, full tools incl. MCP)`},{name:`schedule`,handler:pa,safe:!0,group:`agent`,description:`Manage scheduled tasks: /schedule add|list|remove|run|enable|disable <args>`},{name:`delegates`,handler:li,safe:!0,group:`agent`,description:`Toggle the Delegates panel (↑↓ select · k kill · o output · a apply)`},{name:`diagnose`,handler:(e,t)=>X([`diagnose`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/status diagnose (deprecated alias)`},{name:`context`,handler:(e,t)=>U([`context`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/session context (deprecated alias)`},{name:`perf`,handler:(e,t)=>X([`perf`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/status perf (deprecated alias)`},{name:`cache-stats`,handler:(e,t)=>X([`cache-stats`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/status cache (deprecated alias)`},{name:`services`,handler:(e,t)=>X([`services`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/status services (deprecated alias)`},{name:`gallery`,handler:Ti,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:Gn,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:qn,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:(e,t)=>G([`effort`,...e],t),group:`ui`,tuiHidden:!0,deprecated:!0,description:`/preference effort (deprecated alias)`},{name:`preference`,aliases:[`pref`],handler:G,safe:!0,group:`ui`,description:`Preferences: /preference [general|lang|theme|keybindings|shortcuts|effort|proxy] (RFC-369)`},{name:`trust`,handler:(e,t)=>J([`trust`,...e],t),safe:!0,group:`ui`,tuiHidden:!0,deprecated:!0,description:`/extension trust (deprecated alias)`},{name:`notification`,aliases:[`notif`],handler:Xr,group:`ui`,description:`Toggle the notification center panel (≡ ctrl+n)`},{name:`draft`,handler:Ca,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:Oa,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:(e,t)=>G([`keybindings`,...e],t),safe:!0,group:`ui`,tuiHidden:!0,deprecated:!0,description:`/preference keybindings (deprecated alias)`},{name:`shortcuts`,handler:(e,t)=>G([`shortcuts`,...e],t),safe:!0,group:`ui`,tuiHidden:!0,deprecated:!0,description:`/preference shortcuts (deprecated alias)`},{name:`proxy`,handler:(e,t)=>G([`proxy`,...e],t),group:`ui`,tuiHidden:!0,deprecated:!0,description:`/preference proxy (deprecated alias)`},{name:`help`,aliases:[`h`,`?`],safe:!0,engineBuiltin:!0,group:`other`,description:`Show available commands`,handler:async(e,t)=>Jr(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:Na,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:(e,t)=>U([`resume`,...e],t),group:`other`,tuiHidden:!0,deprecated:!0,description:`/session resume (deprecated alias)`},{name:`rename`,handler:Pn,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:In,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 $r(e,t);return}await qr(e,t)||await Kr(e,t)}},{name:`about`,handler:Ai,safe:!0,group:`other`,description:`Show version, build, and environment info (/about)`},{name:`setup`,handler:ua,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:J,group:`other`,description:`Manage extensions: /extension [trust|install|registry|search|update] or open panel (RFC-369)`},{name:`install`,handler:(e,t)=>J([`install`,...e],t),safe:!0,group:`other`,tuiHidden:!0,deprecated:!0,description:`/extension install (deprecated alias)`},{name:`registry`,handler:(e,t)=>J([`registry`,...e],t),safe:!0,group:`other`,tuiHidden:!0,deprecated:!0,description:`/extension registry (deprecated alias)`},{name:`search`,handler:(e,t)=>J([`search`,...e],t),safe:!0,group:`other`,tuiHidden:!0,deprecated:!0,description:`/extension search (deprecated alias)`},{name:`permissions`,aliases:[`perms`],handler:Gr,safe:!0,group:`other`,description:`View / clear the always-allow list (/permissions [clear])`},{name:`feedback`,handler:Ni,group:`other`,description:`Report an issue or send feedback via GitHub (/feedback [--repo <owner/repo>])`},{name:`archive`,aliases:[`unarchive`],handler:(e,t)=>U([`archive`,...e],t),safe:!0,tuiHidden:!0,deprecated:!0,description:`/session archive (deprecated alias)`},{name:`session`,handler:U,description:`Session management: /session [fork|unlock|kill|inspect|pin|archive|resume|compact|context] (RFC-369)`},{name:`fork`,handler:Yn,safe:!0,description:`Fork current session into a named branch`},{name:`pin`,aliases:[`unpin`],handler:(e,t)=>U([`pin`,...e],t),safe:!0,tuiHidden:!0,deprecated:!0,description:`/session pin (deprecated alias)`},{name:`history`,aliases:[`hist`],handler:Yr,safe:!0,description:`Open history search panel (same panel as Ctrl+R)`},{name:`prompts`,handler:Zr,safe:!0,description:`View prompt log (list of submitted prompts this session)`}],Ua=new Set($.filter(e=>e.safe).flatMap(e=>[e.name,...e.aliases??[]])),Wa=new Set($.filter(e=>e.engineBuiltin).flatMap(e=>[e.name,...e.aliases??[]])),Ga=new Set($.filter(e=>e.handler).flatMap(e=>[e.name,...e.aliases??[]]));async function Ka(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{Rt as $,sr as A,Ke as B,mr as C,cr as D,gr as E,gn as F,an as G,et as H,mn as I,F as J,Kt as K,pn as L,xn as M,z as N,or as O,hn as P,Gt as Q,dn as R,W as S,hr as T,I as U,Je as V,on as W,Jt as X,qt as Y,Qt as Z,Dr as _,Va as a,Tt as at,br as b,ia as c,Gi as d,Lt as et,Bi as f,ei as g,di as h,$ as i,Et as it,kn as j,ar as k,aa as l,Y as m,Wa as n,kt as nt,Ka as o,yt as ot,gi as p,Yt as q,Ua as r,Dt as rt,fa as s,Ga as t,Ot as tt,Ki as u,yr as v,fr as w,_r as x,Sr as y,un as z};
21
- //# sourceMappingURL=command-dispatcher-DLUFMLi1.js.map
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import{r as e}from"./feedback-rhp8Et4E.js";export{e as runFeedbackCommand};