@x-otto/cli 0.0.1-alpha.53 → 0.0.1-alpha.55

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.
Files changed (42) hide show
  1. package/dist/{auth-command--ky3JspQ.js → auth-command-Cw71Gud0.js} +2 -2
  2. package/dist/{auth-command--ky3JspQ.js.map → auth-command-Cw71Gud0.js.map} +1 -1
  3. package/dist/build-id-9kqTcA9R.js +3 -0
  4. package/dist/build-id-9kqTcA9R.js.map +1 -0
  5. package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/meta.json +1 -1
  6. package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/plugin.cjs +195 -161
  7. package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin.ts +4 -0
  8. package/dist/bundled-extensions/plugin-otto-wire-protocols/src/anthropic-messages.ts +9 -1
  9. package/dist/bundled-extensions/plugin-otto-wire-protocols/src/openai-completions.ts +11 -1
  10. package/dist/bundled-extensions/plugin-otto-wire-protocols/src/openai-responses.ts +9 -1
  11. package/dist/command-dispatcher-W3E5zhWN.js +18 -0
  12. package/dist/command-dispatcher-W3E5zhWN.js.map +1 -0
  13. package/dist/create-host-app-_xUKDWy7.js +3 -0
  14. package/dist/{create-host-app-BtifD7KK.js.map → create-host-app-_xUKDWy7.js.map} +1 -1
  15. package/dist/{doctor-BAxvhLws.js → doctor-BDEllJgc.js} +2 -2
  16. package/dist/{doctor-BAxvhLws.js.map → doctor-BDEllJgc.js.map} +1 -1
  17. package/dist/{feedback-CJVKfI0S.js → feedback-CqTWm_TD.js} +10 -10
  18. package/dist/{feedback-CJVKfI0S.js.map → feedback-CqTWm_TD.js.map} +1 -1
  19. package/dist/{feedback-backend-methods-C23Z2suw.js → feedback-backend-methods-3CMRkGoJ.js} +2 -2
  20. package/dist/{feedback-backend-methods-C23Z2suw.js.map → feedback-backend-methods-3CMRkGoJ.js.map} +1 -1
  21. package/dist/index.js +7 -7
  22. package/dist/index.js.map +1 -1
  23. package/dist/{interactive-schedule-BKiI3Qrw.js → interactive-schedule-D0NOMjB7.js} +2 -2
  24. package/dist/{interactive-schedule-BKiI3Qrw.js.map → interactive-schedule-D0NOMjB7.js.map} +1 -1
  25. package/dist/{mcp-server-CfJK4pav.js → mcp-server-kME-VSX4.js} +2 -2
  26. package/dist/{mcp-server-CfJK4pav.js.map → mcp-server-kME-VSX4.js.map} +1 -1
  27. package/dist/{parse-cli-B9Go-f6A.js → parse-cli-Byh6vJ3e.js} +2 -2
  28. package/dist/{parse-cli-B9Go-f6A.js.map → parse-cli-Byh6vJ3e.js.map} +1 -1
  29. package/dist/schedule-C_uHI2M8.js +5 -0
  30. package/dist/schedule-C_uHI2M8.js.map +1 -0
  31. package/dist/{serve-ChSSkjLs.js → serve-Di0fC7-B.js} +2 -2
  32. package/dist/{serve-ChSSkjLs.js.map → serve-Di0fC7-B.js.map} +1 -1
  33. package/dist/{version-BL66TSQP.js → version-CHEEY4Vx.js} +2 -2
  34. package/dist/{version-BL66TSQP.js.map → version-CHEEY4Vx.js.map} +1 -1
  35. package/package.json +18 -18
  36. package/dist/build-id-C94zHRXj.js +0 -3
  37. package/dist/build-id-C94zHRXj.js.map +0 -1
  38. package/dist/command-dispatcher-CKj6qR-G.js +0 -18
  39. package/dist/command-dispatcher-CKj6qR-G.js.map +0 -1
  40. package/dist/create-host-app-BtifD7KK.js +0 -3
  41. package/dist/schedule-Ke0jwatM.js +0 -5
  42. package/dist/schedule-Ke0jwatM.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"serve-ChSSkjLs.js","names":[],"sources":["../src/commands/serve.ts"],"sourcesContent":["import type { AddressInfo } from 'node:net'\nimport { resolve } from 'node:path'\nimport { SERVICE_PORT } from '@x-otto/env'\nimport { createHostApp } from '../create-host-app'\nimport { createCodingService } from '@x-otto/service'\nimport type { AppContext } from '@x-otto/coding'\n\nimport { waitForShutdown } from './daemon-base'\n\nexport interface ServeDeps {\n stdout?: (s: string) => void\n stderr?: (s: string) => void\n /** 全局 CLI 选项透传(与 `otto run` 同源装配)。 */\n projectDir?: string\n configPath?: string\n modelId?: string\n verbose?: boolean\n /** 测试注入:替代生产装配的 app(结构 = AppContext + start/stop)。 */\n app?: AppContext & { start(): Promise<void>; stop(): Promise<void> }\n /** 测试注入:优雅退出信号(生产 = SIGINT/SIGTERM)。 */\n signal?: AbortSignal\n}\n\nexport async function runServeCommand(args: string[], deps: ServeDeps = {}): Promise<number> {\n const stdout = deps.stdout ?? ((s) => process.stdout.write(s))\n const stderr = deps.stderr ?? ((s) => process.stderr.write(s))\n\n if (args[0] === 'help' || args[0] === '--help') {\n printHelp(stdout)\n return 0\n }\n\n let port: number\n let inspect: boolean\n let staticDir: string | undefined\n let token: string | undefined\n /** RFC-435 D2:serve headless scheduler(无人值守定时任务)。退出时 stop 释放 ownership。 */\n let appScheduler: { stop(): Promise<void> } | undefined\n try {\n ;({ port, inspect, staticDir, token } = parseServeArgs(args))\n } catch (error) {\n stderr(`otto serve: ${error instanceof Error ? error.message : String(error)}\\n`)\n return 1\n }\n\n const app =\n deps.app ??\n createHostApp({\n logger: {\n name: 'otto-serve',\n level: deps.verbose ? 'debug' : 'info',\n destination: 'stderr',\n },\n // `--inspect` 必须下传:`AppOptions.inspect` 是 `buildInspectDevtools` 的唯一开关\n // (devtools-setup.ts:19 `if (!inspect) return { devtools: null }`)。此前 serve 解析了\n // 该 flag、也据它打印\"调试器已启用\"提示,却从未传给 createApp —— 于是 `app.devtools`\n // 恒为 null,`/api/debugger/*` 全部 503、DebugBridge 也不会被构造。即 `otto serve\n // --inspect` 实际从不启用调试器(提示与事实相反)。\n inspect,\n workspaceDir: deps.projectDir,\n projectConfigPath: deps.configPath,\n modelId: deps.modelId,\n })\n\n try {\n await app.start()\n } catch (error) {\n stderr(`otto serve: failed to start app: ${error instanceof Error ? error.message : String(error)}\\n`)\n return 1\n }\n\n // RFC-435 D2:serve/daemon 无人值守装配 headless SchedulerService——job/subscriber 类\n // cron 任务在交互会话关闭后仍到点执行(用户原始诉求\"每天凌晨自动维护文档\")。\n // 无 sessionRef/tui → job-only 形态(session 类任务跳过 + fire log 记录,RFC-435 D2)。\n // fail-soft:装配失败不阻断 serve 主功能(调度是附加能力,R3)。\n // 仅完整 App(createHostApp 生产路径)装配——测试注入的 AppContext 桩无 agentJobs/\n // panelBackendController 等调度依赖,跳过(T435-5 用 fake app 直接验证装配调用)。\n if ('agentJobs' in app && typeof app.start === 'function') {\n const { setupScheduleService } = await import('./interactive-schedule')\n const { FireLogger, DEFAULT_SCHEDULE_CONFIG } = await import('@x-otto/schedule')\n const serveFireLogger = new FireLogger(DEFAULT_SCHEDULE_CONFIG)\n try {\n const { scheduler } = setupScheduleService(app, {})\n // serve 生命周期:优雅退出时释放 ownership(stop),避免锁残留 5min stale 窗口。\n appScheduler = scheduler\n // D5:无人值守装配成功落盘可查(daemon 壳 stdio:'ignore',stderr 日志不可见)。\n serveFireLogger.write('daemon-scheduler', 'headless scheduler assembled (job-only)')\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n app.logger?.warn?.({ err: msg }, '[schedule] serve headless scheduler setup failed (non-fatal)')\n // D5:装配失败落盘——无人值守时用户第二天必须能查到调度未起。\n serveFireLogger.write('daemon-scheduler', `headless scheduler setup FAILED: ${msg}`)\n }\n }\n\n // --token 同时启用 HTTP Bearer(apiToken)与 WS ?token=(wsAuthToken);页面用 URL `?token=` 对上。\n const service = createCodingService(app, {\n port,\n host: '127.0.0.1',\n staticDir,\n apiToken: token,\n wsAuthToken: token,\n // RFC-335 M2:由 `otto daemon start` 下传,使 AuthorityDescriptor.instanceId 与\n // daemon state 记录一致(客户端据此确认\"连上的 authority 就是 state 里那个 daemon\")。\n // 前台直接 `otto serve` 时缺省,由 service 自行生成。\n authorityId: process.env['OTTO_AUTHORITY_ID'] || undefined,\n })\n\n try {\n await service.start()\n } catch (error) {\n stderr(`otto serve: failed to listen on port ${port}: ${error instanceof Error ? error.message : String(error)}\\n`)\n await app.stop()\n return 1\n }\n\n const actualPort = (service.httpServer.address() as AddressInfo).port\n // 不把 token 明文打进 stdout(会落 scrollback/CI 日志)——只提示需附加 ?token=。\n const webHint = token ? ' (打开时附加 ?token=<你的 token>)' : ''\n stdout(`otto service listening on http://127.0.0.1:${actualPort}${token ? ' (auth: token required)' : ''}\n${staticDir ? ` web: http://127.0.0.1:${actualPort}/${webHint} (静态页面同源托管 ${staticDir})\\n` : ''} panels: otto observe summary <session-id>\n otto time-travel checkpoints <session-id>\n otto debug breakpoints list${inspect ? '' : ' (debugger disabled — restart with `otto serve --inspect`)'}\n stop: Ctrl-C\n`)\n\n await waitForShutdown(deps.signal)\n\n stdout('otto serve: shutting down...\\n')\n // RFC-435 D4:先 stop scheduler(release fire ownership,避免锁残留 stale 窗口,\n // 交互会话/其他 daemon 立即可接管),再停 service/app。\n if (appScheduler) {\n try {\n await appScheduler.stop()\n } catch (error) {\n app.logger?.warn?.(\n { err: error instanceof Error ? error.message : String(error) },\n '[schedule] serve scheduler stop failed',\n )\n }\n }\n await service.stop()\n await app.stop()\n // 硬退出:service.stop()/app.stop() 可能留下孤儿 handle(worker_threads port、\n // DB pool、trace tail),吊住事件循环导致 Ctrl+C 后进程不退。与 interactive 路径\n // (cli.ts 末尾 process.exit)对齐。stdio 已同步写,无截断风险。\n process.exit(0)\n}\n\nfunction parseServeArgs(args: string[]): {\n port: number\n inspect: boolean\n staticDir?: string\n token?: string\n} {\n let port = SERVICE_PORT\n let inspect = false\n let staticDir: string | undefined\n let token: string | undefined\n\n // 取下一个值;缺失或形如 --flag(误把下个选项当值)即报错,避免静默吞掉选项。\n const takeValue = (i: number, name: string): string => {\n const raw = args[i + 1]\n if (raw === undefined || raw.startsWith('--')) {\n throw new Error(`${name} requires a value`)\n }\n return raw\n }\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (arg === '--port' || arg === '-p') {\n const raw = takeValue(i, '--port')\n i++\n const n = Number(raw)\n if (!Number.isInteger(n) || n < 0 || n > 65535) {\n throw new Error(`invalid --port value: ${raw}`)\n }\n port = n\n } else if (arg === '--inspect') {\n inspect = true\n } else if (arg === '--static') {\n staticDir = resolve(takeValue(i, '--static'))\n i++\n } else if (arg === '--token') {\n token = takeValue(i, '--token')\n i++\n }\n // 其它(含全局 flag --verbose/--model 等,经 ctx.args 透传进来)忽略——\n // 不能 throw,否则 `otto serve --verbose` 会误伤(全局 flag 由 parseCLI 已解析)。\n }\n\n return { port, inspect, staticDir, token }\n}\n\nfunction printHelp(stdout: (s: string) => void): void {\n stdout(`otto serve — 启动 HTTP/WS service(观测/调试/时间旅行面板的对端)\n\n用法:\n otto serve [--port <n>] [--inspect] [--static <dir>] [--token <t>]\n\n选项:\n --port, -p <n> 监听端口(默认 ${SERVICE_PORT},可经 OTTO_SERVICE_PORT 覆盖;0 = 随机)\n --inspect 启用调试器(断点/暂停面板需要)\n --static <dir> 同源托管一个已构建的前端目录(SPA),页面与 /api、/ws 同端口免 CORS\n --token <t> 启用鉴权:HTTP /api/* 需 Bearer,WS 需 ?token=;页面用 URL ?token=<t> 对上\n\n面板命令默认连 http://127.0.0.1:${SERVICE_PORT}(可 --remote 覆盖)\n`)\n}\n"],"mappings":";gOAuBA,eAAsB,EAAgB,EAAgB,EAAkB,EAAE,CAAmB,CAC3F,IAAM,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EACvD,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EAE7D,GAAI,EAAK,KAAO,QAAU,EAAK,KAAO,SAEpC,OADA,EAAU,EAAO,CACV,EAGT,IAAI,EACA,EACA,EACA,EAEA,EACJ,GAAI,EACA,uCAAsC,EAAe,EAAK,QACrD,EAAO,CAEd,OADA,EAAO,eAAe,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAAI,CAC1E,EAGT,IAAM,EACJ,EAAK,KACL,EAAc,CACZ,OAAQ,CACN,KAAM,aACN,MAAO,EAAK,QAAU,QAAU,OAChC,YAAa,SACd,CAMD,UACA,aAAc,EAAK,WACnB,kBAAmB,EAAK,WACxB,QAAS,EAAK,QACf,CAAC,CAEJ,GAAI,CACF,MAAM,EAAI,OAAO,OACV,EAAO,CAEd,OADA,EAAO,oCAAoC,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAAI,CAC/F,EAST,GAAI,cAAe,GAAO,OAAO,EAAI,OAAU,WAAY,CACzD,GAAM,CAAE,wBAAyB,MAAM,OAAO,sCAAA,KAAA,GAAA,EAAA,EAAA,CACxC,CAAE,aAAY,2BAA4B,MAAM,OAAO,oBACvD,EAAkB,IAAI,EAAW,EAAwB,CAC/D,GAAI,CACF,GAAM,CAAE,aAAc,EAAqB,EAAK,EAAE,CAAC,CAEnD,EAAe,EAEf,EAAgB,MAAM,mBAAoB,0CAA0C,OAC7E,EAAO,CACd,IAAM,EAAM,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAClE,EAAI,QAAQ,OAAO,CAAE,IAAK,EAAK,CAAE,+DAA+D,CAEhG,EAAgB,MAAM,mBAAoB,oCAAoC,IAAM,EAKxF,IAAM,EAAU,EAAoB,EAAK,CACvC,OACA,KAAM,YACN,YACA,SAAU,EACV,YAAa,EAIb,YAAa,QAAQ,IAAI,mBAAwB,IAAA,GAClD,CAAC,CAEF,GAAI,CACF,MAAM,EAAQ,OAAO,OACd,EAAO,CAGd,OAFA,EAAO,wCAAwC,EAAK,IAAI,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAAI,CACnH,MAAM,EAAI,MAAM,CACT,EAGT,IAAM,EAAc,EAAQ,WAAW,SAAS,CAAiB,KAejE,GAZA,EAAO,8CAA8C,IAAa,EAAQ,4BAA8B,GAAG;EAC3G,EAAY,+BAA+B,EAAW,GAFtC,EAAQ,6BAA+B,GAEU,eAAe,EAAU,KAAO,GAAG;;wCAE9D,EAAU,GAAK,+DAA+D;;EAEpH,CAEA,MAAM,EAAgB,EAAK,OAAO,CAElC,EAAO;EAAiC,CAGpC,EACF,GAAI,CACF,MAAM,EAAa,MAAM,OAClB,EAAO,CACd,EAAI,QAAQ,OACV,CAAE,IAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAE,CAC/D,yCACD,CAGL,MAAM,EAAQ,MAAM,CACpB,MAAM,EAAI,MAAM,CAIhB,QAAQ,KAAK,EAAE,CAGjB,SAAS,EAAe,EAKtB,CACA,IAAI,EAAO,EACP,EAAU,GACV,EACA,EAGE,GAAa,EAAW,IAAyB,CACrD,IAAM,EAAM,EAAK,EAAI,GACrB,GAAI,IAAQ,IAAA,IAAa,EAAI,WAAW,KAAK,CAC3C,MAAU,MAAM,GAAG,EAAK,mBAAmB,CAE7C,OAAO,GAGT,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAAK,CACpC,IAAM,EAAM,EAAK,GACjB,GAAI,IAAQ,UAAY,IAAQ,KAAM,CACpC,IAAM,EAAM,EAAU,EAAG,SAAS,CAClC,IACA,IAAM,EAAI,OAAO,EAAI,CACrB,GAAI,CAAC,OAAO,UAAU,EAAE,EAAI,EAAI,GAAK,EAAI,MACvC,MAAU,MAAM,yBAAyB,IAAM,CAEjD,EAAO,OACE,IAAQ,YACjB,EAAU,GACD,IAAQ,YACjB,EAAY,EAAQ,EAAU,EAAG,WAAW,CAAC,CAC7C,KACS,IAAQ,YACjB,EAAQ,EAAU,EAAG,UAAU,CAC/B,KAMJ,MAAO,CAAE,OAAM,UAAS,YAAW,QAAO,CAG5C,SAAS,EAAU,EAAmC,CACpD,EAAO;;;;;;6BAMoB,EAAa;;;;;2BAKf,EAAa;EACtC"}
1
+ {"version":3,"file":"serve-Di0fC7-B.js","names":[],"sources":["../src/commands/serve.ts"],"sourcesContent":["import type { AddressInfo } from 'node:net'\nimport { resolve } from 'node:path'\nimport { SERVICE_PORT } from '@x-otto/env'\nimport { createHostApp } from '../create-host-app'\nimport { createCodingService } from '@x-otto/service'\nimport type { AppContext } from '@x-otto/coding'\n\nimport { waitForShutdown } from './daemon-base'\n\nexport interface ServeDeps {\n stdout?: (s: string) => void\n stderr?: (s: string) => void\n /** 全局 CLI 选项透传(与 `otto run` 同源装配)。 */\n projectDir?: string\n configPath?: string\n modelId?: string\n verbose?: boolean\n /** 测试注入:替代生产装配的 app(结构 = AppContext + start/stop)。 */\n app?: AppContext & { start(): Promise<void>; stop(): Promise<void> }\n /** 测试注入:优雅退出信号(生产 = SIGINT/SIGTERM)。 */\n signal?: AbortSignal\n}\n\nexport async function runServeCommand(args: string[], deps: ServeDeps = {}): Promise<number> {\n const stdout = deps.stdout ?? ((s) => process.stdout.write(s))\n const stderr = deps.stderr ?? ((s) => process.stderr.write(s))\n\n if (args[0] === 'help' || args[0] === '--help') {\n printHelp(stdout)\n return 0\n }\n\n let port: number\n let inspect: boolean\n let staticDir: string | undefined\n let token: string | undefined\n /** RFC-435 D2:serve headless scheduler(无人值守定时任务)。退出时 stop 释放 ownership。 */\n let appScheduler: { stop(): Promise<void> } | undefined\n try {\n ;({ port, inspect, staticDir, token } = parseServeArgs(args))\n } catch (error) {\n stderr(`otto serve: ${error instanceof Error ? error.message : String(error)}\\n`)\n return 1\n }\n\n const app =\n deps.app ??\n createHostApp({\n logger: {\n name: 'otto-serve',\n level: deps.verbose ? 'debug' : 'info',\n destination: 'stderr',\n },\n // `--inspect` 必须下传:`AppOptions.inspect` 是 `buildInspectDevtools` 的唯一开关\n // (devtools-setup.ts:19 `if (!inspect) return { devtools: null }`)。此前 serve 解析了\n // 该 flag、也据它打印\"调试器已启用\"提示,却从未传给 createApp —— 于是 `app.devtools`\n // 恒为 null,`/api/debugger/*` 全部 503、DebugBridge 也不会被构造。即 `otto serve\n // --inspect` 实际从不启用调试器(提示与事实相反)。\n inspect,\n workspaceDir: deps.projectDir,\n projectConfigPath: deps.configPath,\n modelId: deps.modelId,\n })\n\n try {\n await app.start()\n } catch (error) {\n stderr(`otto serve: failed to start app: ${error instanceof Error ? error.message : String(error)}\\n`)\n return 1\n }\n\n // RFC-435 D2:serve/daemon 无人值守装配 headless SchedulerService——job/subscriber 类\n // cron 任务在交互会话关闭后仍到点执行(用户原始诉求\"每天凌晨自动维护文档\")。\n // 无 sessionRef/tui → job-only 形态(session 类任务跳过 + fire log 记录,RFC-435 D2)。\n // fail-soft:装配失败不阻断 serve 主功能(调度是附加能力,R3)。\n // 仅完整 App(createHostApp 生产路径)装配——测试注入的 AppContext 桩无 agentJobs/\n // panelBackendController 等调度依赖,跳过(T435-5 用 fake app 直接验证装配调用)。\n if ('agentJobs' in app && typeof app.start === 'function') {\n const { setupScheduleService } = await import('./interactive-schedule')\n const { FireLogger, DEFAULT_SCHEDULE_CONFIG } = await import('@x-otto/schedule')\n const serveFireLogger = new FireLogger(DEFAULT_SCHEDULE_CONFIG)\n try {\n const { scheduler } = setupScheduleService(app, {})\n // serve 生命周期:优雅退出时释放 ownership(stop),避免锁残留 5min stale 窗口。\n appScheduler = scheduler\n // D5:无人值守装配成功落盘可查(daemon 壳 stdio:'ignore',stderr 日志不可见)。\n serveFireLogger.write('daemon-scheduler', 'headless scheduler assembled (job-only)')\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error)\n app.logger?.warn?.({ err: msg }, '[schedule] serve headless scheduler setup failed (non-fatal)')\n // D5:装配失败落盘——无人值守时用户第二天必须能查到调度未起。\n serveFireLogger.write('daemon-scheduler', `headless scheduler setup FAILED: ${msg}`)\n }\n }\n\n // --token 同时启用 HTTP Bearer(apiToken)与 WS ?token=(wsAuthToken);页面用 URL `?token=` 对上。\n const service = createCodingService(app, {\n port,\n host: '127.0.0.1',\n staticDir,\n apiToken: token,\n wsAuthToken: token,\n // RFC-335 M2:由 `otto daemon start` 下传,使 AuthorityDescriptor.instanceId 与\n // daemon state 记录一致(客户端据此确认\"连上的 authority 就是 state 里那个 daemon\")。\n // 前台直接 `otto serve` 时缺省,由 service 自行生成。\n authorityId: process.env['OTTO_AUTHORITY_ID'] || undefined,\n })\n\n try {\n await service.start()\n } catch (error) {\n stderr(`otto serve: failed to listen on port ${port}: ${error instanceof Error ? error.message : String(error)}\\n`)\n await app.stop()\n return 1\n }\n\n const actualPort = (service.httpServer.address() as AddressInfo).port\n // 不把 token 明文打进 stdout(会落 scrollback/CI 日志)——只提示需附加 ?token=。\n const webHint = token ? ' (打开时附加 ?token=<你的 token>)' : ''\n stdout(`otto service listening on http://127.0.0.1:${actualPort}${token ? ' (auth: token required)' : ''}\n${staticDir ? ` web: http://127.0.0.1:${actualPort}/${webHint} (静态页面同源托管 ${staticDir})\\n` : ''} panels: otto observe summary <session-id>\n otto time-travel checkpoints <session-id>\n otto debug breakpoints list${inspect ? '' : ' (debugger disabled — restart with `otto serve --inspect`)'}\n stop: Ctrl-C\n`)\n\n await waitForShutdown(deps.signal)\n\n stdout('otto serve: shutting down...\\n')\n // RFC-435 D4:先 stop scheduler(release fire ownership,避免锁残留 stale 窗口,\n // 交互会话/其他 daemon 立即可接管),再停 service/app。\n if (appScheduler) {\n try {\n await appScheduler.stop()\n } catch (error) {\n app.logger?.warn?.(\n { err: error instanceof Error ? error.message : String(error) },\n '[schedule] serve scheduler stop failed',\n )\n }\n }\n await service.stop()\n await app.stop()\n // 硬退出:service.stop()/app.stop() 可能留下孤儿 handle(worker_threads port、\n // DB pool、trace tail),吊住事件循环导致 Ctrl+C 后进程不退。与 interactive 路径\n // (cli.ts 末尾 process.exit)对齐。stdio 已同步写,无截断风险。\n process.exit(0)\n}\n\nfunction parseServeArgs(args: string[]): {\n port: number\n inspect: boolean\n staticDir?: string\n token?: string\n} {\n let port = SERVICE_PORT\n let inspect = false\n let staticDir: string | undefined\n let token: string | undefined\n\n // 取下一个值;缺失或形如 --flag(误把下个选项当值)即报错,避免静默吞掉选项。\n const takeValue = (i: number, name: string): string => {\n const raw = args[i + 1]\n if (raw === undefined || raw.startsWith('--')) {\n throw new Error(`${name} requires a value`)\n }\n return raw\n }\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (arg === '--port' || arg === '-p') {\n const raw = takeValue(i, '--port')\n i++\n const n = Number(raw)\n if (!Number.isInteger(n) || n < 0 || n > 65535) {\n throw new Error(`invalid --port value: ${raw}`)\n }\n port = n\n } else if (arg === '--inspect') {\n inspect = true\n } else if (arg === '--static') {\n staticDir = resolve(takeValue(i, '--static'))\n i++\n } else if (arg === '--token') {\n token = takeValue(i, '--token')\n i++\n }\n // 其它(含全局 flag --verbose/--model 等,经 ctx.args 透传进来)忽略——\n // 不能 throw,否则 `otto serve --verbose` 会误伤(全局 flag 由 parseCLI 已解析)。\n }\n\n return { port, inspect, staticDir, token }\n}\n\nfunction printHelp(stdout: (s: string) => void): void {\n stdout(`otto serve — 启动 HTTP/WS service(观测/调试/时间旅行面板的对端)\n\n用法:\n otto serve [--port <n>] [--inspect] [--static <dir>] [--token <t>]\n\n选项:\n --port, -p <n> 监听端口(默认 ${SERVICE_PORT},可经 OTTO_SERVICE_PORT 覆盖;0 = 随机)\n --inspect 启用调试器(断点/暂停面板需要)\n --static <dir> 同源托管一个已构建的前端目录(SPA),页面与 /api、/ws 同端口免 CORS\n --token <t> 启用鉴权:HTTP /api/* 需 Bearer,WS 需 ?token=;页面用 URL ?token=<t> 对上\n\n面板命令默认连 http://127.0.0.1:${SERVICE_PORT}(可 --remote 覆盖)\n`)\n}\n"],"mappings":";gOAuBA,eAAsB,EAAgB,EAAgB,EAAkB,EAAE,CAAmB,CAC3F,IAAM,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EACvD,EAAS,EAAK,SAAY,GAAM,QAAQ,OAAO,MAAM,EAAE,EAE7D,GAAI,EAAK,KAAO,QAAU,EAAK,KAAO,SAEpC,OADA,EAAU,EAAO,CACV,EAGT,IAAI,EACA,EACA,EACA,EAEA,EACJ,GAAI,EACA,uCAAsC,EAAe,EAAK,QACrD,EAAO,CAEd,OADA,EAAO,eAAe,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAAI,CAC1E,EAGT,IAAM,EACJ,EAAK,KACL,EAAc,CACZ,OAAQ,CACN,KAAM,aACN,MAAO,EAAK,QAAU,QAAU,OAChC,YAAa,SACd,CAMD,UACA,aAAc,EAAK,WACnB,kBAAmB,EAAK,WACxB,QAAS,EAAK,QACf,CAAC,CAEJ,GAAI,CACF,MAAM,EAAI,OAAO,OACV,EAAO,CAEd,OADA,EAAO,oCAAoC,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAAI,CAC/F,EAST,GAAI,cAAe,GAAO,OAAO,EAAI,OAAU,WAAY,CACzD,GAAM,CAAE,wBAAyB,MAAM,OAAO,sCAAA,KAAA,GAAA,EAAA,EAAA,CACxC,CAAE,aAAY,2BAA4B,MAAM,OAAO,oBACvD,EAAkB,IAAI,EAAW,EAAwB,CAC/D,GAAI,CACF,GAAM,CAAE,aAAc,EAAqB,EAAK,EAAE,CAAC,CAEnD,EAAe,EAEf,EAAgB,MAAM,mBAAoB,0CAA0C,OAC7E,EAAO,CACd,IAAM,EAAM,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAClE,EAAI,QAAQ,OAAO,CAAE,IAAK,EAAK,CAAE,+DAA+D,CAEhG,EAAgB,MAAM,mBAAoB,oCAAoC,IAAM,EAKxF,IAAM,EAAU,EAAoB,EAAK,CACvC,OACA,KAAM,YACN,YACA,SAAU,EACV,YAAa,EAIb,YAAa,QAAQ,IAAI,mBAAwB,IAAA,GAClD,CAAC,CAEF,GAAI,CACF,MAAM,EAAQ,OAAO,OACd,EAAO,CAGd,OAFA,EAAO,wCAAwC,EAAK,IAAI,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAC,IAAI,CACnH,MAAM,EAAI,MAAM,CACT,EAGT,IAAM,EAAc,EAAQ,WAAW,SAAS,CAAiB,KAejE,GAZA,EAAO,8CAA8C,IAAa,EAAQ,4BAA8B,GAAG;EAC3G,EAAY,+BAA+B,EAAW,GAFtC,EAAQ,6BAA+B,GAEU,eAAe,EAAU,KAAO,GAAG;;wCAE9D,EAAU,GAAK,+DAA+D;;EAEpH,CAEA,MAAM,EAAgB,EAAK,OAAO,CAElC,EAAO;EAAiC,CAGpC,EACF,GAAI,CACF,MAAM,EAAa,MAAM,OAClB,EAAO,CACd,EAAI,QAAQ,OACV,CAAE,IAAK,aAAiB,MAAQ,EAAM,QAAU,OAAO,EAAM,CAAE,CAC/D,yCACD,CAGL,MAAM,EAAQ,MAAM,CACpB,MAAM,EAAI,MAAM,CAIhB,QAAQ,KAAK,EAAE,CAGjB,SAAS,EAAe,EAKtB,CACA,IAAI,EAAO,EACP,EAAU,GACV,EACA,EAGE,GAAa,EAAW,IAAyB,CACrD,IAAM,EAAM,EAAK,EAAI,GACrB,GAAI,IAAQ,IAAA,IAAa,EAAI,WAAW,KAAK,CAC3C,MAAU,MAAM,GAAG,EAAK,mBAAmB,CAE7C,OAAO,GAGT,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAAK,CACpC,IAAM,EAAM,EAAK,GACjB,GAAI,IAAQ,UAAY,IAAQ,KAAM,CACpC,IAAM,EAAM,EAAU,EAAG,SAAS,CAClC,IACA,IAAM,EAAI,OAAO,EAAI,CACrB,GAAI,CAAC,OAAO,UAAU,EAAE,EAAI,EAAI,GAAK,EAAI,MACvC,MAAU,MAAM,yBAAyB,IAAM,CAEjD,EAAO,OACE,IAAQ,YACjB,EAAU,GACD,IAAQ,YACjB,EAAY,EAAQ,EAAU,EAAG,WAAW,CAAC,CAC7C,KACS,IAAQ,YACjB,EAAQ,EAAU,EAAG,UAAU,CAC/B,KAMJ,MAAO,CAAE,OAAM,UAAS,YAAW,QAAO,CAG5C,SAAS,EAAU,EAAmC,CACpD,EAAO;;;;;;6BAMoB,EAAa;;;;;2BAKf,EAAa;EACtC"}
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{n as e}from"./build-id-C94zHRXj.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-BL66TSQP.js.map
2
+ import{r as e}from"./build-id-9kqTcA9R.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-CHEEY4Vx.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version-BL66TSQP.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-CHEEY4Vx.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.53",
3
+ "version": "0.0.1-alpha.55",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -19,28 +19,28 @@
19
19
  "dependencies": {
20
20
  "react": "^19.2.4",
21
21
  "zod": "4.3.6",
22
- "@x-otto/agent": "0.0.1-alpha.6",
23
- "@x-otto/ai": "0.0.1-alpha.5",
24
- "@x-otto/coding": "0.0.1-alpha.22",
25
- "@x-otto/env": "0.1.0-alpha.7",
22
+ "@x-otto/agent": "0.0.1-alpha.5",
23
+ "@x-otto/env": "0.1.0-alpha.8",
24
+ "@x-otto/coding": "0.0.1-alpha.23",
25
+ "@x-otto/ai": "0.0.1-alpha.4",
26
+ "@x-otto/hooks": "0.0.1-alpha.3",
27
+ "@x-otto/mcp": "0.0.1-alpha.3",
26
28
  "@x-otto/guard": "0.0.1-alpha.1",
27
- "@x-otto/hooks": "0.0.1-alpha.4",
28
- "@x-otto/mcp": "0.0.1-alpha.4",
29
- "@x-otto/persistence": "0.0.1-alpha.5",
30
- "@x-otto/plugin": "0.1.0-alpha.7",
29
+ "@x-otto/persistence": "0.0.1-alpha.4",
30
+ "@x-otto/plugin": "0.1.0-alpha.8",
31
+ "@x-otto/memory": "0.0.1-alpha.3",
31
32
  "@x-otto/remote-persistence-server": "0.0.1-alpha.4",
32
- "@x-otto/runtime": "0.0.1-alpha.11",
33
+ "@x-otto/runtime": "0.0.1-alpha.10",
34
+ "@x-otto/interchange": "0.1.0-alpha.8",
35
+ "@x-otto/session": "0.0.1-alpha.5",
33
36
  "@x-otto/schedule": "0.0.1-alpha.4",
34
37
  "@x-otto/service": "0.0.1-alpha.3",
35
- "@x-otto/session": "0.0.1-alpha.6",
36
- "@x-otto/session-contract": "0.0.1-alpha.4",
37
- "@x-otto/setting": "0.0.1-alpha.5",
38
- "@x-otto/shared": "0.1.0-alpha.7",
39
- "@x-otto/tools": "0.0.1-alpha.5",
38
+ "@x-otto/shared": "0.1.0-alpha.8",
39
+ "@x-otto/setting": "0.0.1-alpha.4",
40
+ "@x-otto/session-contract": "0.0.1-alpha.3",
41
+ "@x-otto/tools": "0.0.1-alpha.4",
40
42
  "@x-otto/trace-view": "0.0.1-alpha.2",
41
- "@x-otto/tui": "0.0.1-alpha.20",
42
- "@x-otto/interchange": "0.1.0-alpha.7",
43
- "@x-otto/memory": "0.0.1-alpha.4"
43
+ "@x-otto/tui": "0.0.1-alpha.20"
44
44
  },
45
45
  "publishConfig": {
46
46
  "access": "public",
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- const e=5445,t=`606c165f4`;export{e as n,t};
3
- //# sourceMappingURL=build-id-C94zHRXj.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"build-id-C94zHRXj.js","names":[],"sources":["../src/build-id.ts"],"sourcesContent":["// auto-generated by scripts/gen-build-id.mjs — DO NOT EDIT\nexport const BUILD_ID = 5445\nexport const BUILD_BRANCH = 'dev'\nexport const BUILD_HASH = '606c165f4'\n"],"mappings":";AACA,MAAa,EAAW,KAEX,EAAa"}
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env node
2
- import{t as e}from"./build-id-C94zHRXj.js";import{t}from"./version-BL66TSQP.js";import{t as n}from"./discover-with-bundled-CF8qFP41.js";import{n as r,r as i,t as a}from"./service-client-cfUUP4EE.js";import{n as o}from"./extension-Dpn8gltG.js";import{n as s,t as c}from"./registry-BUvu-es1.js";import{t as l}from"./proxy-CFZDVIwI.js";import{i as u}from"./install-CEPczuet.js";import{t as d}from"./schedule-Ke0jwatM.js";import{createRequire as f}from"node:module";import{arch as p,cpus as m,freemem as h,homedir as g,platform as _,release as v,totalmem as y}from"node:os";import{execFile as b,execSync as x,spawn as ee,spawnSync as S}from"node:child_process";import{DEFAULT_WORKSPACE_KEY as C,INDUCTOR_PLUGIN_ID as w,PLUGIN_MANIFEST_FILENAME as te,POINT as ne,buildExtensionContext as re,checkUpgrades as T,collectPluginPerfMetrics as ie,defaultPostInstallExecutor as ae,detectProjectConfigGating as oe,discoverFileCommands as se,discoverPlugins as ce,dispatch as le,evaluateClaudeTrust as ue,evaluatePluginTrust as E,findWorkspaceRoot as de,getLastAssistantText as D,grantPluginCapabilities as fe,grantPluginCapabilitiesWithVersion as pe,install as me,installPluginFromPackage as he,openTarget as ge,parsePluginManifest as _e,readHighRiskCapabilities as ve,readPluginLogTail as ye,readSkillLoopStatus as be,recordPluginInstalled as xe,recordPluginUninstalled as Se,redactSensitiveFields 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,SDK_VERSION as Re}from"@x-otto/env";import{dirname as O,join as k,relative as ze,resolve as Be}from"node:path";import{closeSync as Ve,existsSync as A,openSync as He,readFileSync as Ue,readSync as We,readdirSync as Ge,statSync as j}from"node:fs";import{ACTION_CHIP_VALUE_SEGMENT as Ke,FIGURES as M,buildTurnSummary as qe,createBuiltinThemeRegistry as Je,createReducerState as Ye,deriveTurnBoundaries as Xe,detectLanguage as Ze,formatProviderUsageLimitTypeFull as Qe,i18next as N,initI18n as $e,insertTurnSummaries as et,reduceToTui as tt}from"@x-otto/tui";import{createBuiltinCommands as nt}from"@x-otto/tui/compat";import{MaxToolTurnsError as rt,PromptBudgetExceededError as it}from"@x-otto/agent";import{readFile as at,readdir as ot,stat as st,unlink as ct}from"node:fs/promises";import{DEFAULT_COMPACTION_CONFIG as lt,DEFAULT_PRUNE_CONFIG as ut,estimateTokens as dt,resolveContextSize as ft}from"@x-otto/memory";import{classifyAuthErrorType as pt,computeCacheHitRatio as mt,createModelUsabilityGate as P,getProviderDescriptor as ht,getToolCallsByAssistantMessage as gt,isAuthError as _t}from"@x-otto/ai";import{promisify as vt}from"node:util";var yt=Object.defineProperty,bt=(e,t)=>{let n={};for(var r in e)yt(n,r,{get:e[r],enumerable:!0});return t||yt(n,Symbol.toStringTag,{value:`Module`}),n},xt=f(import.meta.url);function St(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 Ct(e,t){let n=D(e.session.messages())||t.partialText,r=St(t);return n?`${n}\n${r}`:r}function wt(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 Tt(e,t){let n=D(e.session.messages())||t.partialText,r=wt(t);return n?`${n}\n${r}`:r}async function Et(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 rt||t instanceof it){let n=t instanceof it,r=n?wt(t):St(t);o?.(n?`budget-exceeded`:`max-tool-turns`,r);let l=o?D(e.session.messages())||t.partialText:n?Tt(e,t):Ct(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}),D(n)}let l=D(e.session.messages());return s(l),l}async function Dt(e,n){try{await e.prompt(n)}catch(n){if(n instanceof rt)return{sessionId:e.id,status:`max_turns`,messageCount:e.session.messages().length,response:D(e.session.messages())||n.partialText,ottoVersion:t()};if(n instanceof it)return{sessionId:e.id,status:`budget_exceeded`,messageCount:e.session.messages().length,response:D(e.session.messages())||n.partialText,ottoVersion:t()};throw n}return{sessionId:e.id,status:e.status,messageCount:e.session.messages().length,response:D(e.session.messages()),ottoVersion:t()}}var F=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=nt()}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=x(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 Et(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 Et(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 Ze()}function kt(e=`auto`){let t=e===`auto`?Ze():e;return $e(t),t}const At=`@x-otto/cli`;async function jt(e){let t=process.env.OTTO_UPGRADE_MOCK;if(t){let n=t===`force`,r=/^\d+\.\d+\.\d+/.test(t)?t:n?`2.0.0`:`0.2.0`;return{latest:r,current:e,newer:Pt(r,Mt(e))>0}}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=ee(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)}let Rt,zt;function Bt(e){let t=e.map(e=>e.name).sort().join(`,`);if(Rt!==void 0&&zt===t)return Rt;let n=e=>typeof e==`function`?`[fn]`:typeof e==`string`?e:``;return Rt=dt(JSON.stringify(e.map(e=>({name:e.name,description:n(e.description),parameters:e.parameters})))),zt=t,Rt}let I,Vt;function Ht(e){return I!==void 0&&Vt===e?I:(I=dt(e),Vt=e,I)}function Ut(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=Ht(t)+Bt(n),h=a+o+r+i+p,g=Math.max(0,h-m),_=Math.max(0,s-m-g),v=ft(ut.trigger,s),y=ft(lt.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:y,lastInput:r,lastOutput:i,totalInput:l,totalOutput:u,cost:d,live:p>0}}const Wt={openai:`OpenAI`};function Gt(e){let t=[`confirm`,`auto`,`bypass`];return t[(t.indexOf(e)+1)%t.length]??`confirm`}function Kt(e){return e===`error`?`error`:e===`approval_required`||e===`input_required`?`warning`:`info`}function qt(e,t,n){let r=t===void 0?void 0:{code:t},i=r!==void 0&&_t(r),a=i&&pt(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 L(e){return e?e.toLowerCase()===`xhigh`?`XHigh`:e.charAt(0).toUpperCase()+e.slice(1):``}function Jt(e,t,n){return e?`${t.on} ${n.on}`:`${t.off} ${n.off}`}function R(e,t,n){if(!t)return`(no model)`;let r=L(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 Yt(e,t){let n=[...se(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 Xt(e){return{id:e.id,type:`function`,function:{name:e.name,arguments:JSON.stringify(e.arguments)}}}function Zt(e){return{type:`thinking`,thinking:e.text}}function Qt(e){return{type:`text`,text:e.text}}function $t(e){return{type:`a2ui`,version:e.version,components:e.components}}function en(e){let t=[],n=[];for(let r of e)switch(r.type){case`text`:r.text.trim()&&t.push(Qt(r));break;case`thinking`:r.text.trim()&&t.push(Zt(r));break;case`tool_call`:n.push(Xt(r));break;case`a2ui`:t.push($t(r));break}return{content:t,toolCalls:n}}function tn(e){return typeof e==`string`?e.trim():e.filter(e=>e.type===`text`).map(e=>e.text).join(``).trim()}function nn(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 z(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=tn(e.content);t&&i.push({role:`user`,content:t});continue}if(e.role===`assistant`){let{content:t}=en(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:nn(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:nn(r),argsObj:r,result:tn(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 rn=vt(b);function an(e,t,n){for(let r of e){if(r.role!==`assistant`)continue;let e=gt(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 on(e,t){let n=O(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=Ue(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 sn(e,t){let n=O(e),r=async e=>{try{let{stdout:t}=await rn(`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 at(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 cn(e){return[...e].sort((e,t)=>t.savedAt-e.savedAt)}function ln(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 un(e,t,n){let r=Date.now();return{id:`${r.toString(36)}-${Math.random().toString(36).slice(2,6)}`,name:ln(e,n),text:t,savedAt:r}}function dn(e){return e.length<=50?[...e]:e.slice(-50)}function B(e){let t=z(e.session.visibleMessages()),n=e.session.getTurnSummaries();return!n||n.length===0?t:et(t,n,e.session.getTurnCount()??t.filter(e=>e.role===`user`).length)}function fn(e){let{resumedNote:t,isFound:n,session:r,projState:i,tui:a}=e,o=B(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(/^↻ /,``)),pn({session:r,projState:i,tui:a,chatMsgs:o})}function pn(e){let{session:t,projState:n,tui:r}=e,i=e.chatMsgs??B(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(Xe(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?an(e,t.toolCallId,n):{};return r.oldContent===void 0&&r.newContent===void 0&&(r=on(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(cn(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 V=new Map;function mn(e){return V.get(e)}function H(e){V.delete(e);let t=W.get(e);t&&(clearTimeout(t),W.delete(e))}function hn(){return[...V.values()]}function U(e,t,n){let r={id:e,transcript:z(t),streaming:``,status:n?`busy`:`idle`,lastActivityAt:Date.now()};return V.set(e,r),r}function gn(e,t){let n=V.get(e);n&&(n.transcript=z(t),n.lastActivityAt=Date.now())}const _n=new Set;function vn(e){return _n.add(e),()=>{_n.delete(e)}}const W=new Map;function yn(e){let t=W.get(e.id);t&&clearTimeout(t),W.set(e.id,setTimeout(()=>{W.delete(e.id);for(let t of _n)t(e)},300))}function bn(e,t){let n=``,r=t=>{e.status!==t&&(e.status=t,yn(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`),gn(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(),yn(e);return}},()=>e]}function xn(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 Sn(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${xn(s)}`}]}),t.tui.info.showToast(`/session inspect`,`已查看会话 ${s.session.id}(只读快照;如需实时参与该会话请用 otto --attach ${s.session.id})`)}function Cn(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 wn=e=>`把下面的笔记归纳成一个简短标题(≤6 词)和一句话描述。严格只按此格式输出:\nTITLE: <标题>\nDESC: <一句话描述>\n\n笔记:\n${e}`;function Tn(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 En(e,t,n=8e3){let r=Cn(e);if(!t)return r;let i=new AbortController,a=setTimeout(()=>i.abort(),n);a.unref?.();try{let n=Tn(await t(wn(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 Dn(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 On(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=Cn(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,...Dn(n,r)});return}if(i===`project`){let e=n?n.getInjection().trim():``;t.tui.modal.openModal({kind:`memory`,projectIndex:e,userIndex:``,...Dn(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,...Dn(n,r)})}async function kn(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 An(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(R(t.app,n.id,t.state.session.thinkingLevel));let r=n?.contextWindow??2e5,i=Ut({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 jn(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 Mn(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]=bn(U(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 U(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 F(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(R(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=mn(n.id);if(a)t.tui.messages.pushMessages(a.transcript),H(n.id);else{let e=B(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),y=r?` [workspace: ${r}]`:``,b=[!i&&s>0?N.t(`cmd.resumeArchivedHiddenHint`,{count:s}):``].filter(Boolean),x=b.length>0?` ${b.join(` `)}`:``,ee=new Map(hn().map(e=>[e.id,e])),S=0,C=0,w=e=>{if(e.id===d)return``;let n=ee.get(e.id);return n?n.status===`busy`?(S++,`● ${N.t(`cmd.resumeStatusBusy`)} · `):n.status===`needs-input`?(C++,`● ${N.t(`cmd.resumeStatusNeedsInput`)} · `):`· ${N.t(`cmd.resumeStatusIdle`)} · `:t.app.getSession(e.id)?.isBusy?(S++,`● ${N.t(`cmd.resumeStatusBusy`)} · `):``},te=[S>0?`${S} ${N.t(`cmd.resumeStatusBusy`)}`:``,C>0?`${C} ${N.t(`cmd.resumeStatusNeedsInput`)}`:``].filter(Boolean).join(`, `),ne=te?` · ${te}`:``,re=N.t(`cmd.resumeSubtitle`,{sessions:c.length,msgs:v,recent:_})+ne+x,T=i?N.t(`cmd.resumeArchivedOnlyTitle`,{n:c.length}):N.t(`cmd.resumeSelectTitle`,{n:c.length});t.tui.modal.openModal({kind:`select`,title:T+y,subtitle:re,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=[w(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 Nn(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:`/extension reload`,status:`error`,summary:N.t(`cmd.reloadFailed`,{msg:e instanceof Error?e.message:String(e)})}))}async function Pn(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 Fn(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 In(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??``}))),Ln(t);return}if(r.length===0){Rn(t.state.session.id,n,t),Ln(t);return}if(r.length===1){Rn(r[0],n,t),Ln(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`})),Ln(t)}function Ln(e){let t=e.callbacks.refreshSlashCommands();e.tui.plugins.setCommands(t)}function Rn(e,t,n){if(e===n.state.session.id){zn(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}zn(a,t,n)}function zn(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 Bn(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=Ut({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 G(e,t){let n=e[0];if(n===`fork`){await Vn(e.slice(1),t);return}if(n===`kill`){await qn(e.slice(1),t);return}if(n===`pin`||n===`unpin`){await In(e.slice(1),t);return}if(n===`archive`||n===`unarchive`){await Fn(e.slice(1),t);return}if(n===`resume`){await Mn(e.slice(1),t);return}if(n===`compact`){await kn(e.slice(1),t);return}if(n===`context`){await Bn(e.slice(1),t);return}if(n===`inspect`){await Sn(e.slice(1),t);return}if(n===`clear`){await An(e.slice(1),t);return}if(n!==`unlock`){let n=e.join(` `).trim();if(!n){t.tui.info.showToast(N.t(`cmd.titleSessionCmd`),`Usage: /session fork | clear | unlock <id> [--force] | kill <id> | inspect <id> | pin [<id>...] | archive [<id>] | resume [<id>] | compact | context | <prompt text>`);return}await Hn(n,t);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 Vn(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]=bn(U(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 U(i.id,i.session.messages(),!1);t.callbacks.sessionUnsub?.(),t.state.session=r,t.state.interactive=new F(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(R(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=B(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 Hn(e,t){let n=t.state.session.model?.id,r=await t.app.createSession({interactive:!0,...n?{modelId:n}:{}}),i=t.state.session;if(t.state.session.isBusy){let[e]=bn(U(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 U(i.id,i.session.messages(),!1);t.callbacks.sessionUnsub?.(),t.state.session=r,t.state.interactive=new F(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(R(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(),t.tui.messages.pushMessages([]),t.callbacks.restoreSwitchedSession(),t.tui.info.setTopView({session:r.id});{let n=Ee(r.session.metadata().title,[{role:`user`,content:e}],r.id);t.tui.stores.tasks.setSessionTitle(n),t.tui.lifecycle.setTerminalTitle(n)}t.state.agentProcessing=!0,t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!0}),t.tui.messages.echoUserInput(e,{pending:!0}),r.prompt(e).catch(e=>{t.tui.info.showToast(N.t(`cmd.titleSessionCmd`),`Prompt failed: ${e instanceof Error?e.message:String(e)}`)}).finally(()=>{t.state.agentProcessing=!1,t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!1})})}async function Un(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)}`:``}`;t.state.agentProcessing=!0,t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!0}),a.session.prompt(o).catch(e=>{t.tui.info.showToast(`a2ui`,`Action failed: ${e instanceof Error?e.message:String(e)}`)}).finally(()=>{t.state.agentProcessing=!1,t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!1})})}async function Wn(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=k(o,`trace`),d=[];for(let e of l){let t=k(u,`${encodeURIComponent(e.id)}.jsonl`);try{let n=await st(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} | 预估回收: ${Gn(e)}`,i=[`会话 ID 大小 最后活跃 标题`,...d.map(e=>` ${e.session.id.slice(0,8)} ${Gn(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 ct(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 文件,回收 ${Gn(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 Gn(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 Kn(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??k(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 qn(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){H(i.id),t.tui.info.showToast(`session kill`,`Removed stale session ${i.id.slice(0,8)} from background.`);return}a.abort(),H(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 Jn(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]=bn(U(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 U(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 F(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(R(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=B(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 Yn(e){switch(e){case`global`:return N.t(`cmd.scopeGlobal`);case`repository`:return N.t(`cmd.scopeRepository`);default:return N.t(`cmd.scopeProject`)}}function Xn(e,t,n){return{workspaceDir:e.app.workspaceDir,workspaceRoot:t===`repository`?de(e.app.workspaceDir):void 0,global:t===`global`,dryRun:n}}async function Zn(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,Xn(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:Yn(r)}),...c].join(`
8
- `),confirmLabel:N.t(`cmd.uninstallConfirmYes`),dangerous:!0,onConfirm:()=>{Qn(e)},onCancel:()=>a?.()})}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,Xn(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:Yn(r)})),n===`plugin`&&await Se(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 $n(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 er(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 tr(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 nr(e,t){tr(e,`model`,t)}function rr(e,t){tr(e,`effort`,t)}function ir(e,t){er(e,`retry.queued`,{attempt:t.attempt,max:t.max,...t.mode===void 0?{}:{mode:t.mode},...t.reason===void 0?{}:{reason:t.reason}})}function ar(e,t){er(e,`retry.cancelled`,{attempt:t.attempt})}function or(e){er(e,`retry.reset`,{})}function sr(e,t,n){er(e,`pause.${t}`,{...n===void 0?{}:{source:n}})}const cr=(e,t,n)=>{let r=L(n),i=r?`${e}·${r}`:e;return t?`${i} (${t>=1e6?`${(t/1e6).toFixed(1)}M`:`${Math.round(t/1e3)}K`})`:i},K=[`low`,`medium`,`high`,`xhigh`,`max`];function lr(e,t){return[t,...e.filter(e=>e!==t)].slice(0,5)}function ur(e){let t=new RegExp(String.raw`\[@model:(${Ke}+)\]`,`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 dr(e,t){let n=ur(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 fr(e){let t=new RegExp(String.raw`\[@effort:(${Ke}+)\]`,`g`),n=[];return{text:e.replace(t,(e,t)=>(n.push(t.replace(/\\\]/g,`]`)),``)).replace(/\n{3,}/g,`
11
-
12
- `).trim(),levels:n}}function pr(e,t){let n=fr(e),r=n.levels.at(-1);return r&&(K.includes(r)?r!==t.currentEffort&&t.applyEffort(r):t.onInvalidLevel?.(r)),n.text}function mr(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=lr(o.settings.get(`recent_models`)??[],e)),await o.settings.persist(t)}catch{}if(m){if(f.applyModel(m),t.value=!0,e!==p&&(o.syncSessionToolsFor(f.id),nr({tui:i.value??{messages:{pushMessage:()=>{}}},session:f,traceStore:o.storage.traceStore},{from:p,to:m.id,label:cr(m.id,m.contextWindow,f.thinkingLevel)})),m.api.includes(`:`)&&o.firePluginActivationEvent?.(`onProvider:${m.api}`),u?.({kind:`setModel`,modelId:e}),i.value?.stores.tasks.setModelName(cr(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(cr(f.model.id,f.model.contextWindow,f.thinkingLevel)),i.value?.engine.pushEngineEvent({kind:`maxOutputTokens`,n:f.model.maxOutputTokens})),`Model "${e}" not in registry — switch NOT applied (still ${f.model?.id??`unset`}). Check the id or /auth the provider.`}}function hr(e){let{getSession:t,app:n,tuiRef:r,options:i,fmtDisplayModel:a,applyModel:o}=e,s=!1,c=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)}catch{return{usable:!1,reason:`unauthenticated`}}},f=async e=>{try{return await l(e)}catch{return{usable:!1,reason:`unauthenticated`}}},p=i.value?.model??n.settings.get(`model`);if(typeof p!=`string`||!p)return`proceed`;let m=n.modelRegistry.find(p),h;if(m&&(h=await f(m),h.usable))return m.id!==u.id&&await o(m.id),`proceed`;let g=m?ht(m.provider)!==void 0:!0,_=m?ht(m.provider)?.env:void 0,v=m?!!n.authStore.oauth.get(m.provider):!1,y=m?g?h?.reason===`intranet-unreachable`?N.t(`model.reasonIntranetUnreachable`,{provider:m.provider}):N.t(`model.reasonUnauthenticated`,{provider:m.provider}):N.t(`model.reasonProviderNotLoaded`,{provider:m.provider}):N.t(`model.reasonNotFound`),b=_?N.t(`model.hintEnvKey`,{provider:m?.provider??``,env:_}):N.t(`model.hint`),x;if((await f(u)).usable)x=u;else for(let e of n.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`))if((await d(e)).usable){x=e;break}return r.value?x?await new Promise(t=>{r.value?.modal.openModal({kind:`confirm`,title:N.t(`model.title`),message:[`${a(p)} → ${a(x.id)}`,``,y,``,b],confirmLabel:N.t(`model.permanent`),extraLabel:v?N.t(`model.login`):N.t(`model.setKey`),cancelLabel:N.t(`model.dismiss`),onConfirm:()=>{o(x.id,{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??``})),s=!1,t(`abort`)},onCancel:()=>{e.onExitSession?.(),t(`abort`)}})}):(r.value.modal.openModal({kind:`info`,title:N.t(`model.title`),lines:[a(p),``,y,``,b,``,N.t(`model.noFallback`)],action:m?{kind:`login`,run:()=>e.onLogin?.(m.provider)}:void 0}),s=!1,`abort`):`proceed`}}function gr(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 _r(e){let t=e.trim().split(`
13
- `)[0].replace(/\s+/g,` `).trim();return t.length>40?`${t.slice(0,39)}…`:t}function vr(e){e.pluginInput.unregisterBySource(`shortcut`);let t=(e.settings.get(`shortcuts`)??[]).map(e=>({label:`@${e.name}`,value:`[@shortcut:${e.name.replace(/]/g,`\\]`)}]`,description:_r(e.text),kind:`shortcut`,source:`shortcut`}));t.length&&e.pluginInput.register(t)}function yr(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 br={low:`cmd.effortDescLow`,medium:`cmd.effortDescMedium`,high:`cmd.effortDescHigh`,xhigh:`cmd.effortDescXhigh`,max:`cmd.effortDescMax`};function xr(e){let t=K.map(e=>({label:L(e),value:`[@effort:${e}]`,description:N.t(br[e]??`cmd.effortDescLow`),kind:`effort`,source:`builtin-effort`}));e.pluginInput.unregisterBySource(`builtin-effort`),e.pluginInput.register(t)}async function Sr(e,t){t.tui.modal.openModal({kind:`shortcutsPanel`,shortcuts:t.app.getShortcuts(),onSave:(e,n,r)=>{t.app.saveShortcut(e,n,r).then(()=>vr(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(()=>vr(t.app)).catch(e=>{t.tui.info.showToast(`Shortcuts`,`Delete failed: ${e instanceof Error?e.message:String(e)}`)})}})}const Cr={low:{label:`Low`,desc:`节约 Token,快速响应`,intensity:.2},medium:{label:`Medium`,desc:`平衡速度与推理质量`,intensity:.4},high:{label:`High`,desc:`深度推理,延迟较高`,intensity:.6},xhigh:{label:`XHigh`,desc:`更长推理链,更全面思考`,intensity:.8},max:{label:`Max`,desc:`全力推理,最慢但最深入`,intensity:1}};function wr(e){let t=Math.round(e*8);return`━`.repeat(Math.max(0,t))+`╌`.repeat(Math.max(0,8-t))}async function Tr(e,t){let n=e[0]?.toLowerCase();if(n&&K.includes(n)){Er(t,n);return}if(n){t.tui.info.showToast(N.t(`cmd.titleEffort`),N.t(`cmd.effortUnknown`,{arg:n,levels:K.join(` / `)}));return}let r=t.state.session.thinkingLevel;t.tui.modal.openModal({kind:`select`,title:N.t(`cmd.selectEffortTitle`),options:K.map(e=>{let t=Cr[e],n=e===r,i=wr(t.intensity);return{label:t.label,value:e,detail:`${i} ${t.desc}${n?` · 当前`:``}`}}),onSelect:e=>Er(t,e),onCancel:()=>{}})}function Er(e,t){let n=e.state.session,r=n.thinkingLevel;n.applyThinkingLevel(t),e.app.settings.persist({thinking_level:t}),r!==t&&rr({tui:e.tui,session:n,traceStore:e.app.storage.traceStore},{from:r,to:t,label:L(t)}),n.model?.id&&e.tui.stores.tasks.setModelName(R(e.app,n.model.id,t)),e.tui.info.showToast(N.t(`cmd.titleEffort`),t)}async function Dr(e,t){let n=e[0]?.toLowerCase();if(n===`general`||n===`gen`){q(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`){$n(e.slice(1),t);return}if(n===`shortcuts`){Sr(e.slice(1),t);return}if(n===`proxy`){l(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??Je(),o=n.get(`theme_preset`)??{},s=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:s,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:`Proxy`,value:`proxy`,detail:`Configure HTTP proxy`}],defaultSelectedValue:t,onSelect:t=>{t===`general`?q(e):t===`lang`?zr([],e):t===`theme`?Br([],e):t===`keybindings`?$n([],e):t===`shortcuts`?Sr([],e):t===`proxy`&&l([],e)},onCancel:()=>{}})}let kr;function q(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===w),f={on:M.toggleOn,off:M.toggleOff},p={on:N.t(`cmd.toggleOn`),off:N.t(`cmd.toggleOff`)},m=e=>Jt(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`){J(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){q(e);return}let n=t.trim();await e.app.settings.persist({nickname:n}),q(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}),J(e,N.t(`cmd.genSaved`),`threshold`)})()},onCancel:()=>{J(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}),J(e,N.t(`cmd.genSaved`),`cooldown`)})()},onCancel:()=>{J(e,void 0,`cooldown`)}})}function J(e,t,n){let r=e.app.settings,i=r.get(`skill_loop`)?.enabled===!0,a=e.app.activePlugins().some(e=>e.id===w),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:()=>{q(e,void 0,`skillLoopPanel`)},onCancel:()=>{q(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:Jt(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}),J(e,n?N.t(`cmd.genSkillLoopOn`):N.t(`cmd.genSkillLoopOff`),`toggle`)})()},onCancel:()=>{q(e,void 0,`skillLoopPanel`)}})}function Lr(e){let t=e.app.settings,n=e.app.activePlugins().some(e=>e.id===w),r=be({workspaceKey:e.app.workspaceRef?.key??C,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:()=>{J(e,void 0,`status`)},onCancel:()=>{J(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}),q(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}),q(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??Je(),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??Je(),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:g()}).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 ci(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=ue(r),o=oe(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:g()}).filter(e=>e.scope===`project`||e.scope===`repository`);for(let e of c){let t=E(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),``,...Kr(t),N.t(`cmd.permsClearHint`),N.t(`cmd.permsManageHint`)]})}function Kr(e){let t=e.app.getRecentPermissionDecisions?.(e.state.session.id,8)??[];if(t.length===0)return[`${N.t(`cmd.permsRecentLabel`)} ${N.t(`cmd.permsEmpty`)}`,``];let n=e=>{let t=new Date(e),n=e=>String(e).padStart(2,`0`);return`${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`};return[N.t(`cmd.permsRecentLabel`),...t.map(e=>{let t=e.filePath?` ${e.filePath}`:``;return` ${n(e.timestamp)} ${e.effect.padEnd(5)} ${e.toolName}${t} (${e.policyName})`}),``]}async function qr(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:`select`,title:N.t(`cmd.titleUpgrade`),subtitle:N.t(`cmd.upgradeConfirmSubtitle`,{current:r,latest:i.latest}),subtitleTone:`warning`,layout:`buttons`,options:[{label:N.t(`common.upgradeButton`),value:`upgrade`,color:`accent`},{label:N.t(`common.cancelButton`),value:`cancel`,color:`amber`}],onSelect:e=>{e===`upgrade`&&Jr(n,i.latest)}})}async function Jr(e,t){e.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgrading`));let{ok:n,error:r}=await Ft(t);if(!n){e.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeFailed`,{err:r??N.t(`cmd.unknownError`)}));return}e.state.restartRequested=!0,e.tui.lifecycle.stop()}async function Yr(e,n){if(!e.includes(`--force`))return!1;let r=await jt(t());return r?r.newer?(await Jr(n,r.latest),!0):(n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeLatest`,{current:t()})),!0):(n.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeNoNetwork`)),!0)}async function Xr(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 ja){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=>{La(e,[],t)},onCancel:()=>{}})}async function Zr(e,t){t.tui.panes.togglePane(`history`)}async function Qr(e,t){t.tui.panes.togglePane(`notifications`)}async function $r(e,t){t.tui.panes.togglePane(`prompts`)}async function ei(e,t){t.tui.panes.setServices(!0)}async function ti(e,t){t.tui.info.showToast(N.t(`cmd.titleUpgrade`),N.t(`cmd.upgradeCheckScanning`));try{let e=Oe({workspaceDir:t.app.workspaceDir,workspaceRoot:de(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 T(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 ni=bt({confirmHighRiskCapabilities:()=>li,formatPluginContributionsSummary:()=>oi,handleDelegatesToggle:()=>di,handleExtension:()=>Y,handleJobStart:()=>fi,pluginCapabilityLabel:()=>si,promptPluginTrust:()=>ci,runPluginInstall:()=>ui});function ri(e){return!e.endsWith(k(`.claude`,`skills`))}function ii(e,t){return ri(t)?e===`project`?`project`:e===`global`?`global`:null:null}function ai(e,t){let n={project:`project`,global:`global`,plugin:`plugin`,inline:`inline`}[e]??e;return t?`${n} (${t})`:n}function oi(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 si(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 ci(e,t){let n=E(t),r=n.pendingCapabilities,i=()=>{if(ke(t.dir),r.length>0){let n=t.manifest.version;n?pe(t.dir,r,n):(e.tui.info.showToast(N.t(`cmd.titlePlugin`),`插件 "${t.id}" manifest 无版本字段——授权不绑定版本,后续更新后需重新信任`),fe(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=si(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 li(e,t,n){if(t.length===0)return!0;let r=[N.t(`cmd.pluginCapabilityIntro`)];for(let e of t){let t=si(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 ui(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 me(s,{global:!0,as:`plugin`,postInstallExecutor:ae});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=ve(c);if(!r&&!await li(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 he({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 xe(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),d.version?pe(d.dir,u,d.version):fe(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-DbAq_BRH.js`);await e(t)}catch{}return!0}if(!r){await new Promise(e=>setImmediate(e));let{handleModel:e}=await Promise.resolve().then(()=>pi);await e([],t)}return!0}async function di(e,t){t.tui.panes.togglePane(`backgroundTasks`)}async function fi(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 Y(e,t){let r=e[0]?.toLowerCase();if(r===`trust`)return Wr(e.slice(1),t);if(r===`install`)return u(e.slice(1),t);if(r===`registry`)return c(e.slice(1),t);if(r===`search`)return s(e.slice(1),t);if(r===`update`)return ti([`--check`],t);if(r===`reload`)return Nn(e.slice(1),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__`){l();return}if(e.startsWith(`contrib:`)){let n=e.slice(8),a=r.get(n);if(!a)return;le(a,{open:e=>ge(e),runCommand:async(e,n)=>{let{dispatchSlashCommand:r}=await Promise.resolve().then(()=>Aa);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:()=>{}})},l=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-DYHR-ONu.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(()=>Aa);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:ai(n.source.type,n.source.id)}),tone:`muted`},...ri(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`},...ii(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=ii(n.source.type,n.source.root);if(!r)return;await Zn({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 Zn({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:g()}).find(t=>t.id===e);if(!d){o();return}let f=E(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,_=[[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=_.length?` ${_.join(`, `)}`:` —`,y=(t.app.getPluginPanelRegistrations?.()??[]).filter(t=>t.pluginId===e),b=oi({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}),x=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;x.push({label:e?N.t(`cmd.extPluginTrustLabel`):N.t(`cmd.extPluginUntrustLabel`),value:e?`trust`:`untrust`,color:e?`accent`:`gray`})}x.push({label:N.t(`cmd.extReloadLabel`),value:`reload`}),d.scope!==`builtin`&&x.push({label:N.t(`cmd.uninstallActionLabel`),value:`uninstall`,color:`red`});let ee=re(d,{"extension.id":e,"extension.enabled":r,"extension.trusted":f.trusted,"extension.scope":d.scope,"extension.category":`plugin`}),S=d.manifest.contributes,C=we(ne.extensionDetailActions,S?.menus,S?.actions,ee),w=new Map(C.map(e=>[e.id,e.command]));for(let e of C){let n=`${d.id}:action.${e.id}.title`,r=t.app.i18nRegistry.t(n),i=r===n?e.title:r;x.push({label:i,value:`contrib:${e.id}`,color:e.color})}let te={open:e=>ge(e),runCommand:async(e,n)=>{let{dispatchSlashCommand:r}=await Promise.resolve().then(()=>Aa);await r(e,n?n.split(/\s+/).filter(Boolean):[],t)},runScript:async e=>{if(E(d).gated){i(N.t(`cmd.titlePlugin`),N.t(`cmd.extPluginUntrusted`));return}await De(d,e)}},T=y[0];T&&t.app.firePluginActivationEvent?.(`onView:${T.id}`);let ie;if(e===`plugin-feishu-use`){let e=k(u,`.otto`,`feishu-use.json`),t=!1;try{if(A(e)){let n=JSON.parse(Ue(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`?`仓库`:`项目`;ie=[{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||(ie=[{kind:`text`,value:`未配置 — 点击 [重新配置] 引导设置`,tone:`warning`},{kind:`row`,label:`预期配置路径`,value:e,tone:`muted`}]),x.push({label:`重新配置`,value:`feishu-reconfigure`,color:`amber`})}let ae=()=>{let n=t.app.pluginHealthTracker?.query(e)??{hookTimeouts:0,toolTimeouts:0},r=ye(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()||`—`},...b?[{kind:`row`,label:N.t(`cmd.extPluginLabelContributions`),value:b}]:[],{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:x,panelInfo:T?{title:T.title,modulePath:T.modulePath,exportName:T.exportName,pluginId:e}:void 0,dataListEntries:[...se,...ie??oe],...ae(),...d.manifest.contributes?.config?{configForm:{schema:d.manifest.contributes.config,values:Ce(t.app.pluginModuleManager?.getPluginConfig(e,d.manifest.contributes.config)??{}),onEditConfig:async()=>{let n=t.app.pluginModuleManager?.getPluginConfig(e,d.manifest.contributes.config)??{},i=await t.tui.modal.openModal({kind:`input`,title:`Edit config: ${s}`,description:[`Edit JSON configuration (all fields must be valid JSON)`],placeholder:JSON.stringify(n,null,2)});if(i?.trim())try{let n=JSON.parse(i);if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`config must be a JSON object`);await t.app.pluginModuleManager?.updatePluginConfig(e,n),m(e,r,s,c,{kind:`success`,message:`Configuration updated`})}catch(t){m(e,r,s,c,{kind:`error`,message:`Invalid JSON: ${t instanceof Error?t.message:String(t)}`})}}}}:{},onRefresh:()=>m(e,r,s,c),onAction:async n=>{if(n.startsWith(`contrib:`)){let t=w.get(n.slice(8));if(t)try{await le(t,te)}catch(e){a(N.t(`cmd.extToggleFailed`,{err:e instanceof Error?e.message:String(e)}))}m(e,r,s,c)}else if(n===`trust`)ci(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-DbAq_BRH.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 Zn({name:e,type:`plugin`,scope:d.scope===`project`||d.scope===`repository`?d.scope:`global`,ctx:t,onDone:()=>o()})},onClose:()=>o()})};o()}var pi=bt({handleLogout:()=>bi,handleModel:()=>vi,handleProviderAuth:()=>X,handleProviderLogout:()=>yi,handleServiceLogin:()=>xi,handleServiceLogout:()=>Si});const mi=`__otto_model_login__`,hi=`__otto_model_setkey__`,gi=`__otto_model_grant_capability__`,_i=`__otto_model_install_plugin__`;async function vi(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:()=>{Y([],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:_i}]:h?[{label:N.t(`model.goLogin`),value:mi},{label:N.t(`model.setKey`),value:hi}]:[],..._>0?[{label:N.t(`model.goGrantCapability`),value:gi}]:[]]: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===mi){await X([],t,{method:`oauth`});return}if(e===hi){await X([],t,{method:`key`});return}if(e===gi){await Y([],t);return}if(e===_i){let{EXTENSION_ALIASES:e}=await import(`./extension-CoJqqktf.js`),{runPluginInstall:n}=await Promise.resolve().then(()=>ni),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 X(e,t,n){if(e[0]===`logout`)return yi(e.slice(1),t);if(e.includes(`--service`))return xi(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??ht(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 yi(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??ht(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 bi(e,t){e[0]&&e[0]!==`--service`||await Si([],t)}async function xi(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 Si(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)}))}}function Ci(){let e=process.env.OTTO_NOTIFY_COALESCE_WARN_RATIO,t=e?Number(e):NaN;return Number.isFinite(t)&&t>=1?t:1.5}function wi(e,t){return t===0?`healthy`:e<Ci()?`warning`:`healthy`}async function Ti(e,t){let n=e[0]?.toLowerCase();if(n===`cache`||n===`cache-stats`)return Ei(e.slice(1),t);if(n===`diagnose`)return Pn(e.slice(1),t);if(n===`services`)return ei(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();t.tui.engine.pushEngineEvent({kind:`status`,session:{title:u,sessionId:r.id.slice(0,8),modelId:r.model?.id??N.t(`cmd.statusModelUnset`),messageCount:a.length,occupancy:o,contextWindow:s,occupancyPct:c,cumOutput:l,writeLeaseReadOnly:d,isPaused:t.callbacks.isRunPaused()}}),t.tui.engine.pushEngineEvent({kind:`status`,memory:t.app.memoryGovernor.sample()});let f=t.tui.info.getNotifyStats(),p=f.coalescedCalls/Math.max(1,f.coalescedFires);t.tui.engine.pushEngineEvent({kind:`status`,notify:{coalescedCalls:f.coalescedCalls,coalescedFires:f.coalescedFires,immediateCalls:f.immediateCalls,flushFires:f.flushFires,coalesceRatio:p,alert:wi(p,f.coalescedCalls)}});let m=t.app.activePlugins();try{let e=await ie(m,void 0,e=>t.app.pluginHealthTracker.recordToolTimeout(e));t.tui.engine.pushEngineEvent({kind:`status`,pluginMetrics:e})}catch(e){t.app.logger.warn({err:e instanceof Error?e.message:String(e)},`[status] collectPluginPerfMetrics failed`),t.tui.engine.pushEngineEvent({kind:`status`,pluginMetrics:[]})}t.tui.panes.togglePane(`status`)}async function Ei(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:mt(t,e.api)}}),i=r.some(e=>e.hitRatio!==null),a={inputTokens:n.totalInputTokens,outputTokens:0,cacheReadTokens:n.totalCacheReadTokens,cacheWriteTokens:n.totalCacheWriteTokens},o=i?mt(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 Di(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 Oi(e){return new Date(e*1e3).toLocaleString()}async function ki(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:Qe(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:Oi(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 Ai=async(e,t)=>{let n=e[0];switch(n){case`memory-sync`:return ji(e.slice(1),t);default:t.tui.info.showToast(`Workspace`,`/workspace ${n??``} — unknown subcommand. Use: memory-sync [status|enable|disable]`)}};async function ji(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 Mi(t,n){let r=n.state.session,i=r.model?.id??N.t(`cmd.aboutModelNotSet`),a=m().length,o=Math.round(y()/(1024*1024*1024)),s=Math.round(h()/(1024*1024)),c=[{kind:`group`,title:N.t(`cmd.aboutGroupVersion`)},{kind:`row`,label:N.t(`cmd.aboutVersion`),value:`${Re} (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} · ${_()} ${p()} · ${v()}`,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})}function Ni(e,t,n){let r=Te(e,t);if(r)return r;let i=e.split(`/`).pop();if(i)return ce({cwd:t??process.cwd(),homedir:n??g()}).find(e=>e.id===i)?.dir}function Pi(e,t,n){try{let r=Ni(e,t,n);if(!r)return;let i=k(r,te),a=_e(Ue(i,`utf-8`),i);return a?a.codeProviderIds?.[0]??a.contributes?.providers?.[0]?.id??a.contributes?.oauth?.[0]?.id:void 0}catch{return}}function Fi(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 Ii={provider:`install-provider`,authentication:`connect-provider`,model:`choose-model`,ready:`send-first-prompt`,"first-prompt":`none`};function Li(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 Ri(e){let t=Li(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:Ii[t],stage:t,autoOpen:o}}}function zi(e){return e.stage===`ready`||e.stage===`first-prompt`}function Bi(e,t){return e.get(t)===!0}function Vi(e){return{personalizationSeen:Bi(e,`has_completed_onboarding`),dismissed:Bi(e,`has_completed_wizard`)||Bi(e,`wizard_dont_show_again`),firstPromptSubmitted:typeof e.get(`first_prompt_submitted_at`)==`number`}}const Hi=`__otto_setup__`;async function Ui(e){let t=Vi(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!==Hi),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!==Hi?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 Ri({providerInstalled:e.hasProviderPlugin(),...e.providerCandidates?{providerCandidates:e.providerCandidates}:{},connectedProviderIds:r,usableModelIds:a,...o!==void 0&&o!==Hi?{selectedModelId:o}:{},...c===void 0?{}:{selectedModelUsableInMainSession:c},firstPromptSubmitted:t.firstPromptSubmitted,dismissed:t.dismissed})}function Wi(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 Gi=class{snapshot=null;listeners=new Set;constructor(e){this.deps=e}current(){return this.snapshot}async refresh(){let e=await Ui(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 Ki(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 qi(e,t){return e.map((e,n)=>({provider:e,index:n,rank:Ki(e,t)})).sort((e,t)=>e.rank-t.rank||e.index-t.index).map(e=>e.provider)}function Ji(e){try{let{createRequire:t}=xt(`node:module`),{readFileSync:n}=xt(`node:fs`),{dirname:r,join:i}=xt(`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 Yi(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=Xi(t);return t.map(e=>({...e,recommended:e.usable&&e.id===n}))}function Xi(e){return e.find(e=>e.usable)?.id}const Zi={hasReadme:!1,hasPackageManifest:!1,hasTestConfig:!1,isEmpty:!1},Qi=new Set([`node_modules`,`.git`,`.hg`,`.svn`,`.venv`,`venv`,`__pycache__`,`.pytest_cache`,`.mypy_cache`,`.tox`,`dist`,`build`,`.next`,`.nuxt`,`.cache`,`.DS_Store`]),$i=/^readme(\.(md|markdown|txt|rst))?$/i,ea=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`]),ta=/^(jest\.config|vitest\.config|karma\.conf|\.mocharc)(\.(js|ts|mjs|cjs|json))?$/i,na=new Set([`pytest.ini`,`tox.ini`,`phpunit.xml`,`phpunit.xml.dist`,`setup.cfg`]);async function ra(e,t){let n;try{n=await t.readdir(e)}catch{return Zi}let r=n.filter(e=>!Qi.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&&$i.test(e.name)&&(a=!0),!o&&ea.has(e.name)&&(o=!0),!s&&(na.has(e.name)||ta.test(e.name))&&(s=!0),a&&o&&s)))break;return{hasReadme:a,hasPackageManifest:o,hasTestConfig:s,isEmpty:i}}function ia(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 aa=`oxygen-provider`,oa=new Set([`plugin-oxygen`,aa]);async function sa(e){try{let{makeRegistryClient:t}=await import(`./registry-DYHR-ONu.js`),{registries:n}=await t(e.app).loadAll();return n.some(e=>e.entries.some(e=>oa.has(e.id)||e.source===`@x-otto/plugin-oxygen`||e.source.includes(`/plugin-oxygen`)||e.subPath?.endsWith(`plugin-oxygen`)))}catch{return!1}}async function ca(e){let t=e.tui,n=e.app,r=await Ui(Wi({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 sa(e),l=Object.entries(o).filter(([e,t])=>t.capabilities.includes(`provider`)&&(e!==aa||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=qi(l.map(([e,t])=>({id:e,...Ji(t.pkg)})),process.env).map(({id:e})=>({label:e,value:e,detail:u[e]??o[e]?.pkg??e})),f=e=>Fi(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 Ui(Wi({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 Yi((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=ia(await ra(n.workspaceDir,{readdir:e=>ot(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(()=>ni),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=Ni(s);t&&(c=e(t))}catch{}return{ok:!0,providerId:Pi(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-CkSf8ziQ.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 la(e,t){await ca(t)}function Z(e){return cn(e.state.session.session.getDrafts()??[])}function ua(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 da=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return fa(e.slice(1),t);case`save`:return pa(e.slice(1),t);case`load`:return ma(e.slice(1),t);case`delete`:case`remove`:return ha(e.slice(1),t);default:t.tui.info.showToast(`Draft`,`/draft ${n} — unknown subcommand. Use: save|list|load|delete`)}};async function fa(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 pa(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=un(a,o,s),l=dn([...s,c]);try{ua(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 ma(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 ha(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{ua(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 ga=async(e,t)=>{let n=e[0];switch(n){case void 0:case`list`:return _a(t);case`remove`:return va(e[1],t);case`move`:return ya(e[1],e[2],t);case`clear`:return ba(t);default:t.tui.info.showToast(`Queue`,`/queue ${n} — unknown subcommand. Use: list|remove|move|clear`)}};async function _a(e){e.tui.panes.togglePane(`queuePane`,!0)}async function va(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 ya(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 ba(e){e.tui.panes.clearQueue(),e.tui.info.showToast(`Queue`,`Queue cleared`)}const xa=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`)),Sa(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`))),Sa(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`)),Sa(t);return}t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.nothingToPause`))};function Sa(e){let t=e.callbacks.refreshSlashCommands?.();t&&e.tui.plugins.setCommands(t)}function Ca(e){let t;try{let n=He(e,`r`);try{t=Buffer.alloc(512);let e=We(n,t,0,512,0);t=t.subarray(0,e)}finally{Ve(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 wa(e){return e>=1048576?`${(e/1048576).toFixed(1)} MB`:e>=1024?`${(e/1024).toFixed(1)} KB`:`${e} B`}function Ta(e){let t;try{t=Ge(e)}catch{return[]}let n=[];for(let r of t)try{let t=j(k(e,r));n.push({name:r,isDir:t.isDirectory(),size:t.isDirectory()?void 0:t.size})}catch{}return n}function Ea(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=Ea(Ta(n)),a=ze(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:wa(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=k(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}Da(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,O(n),r):()=>{}})}async function Da(e,t,n,r){if(Ca(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 Oa(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=Be(n,r),o=ze(n,a).startsWith(`..`);if(!A(a)){if(o){t.tui.info.showToast(N.t(`cmd.titleOpen`),N.t(`cmd.openNotFound`,{path:r}));return}let e=O(a);for(;e!==n&&e!==O(e)&&!A(e);)e=O(e);if(A(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 Da(t,a,r)}async function ka(e,t){t.tui.engine.clearErrorRetry?.();let n=t.state.session;if(!n){t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.retryNoSession`,{defaultValue:`No active session`}));return}if(n.isBusy){t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.retryBusy`,{defaultValue:`Agent 正在运行,无法重试`}));return}if(![...n.session.messages()].reverse().find(e=>e.role===`user`)){t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.retryNoResumable`,{defaultValue:`无可重试的回合——请输入消息`}));return}t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!0});try{await n.retryLastRound()}catch(e){if(e?.code===`RETRY_NO_RESUMABLE_ROUND`){t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.retryNoResumable`,{defaultValue:`无可重试的回合——请输入消息`}));return}t.tui.info.showToast(N.t(`cmd.titleInfo`),N.t(`cmd.retryFailed`,{defaultValue:`重试失败:{{err}}`,err:e instanceof Error?e.message:String(e)}))}finally{t.tui.engine.pushEngineEvent({kind:`agentProcessing`,value:!1})}}var Aa=bt({DISPATCHABLE_COMMAND_NAMES:()=>Pa,ENGINE_BUILTIN_COMMANDS:()=>Na,HELP_GROUP_ORDER:()=>ja,SAFE_COMMAND_NAMES:()=>Ma,SLASH_COMMANDS:()=>$,buildPluginSlashCommandRegistry:()=>Fa,dispatchSlashCommand:()=>La,handleMemory:()=>On,pluginSlashCommandsToEntries:()=>Ia});const ja=[`session`,`model`,`agent`,`debug`,`ui`,`other`],$=[{name:`clear`,handler:An,engineBuiltin:!0,group:`session`,tuiHidden:!0,deprecated:!0,description:`/session clear (deprecated alias)`},{name:`compact`,handler:(e,t)=>G([`compact`,...e],t),group:`session`,tuiHidden:!0,deprecated:!0,description:`/session compact (deprecated alias)`},{name:`memory`,aliases:[`mem`],handler:On,group:`session`,description:`Project + user memory: /memory [user|project|<name>|forget <name>]`},{name:`workspace`,handler:Ai,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:Ti,safe:!0,engineBuiltin:!0,group:`session`,description:`Session status & perf: /status [cache|diagnose|services]`},{name:`open`,handler:Oa,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:vi,group:`model`,description:`Switch model; /model [<id>|refresh]`},{name:`auth`,aliases:[`login`],handler:X,group:`model`,description:`Connect a model provider (OAuth or API key); /auth [<provider>], /auth logout [<provider>] clears stored credentials`},{name:`usage`,handler:ki,safe:!0,engineBuiltin:!0,group:`model`,description:`Show provider usage quota snapshot (Anthropic OAuth subscription plans only)`},{name:`logout`,handler:bi,group:`model`,description:`Sign out of your otto account (removes local account identity); /logout`},{name:`job`,handler:fi,safe:!0,group:`agent`,description:`Start a background agent job: /job <directive> (worktree-isolated, full tools incl. MCP)`},{name:`schedule`,handler:d,safe:!0,group:`agent`,description:`Manage scheduled tasks: /schedule add|list|remove|run|enable|disable <args>`},{name:`delegates`,handler:di,safe:!0,group:`agent`,description:`Toggle the Delegates panel (↑↓ select · k kill · o output · a apply)`},{name:`diagnose`,handler:(e,t)=>Ti([`diagnose`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/status diagnose (deprecated alias)`},{name:`context`,handler:(e,t)=>G([`context`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/session context (deprecated alias)`},{name:`cache-stats`,handler:(e,t)=>Ti([`cache-stats`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/status cache (deprecated alias)`},{name:`services`,handler:(e,t)=>Ti([`services`,...e],t),safe:!0,group:`debug`,tuiHidden:!0,deprecated:!0,description:`/status services (deprecated alias)`},{name:`gallery`,handler:Di,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:Wn,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:Kn,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:Tr,safe:!0,group:`ui`,description:`Switch reasoning effort level (/effort [low|medium|high|xhigh|max])`},{name:`preference`,aliases:[`pref`],handler:Dr,safe:!0,group:`ui`,description:`Preferences: /preference [general|lang|theme|keybindings|shortcuts|proxy] (RFC-369)`},{name:`trust`,handler:(e,t)=>Y([`trust`,...e],t),safe:!0,group:`ui`,tuiHidden:!0,deprecated:!0,description:`/extension trust (deprecated alias)`},{name:`notification`,aliases:[`notif`],handler:Qr,group:`ui`,description:`Toggle the notification center panel (≡ ctrl+n)`},{name:`draft`,handler:da,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:ga,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)=>Dr([`keybindings`,...e],t),safe:!0,group:`ui`,tuiHidden:!0,deprecated:!0,description:`/preference keybindings (deprecated alias)`},{name:`shortcuts`,handler:(e,t)=>Dr([`shortcuts`,...e],t),safe:!0,group:`ui`,tuiHidden:!0,deprecated:!0,description:`/preference shortcuts (deprecated alias)`},{name:`proxy`,handler:(e,t)=>Dr([`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)=>Xr(e,t,[...$,...Ia([...Fa(t.app).values()])])},{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:xa,safe:!0,group:`other`,description:`Pause after current turn finishes (toggle with /continue)`},{name:`retry`,handler:ka,safe:!0,group:`other`,description:`Re-send the last prompt to the model (e.g. after switching models or fixing a transient error)`},{name:`copy`,engineBuiltin:!0,group:`other`,tuiHidden:!0,description:`Copy last assistant response`},{name:`resume`,handler:(e,t)=>G([`resume`,...e],t),group:`other`,tuiHidden:!0,deprecated:!0,description:`/session resume (deprecated alias)`},{name:`rename`,handler:jn,safe:!0,group:`session`,description:`Set a custom title for the current session (/rename <new title>)`},{name:`a2ui-action`,handler:Un,safe:!1,group:`session`,description:`Trigger A2UI interactive component action (/a2ui-action btn1 click)`},{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 ti(e,t);return}await Yr(e,t)||await qr(e,t)}},{name:`about`,handler:Mi,safe:!0,group:`other`,description:`Show version, build, and environment info (/about)`},{name:`setup`,handler:la,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:Y,group:`other`,description:`Manage extensions: /extension [trust|install|registry|search|update|reload] or open panel (RFC-369)`},{name:`install`,handler:(e,t)=>Y([`install`,...e],t),safe:!0,group:`other`,tuiHidden:!0,deprecated:!0,description:`/extension install (deprecated alias)`},{name:`registry`,handler:(e,t)=>Y([`registry`,...e],t),safe:!0,group:`other`,tuiHidden:!0,deprecated:!0,description:`/extension registry (deprecated alias)`},{name:`search`,handler:(e,t)=>Y([`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:`archive`,aliases:[`unarchive`],handler:(e,t)=>G([`archive`,...e],t),safe:!0,tuiHidden:!0,deprecated:!0,description:`/session archive (deprecated alias)`},{name:`session`,handler:G,description:`Session management: /session [fork|clear|unlock|kill|inspect|pin|archive|resume|compact|context] (RFC-369)`},{name:`fork`,handler:Jn,safe:!0,description:`Fork current session into a named branch`},{name:`pin`,aliases:[`unpin`],handler:(e,t)=>G([`pin`,...e],t),safe:!0,tuiHidden:!0,deprecated:!0,description:`/session pin (deprecated alias)`},{name:`history`,aliases:[`hist`],handler:Zr,safe:!0,description:`Open history search panel (same panel as Ctrl+R)`},{name:`prompts`,handler:$r,safe:!0,description:`View prompt log (list of submitted prompts this session)`}],Ma=new Set($.filter(e=>e.safe).flatMap(e=>[e.name,...e.aliases??[]])),Na=new Set($.filter(e=>e.engineBuiltin).flatMap(e=>[e.name,...e.aliases??[]])),Pa=new Set($.filter(e=>e.handler).flatMap(e=>[e.name,...e.aliases??[]]));function Fa(e){let t=new Set;for(let e of $){t.add(e.name);for(let n of e.aliases??[])t.add(n)}let n=new Map;for(let r of e.pluginSlashCommands?.()??[]){if(t.has(r.name)){console.warn(`[plugin] 插件 "${r.pluginId}" 声明斜杠命令 "/${r.name}" 与内置命令冲突,已忽略(内置优先,RFC-440)`);continue}let e=n.get(r.name);e?e.push(r):n.set(r.name,[r])}let r=new Map;for(let[e,t]of n){if(t.length===1){r.set(e,t[0]);continue}console.warn(`[plugin] 斜杠命令 "/${e}" 被多个插件声明(${t.map(e=>e.pluginId).join(`, `)}),已禁用(fail-closed,RFC-440)`)}return r}function Ia(e){let t=[`session`,`model`,`agent`,`debug`,`ui`,`other`];return e.map(e=>({name:e.name,group:t.includes(e.group??``)?e.group:`other`,description:e.description}))}async function La(e,t,n){let r=$.find(t=>t.name===e);if(r||=$.find(t=>t.aliases?.includes(e)),!r?.handler){let r=Fa(n.app).get(e);return r?(await Ra(r,t,n),!0):!1}return await r.handler(t,n),!0}async function Ra(e,t,n){let r=n.tui,i=n.app.getPluginPanelRegistrations?.()??[];try{let{runInProcessCliCommand:a}=await import(`@x-otto/coding`),o=await a(async()=>(await e.handler({args:t,tui:{openInput:e=>r.modal.openModal({kind:`input`,title:e.title,...e.description?{description:e.description}:{},...e.placeholder?{placeholder:e.placeholder}:{}}),confirm:(e,t)=>new Promise(n=>{r.modal.openModal({kind:`confirm`,title:e,message:t,onConfirm:()=>n(!0),onCancel:()=>n(!1)})}),openPluginPanel:e=>(r.modal.openModal({kind:`pluginPanel`,panelInfo:{title:e.title,modulePath:e.modulePath,exportName:e.exportName,pluginId:e.pluginId},onClose:()=>{}}),Promise.resolve()),showToast:(e,t)=>r.info.showToast(e,t)},app:{workspaceDir:n.app.workspaceDir,modelId:n.state.session.model?.id,settings:{get:e=>n.app.settings.get(e)},pluginPanels:i.map(e=>({pluginId:e.pluginId,title:e.title,modulePath:e.modulePath,exportName:e.exportName}))}}),0));o===124?r.info.showToast(`plugin`,`斜杠命令 /${e.name} 执行超时(已停止等待,handler 可能仍在后台运行)`):o!==0&&r.info.showToast(`plugin`,`斜杠命令 /${e.name} 执行失败(handler 抛出异常,详见日志)`)}catch(t){let n=t instanceof Error?t.message:String(t);r.info.showToast(`plugin`,`斜杠命令 /${e.name} 执行失败:${n}`)}}export{dt as $,or as A,qe as B,pr as C,sr as D,hr as E,pn as F,tn as G,tt as H,dn as I,R as J,Wt as K,un as L,vn as M,H as N,ar as O,fn as P,Ut as Q,cn as R,K as S,mr as T,z as U,Ye as V,nn as W,Kt as X,Gt as Y,Yt as Z,Er as _,Fa as a,Et as at,yr as b,ra as c,Wi as d,Lt as et,zi as f,ni as g,pi as h,$ as i,Dt as it,En as j,ir as k,ia as l,X as m,Na as n,kt as nt,Aa as o,bt as ot,vi as p,qt as q,Ma as r,F as rt,La as s,Pa as t,Ot as tt,Gi as u,vr as v,dr as w,gr as x,xr as y,sn as z};
18
- //# sourceMappingURL=command-dispatcher-CKj6qR-G.js.map