@x-otto/cli 0.0.1-alpha.16-debug → 0.0.1-alpha.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -65
- package/dist/{auth-command-CKlvZtbJ.js → auth-command-kkJh-O5y.js} +2 -2
- package/dist/auth-command-kkJh-O5y.js.map +1 -0
- package/dist/build-id-B2hTdEbZ.js +3 -0
- package/dist/build-id-B2hTdEbZ.js.map +1 -0
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/meta.json +1 -1
- package/dist/bundled-extensions/plugin-otto-wire-protocols/plugin-dist/plugin.cjs +37144 -193
- package/dist/bundled-extensions/plugin-otto-wire-protocols/src/anthropic-messages.ts +2 -2
- package/dist/bundled-extensions-C3n8jg20.js +3 -0
- package/dist/bundled-extensions-C3n8jg20.js.map +1 -0
- package/dist/{command-dispatcher-DibEV53Q.js → command-dispatcher-CbFjx7bg.js} +6 -6
- package/dist/command-dispatcher-CbFjx7bg.js.map +1 -0
- package/dist/{config-migration-DatflIxs.js → config-migration-0zdXsEDB.js} +1 -1
- package/dist/{config-migration-DatflIxs.js.map → config-migration-0zdXsEDB.js.map} +1 -1
- package/dist/create-host-app-BXQ8bU-B.js +3 -0
- package/dist/create-host-app-BXQ8bU-B.js.map +1 -0
- package/dist/create-host-app-DXII2WTM.js +2 -0
- package/dist/{daemon-COESl-zU.js → daemon-BtiaXSxn.js} +1 -1
- package/dist/{daemon-COESl-zU.js.map → daemon-BtiaXSxn.js.map} +1 -1
- package/dist/{daemon-base-YOWgYYN7.js → daemon-base-DKeB2Nyv.js} +1 -1
- package/dist/{daemon-base-YOWgYYN7.js.map → daemon-base-DKeB2Nyv.js.map} +1 -1
- package/dist/{debug-CiosFwme.js → debug-DfgcrVCI.js} +2 -2
- package/dist/{debug-CiosFwme.js.map → debug-DfgcrVCI.js.map} +1 -1
- package/dist/discover-with-bundled-B5d4q___.js +2 -0
- package/dist/discover-with-bundled-CF8qFP41.js +3 -0
- package/dist/discover-with-bundled-CF8qFP41.js.map +1 -0
- package/dist/doctor-DbQC8Z7p.js +36 -0
- package/dist/doctor-DbQC8Z7p.js.map +1 -0
- package/dist/{doctor-attach-_zeIJewx.js → doctor-attach-OJHn8L52.js} +2 -2
- package/dist/{doctor-attach-_zeIJewx.js.map → doctor-attach-OJHn8L52.js.map} +1 -1
- package/dist/{doctor-cdp-K_mIFRfA.js → doctor-cdp-D66ChCCN.js} +1 -1
- package/dist/{doctor-cdp-K_mIFRfA.js.map → doctor-cdp-D66ChCCN.js.map} +1 -1
- package/dist/{doctor-heap-Rr2nNvcw.js → doctor-heap-Brsro5QJ.js} +2 -2
- package/dist/{doctor-heap-Rr2nNvcw.js.map → doctor-heap-Brsro5QJ.js.map} +1 -1
- package/dist/{doctor-ps-OL3FGQYu.js → doctor-ps-B4Syy9qa.js} +2 -2
- package/dist/{doctor-ps-OL3FGQYu.js.map → doctor-ps-B4Syy9qa.js.map} +1 -1
- package/dist/{extension-DAex6RFK.js → extension-DLFCUBJr.js} +41 -33
- package/dist/extension-DLFCUBJr.js.map +1 -0
- package/dist/extension-I87MkZYp.js +2 -0
- package/dist/{extension-plugin-D7gnpllF.js → extension-plugin-DoEcnDu5.js} +4 -4
- package/dist/{extension-plugin-D7gnpllF.js.map → extension-plugin-DoEcnDu5.js.map} +1 -1
- package/dist/extension-plugin-VUdbaAN7.js +2 -0
- package/dist/feedback-DwQu2BmU.js +21 -0
- package/dist/feedback-DwQu2BmU.js.map +1 -0
- package/dist/feedback-j4tDn2uI.js +2 -0
- package/dist/{feishu-setup-DIcd3PMK.js → feishu-setup-C2UDdpIm.js} +2 -2
- package/dist/{feishu-setup-DIcd3PMK.js.map → feishu-setup-C2UDdpIm.js.map} +1 -1
- package/dist/ftue-doctor-recovery-DhiseXnP.js +3 -0
- package/dist/ftue-doctor-recovery-DhiseXnP.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/install-DkJgbg2p.js +2 -0
- package/dist/{install-DlVJRHRT.js → install-hTDjeo61.js} +1 -1
- package/dist/{install-DlVJRHRT.js.map → install-hTDjeo61.js.map} +1 -1
- package/dist/{mcp-DbTYT7hB.js → mcp-BDfBf6gx.js} +1 -1
- package/dist/{mcp-DbTYT7hB.js.map → mcp-BDfBf6gx.js.map} +1 -1
- package/dist/{migrate-boDXhEyV.js → migrate-4QDwYLf6.js} +2 -2
- package/dist/{migrate-boDXhEyV.js.map → migrate-4QDwYLf6.js.map} +1 -1
- package/dist/{model-auth-Dih25xOB.js → model-auth-B6ufdM5K.js} +2 -2
- package/dist/{model-auth-Dih25xOB.js.map → model-auth-B6ufdM5K.js.map} +1 -1
- package/dist/model-auth-DMczbHA9.js +2 -0
- package/dist/{observe-CVg-MRM2.js → observe-C2jjDNDa.js} +2 -2
- package/dist/{observe-CVg-MRM2.js.map → observe-C2jjDNDa.js.map} +1 -1
- package/dist/{parse-cli-Dr-Fl0on.js → parse-cli-Cw5qyM5B.js} +2 -2
- package/dist/{parse-cli-Dr-Fl0on.js.map → parse-cli-Cw5qyM5B.js.map} +1 -1
- package/dist/{persistenced-CCwHu1Ww.js → persistenced-CcAhVOE7.js} +2 -2
- package/dist/{persistenced-CCwHu1Ww.js.map → persistenced-CcAhVOE7.js.map} +1 -1
- package/dist/plugin-assembly-check-CvuJ4dHf.js +3 -0
- package/dist/plugin-assembly-check-CvuJ4dHf.js.map +1 -0
- package/dist/{proxy-evg7ZvoD.js → proxy-CMQBvdZC.js} +1 -1
- package/dist/{proxy-evg7ZvoD.js.map → proxy-CMQBvdZC.js.map} +1 -1
- package/dist/proxy-TzOLqtkc.js +2 -0
- package/dist/{ps-DKrluEuy.js → ps-BWGntaR4.js} +1 -1
- package/dist/{ps-DKrluEuy.js.map → ps-BWGntaR4.js.map} +1 -1
- package/dist/{registry-D0NONjLv.js → registry-Cr5To_5r.js} +3 -3
- package/dist/registry-Cr5To_5r.js.map +1 -0
- package/dist/registry-DAJ7oZTe.js +2 -0
- package/dist/{remote-persistence-server-B_hONoVR.js → remote-persistence-server-CLI-y-zp.js} +2 -2
- package/dist/{remote-persistence-server-B_hONoVR.js.map → remote-persistence-server-CLI-y-zp.js.map} +1 -1
- package/dist/{run-attach-Ci5jYyCa.js → run-attach-DZmBqVjI.js} +2 -2
- package/dist/{run-attach-Ci5jYyCa.js.map → run-attach-DZmBqVjI.js.map} +1 -1
- package/dist/{serve-pVR6UIT9.js → serve-vWHGydiC.js} +3 -3
- package/dist/serve-vWHGydiC.js.map +1 -0
- package/dist/{service-client-BLNeugM9.js → service-client-Cr4sxDVM.js} +1 -1
- package/dist/{service-client-BLNeugM9.js.map → service-client-Cr4sxDVM.js.map} +1 -1
- package/dist/{time-travel-ZozuPPI-.js → time-travel-D1sg5dEb.js} +2 -2
- package/dist/{time-travel-ZozuPPI-.js.map → time-travel-D1sg5dEb.js.map} +1 -1
- package/dist/{version-Cd8HZ7ua.js → version-BaBgJOxV.js} +2 -2
- package/dist/{version-Cd8HZ7ua.js.map → version-BaBgJOxV.js.map} +1 -1
- package/package.json +3 -3
- package/dist/auth-command-CKlvZtbJ.js.map +0 -1
- package/dist/build-id-CIFJCmlj.js +0 -3
- package/dist/build-id-CIFJCmlj.js.map +0 -1
- package/dist/command-dispatcher-DibEV53Q.js.map +0 -1
- package/dist/discover-with-bundled-wSuXDvNc.js +0 -3
- package/dist/discover-with-bundled-wSuXDvNc.js.map +0 -1
- package/dist/doctor-C84-hhEr.js +0 -30
- package/dist/doctor-C84-hhEr.js.map +0 -1
- package/dist/extension-C3AP3KxC.js +0 -2
- package/dist/extension-DAex6RFK.js.map +0 -1
- package/dist/extension-plugin-fPDz7XlG.js +0 -2
- package/dist/feedback-BVl4sRah.js +0 -21
- package/dist/feedback-BVl4sRah.js.map +0 -1
- package/dist/feedback-DAY-1bJ0.js +0 -2
- package/dist/install-WCcQ9k9M.js +0 -2
- package/dist/model-auth-BxHBaDQx.js +0 -2
- package/dist/proxy-BvdBsB1O.js +0 -2
- package/dist/registry-B3nfN62q.js +0 -2
- package/dist/registry-D0NONjLv.js.map +0 -1
- package/dist/serve-pVR6UIT9.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feishu-setup-DIcd3PMK.js","names":[],"sources":["../src/commands/handlers/feishu-setup.ts"],"sourcesContent":["/**\n * /feishu-setup 命令:飞书 webhook 绑定交互向导。\n */\nimport { spawn } from 'node:child_process'\nimport { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { findWorkspaceRoot } from '@x-otto/coding'\nimport { discoverPluginsWithBundled } from '../../discover-with-bundled'\nimport type { CliContext } from '../../command-dispatcher'\n\n/** 按优先级计算 feishu-use 配置文件候选路径(project > repo > user),返回最高优先级路径。 */\nfunction resolveConfigPath(cwd: string): string {\n const repoRoot = findWorkspaceRoot(cwd)\n if (repoRoot && join(repoRoot) !== join(cwd)) {\n return join(cwd, '.otto', 'feishu-use.json')\n }\n return join(cwd, '.otto', 'feishu-use.json')\n}\n\nexport interface FeishuSetupResult {\n /** app_id 已写入配置 */\n appId: string\n /** bot/v3/info 返回的 bot 身份;验证失败时为 undefined */\n botOpenId?: string\n botName?: string\n /** 实际写入的配置文件路径 */\n configPath: string\n /** setup 是否完整成功(凭据已写入 + bot 身份已验证) */\n success: boolean\n}\n\n/** 往指定路径写入 feishu-use 配置文件(mode 0o600),覆盖已有文件。 */\nfunction writeFeishuConfigFile(configPath: string, overrides: Record<string, unknown>): string {\n const base = {\n app_id: 'REPLACE_WITH_YOUR_FEISHU_APP_ID',\n app_secret: 'REPLACE_WITH_YOUR_FEISHU_APP_SECRET',\n allowed_chats: [] as string[],\n workspace_dir: join(configPath, '..', '..', 'feishu-use-workspace'),\n max_reply_chunk_length: 4000,\n }\n const merged = { ...base }\n for (const [k, v] of Object.entries(overrides)) {\n if (v !== undefined && v !== '') (merged as Record<string, unknown>)[k] = v\n }\n mkdirSync(join(configPath, '..'), { recursive: true })\n writeFileSync(configPath, JSON.stringify(merged, null, 2) + '\\n', { mode: 0o600 })\n return configPath\n}\n\n/** 从配置文件读取当前值;文件不存在时返回 undefined。 */\nfunction readConfigSafe(configPath: string): Record<string, unknown> | undefined {\n try {\n if (!existsSync(configPath)) return undefined\n return JSON.parse(readFileSync(configPath, 'utf8')) as Record<string, unknown>\n } catch {\n return undefined\n }\n}\n\n/** openSelect 的 Promise 包装:用户选择 → resolve(value),Esc/取消 → resolve(undefined)。 */\nfunction promiseSelect(\n ctx: CliContext,\n opts: { title: string; options: Array<{ label: string; value: string; detail?: string }> },\n): Promise<string | undefined> {\n return new Promise((resolve) => {\n ctx.tui.modal.openModal({\n kind: 'select',\n ...opts,\n onSelect: (v) => resolve(v),\n onCancel: () => resolve(undefined),\n })\n })\n}\n\n/** openConfirm 的 Promise 包装:确认 → resolve(true),取消 → resolve(false)。 */\nfunction promiseConfirm(ctx: CliContext, title: string, message: string | string[]): Promise<boolean> {\n return new Promise((resolve) => {\n ctx.tui.modal.openModal({\n kind: 'confirm',\n title,\n message,\n onConfirm: () => resolve(true),\n onCancel: () => resolve(false),\n })\n })\n}\n\n/**\n * 启动 `registerApp` 子进程并等待结果。\n *\n * 子进程 stdout 输出 JSON `{ client_id, client_secret }` 表示成功;\n * 超时/崩溃/非零退出码 → resolve(undefined)。\n *\n * `pluginDir` 是 feishu-use 插件安装目录(含 node_modules/@larksuiteoapi/node-sdk)。\n *\n * `onQrCodeUrl`(RFC-134 §8 F1 修复):QR 码 URL 由 SDK `onQRCodeReady` 回调在子进程侧\n * 产生,经 `QRCODE_URL::<json>` 前缀行写入 stderr——本函数解析该前缀行并回调给调用方展示,\n * 修复此前\"stderr 从未被读取、URL 被静默丢弃\"的缺陷(用户选择扫码后永远看不到二维码)。\n */\nfunction runRegisterApp(\n pluginDir: string,\n timeoutMs = 5 * 60 * 1000,\n onQrCodeUrl?: (info: { url: string; expireIn: number }) => void,\n): Promise<{ client_id: string; client_secret: string } | undefined> {\n return new Promise((resolve) => {\n const scriptPath = join(pluginDir, 'scripts', 'register-app.mjs')\n if (!existsSync(scriptPath)) {\n resolve(undefined)\n return\n }\n\n const child = spawn('node', [scriptPath], {\n cwd: pluginDir,\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: timeoutMs,\n env: { ...process.env },\n })\n\n let stdout = ''\n let stderr = ''\n let qrEmitted = false\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString()\n })\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString()\n if (qrEmitted || !onQrCodeUrl) return\n const line = stderr.split('\\n').find((l) => l.startsWith('QRCODE_URL::'))\n if (!line) return\n try {\n const info = JSON.parse(line.slice('QRCODE_URL::'.length)) as { url: string; expireIn: number }\n if (info.url) {\n qrEmitted = true\n onQrCodeUrl(info)\n }\n } catch {\n /* 前缀行畸形,忽略,等待后续 data 事件或直到子进程结束都拿不到 URL */\n }\n })\n\n child.on('error', () => resolve(undefined))\n child.on('close', (code) => {\n if (code !== 0) return resolve(undefined)\n try {\n const result = JSON.parse(stdout.trim().split('\\n').pop()!) as {\n client_id: string\n client_secret: string\n }\n if (result.client_id && result.client_secret) {\n resolve(result)\n return\n }\n } catch {\n /* fall through */\n }\n resolve(undefined)\n })\n })\n}\n\n/**\n * 用 app_id/app_secret 调用 `bot/v3/info` 验证凭据并获取 bot 身份。\n *\n * 子进程执行插件自带脚本 `scripts/verify-bot.mjs`(与 `runRegisterApp` 调用\n * `register-app.mjs` 同模式,终局架构 review 2026-07-20 下沉)——宿主 CLI 只负责\n * spawn + 传参 + 解析结果,不内联飞书 SDK 的具体调用细节(`bot/v3/info` 端点/Client\n * 构造方式),保持 RFC-134 D2 的架构隔离:`packages/cli` 对插件内部实现零认知。\n * 失败(网络不通/凭据错误/权限不足/脚本缺失)返回 undefined。\n */\nfunction verifyBotIdentity(\n pluginDir: string,\n appId: string,\n appSecret: string,\n): Promise<{ openId: string; name: string } | undefined> {\n return new Promise((resolve) => {\n const scriptPath = join(pluginDir, 'scripts', 'verify-bot.mjs')\n if (!existsSync(scriptPath)) {\n resolve(undefined)\n return\n }\n\n const child = spawn('node', [scriptPath], {\n cwd: pluginDir,\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: 15_000,\n env: { ...process.env, FEISHU_VERIFY_APP_ID: appId, FEISHU_VERIFY_APP_SECRET: appSecret },\n })\n\n let stdout = ''\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString()\n })\n\n child.on('error', () => resolve(undefined))\n child.on('close', (code) => {\n if (code !== 0) return resolve(undefined)\n try {\n const r = JSON.parse(stdout.trim()) as { openId: string; name: string }\n resolve(r)\n } catch {\n resolve(undefined)\n }\n })\n })\n}\n\n/** 脱敏 App ID:前 8 字符 + *** + 后 4 字符。 */\nfunction maskAppId(appId: string): string {\n if (appId.length <= 12) return appId.slice(0, 4) + '***'\n return appId.slice(0, 8) + '***' + appId.slice(-4)\n}\n\n/**\n * feishu-use 交互式配置向导主入口(RFC-134 M1)。\n *\n * 在 TUI 内调用(需已有 TUI 上下文),通过 async/await 链式编排对话框。\n * 外部调用方负责提供 configPath 和 pluginDir。\n *\n * @param ctx CliContext(需 TUI 可用)\n * @param configPath 配置文件的目标路径(如 `<cwd>/.otto/feishu-use.json`)\n * @param pluginDir feishu-use 插件的安装目录(含 node_modules)\n * @param existingConfig 已有配置(存在时为重配置模式,展示当前值)\n */\nexport async function runFeishuSetupWizard(\n ctx: CliContext,\n configPath: string,\n pluginDir: string,\n existingConfig?: Record<string, unknown>,\n): Promise<FeishuSetupResult | undefined> {\n // ── 重配置模式:展示当前值 + 确认覆盖 ──\n if (existingConfig?.app_id) {\n const currentAppId = String(existingConfig.app_id)\n const lines = [\n `App ID: ${maskAppId(currentAppId)}`,\n existingConfig.allowed_chats\n ? `allowed_chats: ${(existingConfig.allowed_chats as string[]).length} 个`\n : 'allowed_chats: 空(拒绝所有)',\n `配置路径: ${configPath}`,\n ]\n const confirmed = await promiseConfirm(ctx, 'feishu-use 重配置', ['当前配置:', '', ...lines, '', '确定要重新配置吗?当前凭据将被覆盖。'])\n if (!confirmed) return undefined\n }\n\n // ── Step 1: 选择配置方式 ──\n const method = await promiseSelect(ctx, {\n title: 'feishu-use 配置',\n options: [\n { label: '扫码自动创建飞书应用(推荐)', value: 'qr', detail: '飞书 App 扫码确认后自动获取凭据' },\n { label: '手动输入 App ID / App Secret', value: 'manual', detail: '已有飞书自建应用,直接填入凭据' },\n ],\n })\n if (!method) return undefined // user cancelled\n\n let appId = ''\n let appSecret = ''\n let allowedChats: string[] = []\n let trustedChats: string[] = []\n\n // ── Step 2a: QR 码路径 ──\n if (method === 'qr') {\n ctx.tui.info.showToast('plugin-feishu-use', '正在生成飞书应用注册二维码,请稍候…')\n\n const result = await runRegisterApp(pluginDir, 5 * 60 * 1000, (info) => {\n // RFC-134 §8 F1 修复:QR URL 必须展示给用户才能完成扫码,此前写入 stderr 后\n // 从未被读取,用户永远看不到二维码。用 pushMessage(非 toast)展示——toast 会\n // 在几秒后自动消失,而用户需要足够时间打开飞书 App 扫码。\n const expireMinutes = Math.round(info.expireIn / 60)\n ctx.tui.messages.pushMessage({\n role: 'assistant',\n content: [{\n type: 'text',\n text: `feishu-use:请在飞书 App 中打开以下链接扫码确认创建应用(${expireMinutes} 分钟内有效):\\n${info.url}`,\n }],\n })\n })\n if (!result) {\n // 超时或失败 → 回退到手动输入\n const retry = await promiseConfirm(ctx, 'plugin-feishu-use', '扫码注册失败(超时或网络错误)。是否改为手动输入凭据?')\n if (!retry) return undefined\n // 继续执行 manual 路径(故意 fall-through)\n } else {\n appId = result.client_id\n appSecret = result.client_secret\n ctx.tui.info.showToast('plugin-feishu-use', '扫码注册成功!凭据已自动填充。')\n }\n }\n\n // ── Step 2b: 手动输入路径(或 QR 失败后回退) ──\n if (!appId) {\n const hintId = existingConfig?.app_id ? `(当前: ${maskAppId(String(existingConfig.app_id))},留空保留原值)` : ''\n const enteredId = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '飞书 App ID',\n placeholder: `cli_xxxxxxxxxxxx ${hintId}`,\n description: [],\n })\n if (enteredId === null) return undefined\n appId = enteredId || String(existingConfig?.app_id ?? '')\n\n const enteredSecret = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '飞书 App Secret',\n mask: true,\n description: existingConfig?.app_secret ? ['留空保留当前 Secret'] : [],\n })\n if (enteredSecret === null) return undefined\n appSecret = enteredSecret || String(existingConfig?.app_secret ?? '')\n\n if (!appId || !appSecret) {\n ctx.tui.info.showToast('plugin-feishu-use', 'App ID 和 App Secret 不能为空,配置已取消。')\n return undefined\n }\n\n // 可选字段\n const chatsRaw = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '允许的 chat_id(逗号分隔,留空=拒绝所有)',\n placeholder: existingConfig ? `当前: ${(existingConfig.allowed_chats as string[] | undefined)?.join(', ') ?? '空'}` : '',\n description: [],\n })\n if (chatsRaw === null) return undefined\n if (chatsRaw) {\n allowedChats = chatsRaw.split(',').map(s => s.trim()).filter(Boolean)\n } else if (existingConfig?.allowed_chats) {\n allowedChats = existingConfig.allowed_chats as string[]\n }\n\n const trustedRaw = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '可信 chat_id(逗号分隔,留空=仅只读)',\n placeholder: existingConfig ? `当前: ${(existingConfig.trusted_chats as string[] | undefined)?.join(', ') ?? '空'}` : '',\n description: [],\n })\n if (trustedRaw === null) return undefined\n if (trustedRaw) {\n trustedChats = trustedRaw.split(',').map(s => s.trim()).filter(Boolean)\n } else if (existingConfig?.trusted_chats) {\n trustedChats = existingConfig.trusted_chats as string[]\n }\n }\n\n // ── Step 3: 写入配置 ──\n const workspaceDir = existingConfig?.workspace_dir\n ? String(existingConfig.workspace_dir)\n : join(pluginDir, '..', '..', 'feishu-use-workspace')\n writeFeishuConfigFile(configPath, {\n app_id: appId,\n app_secret: appSecret,\n allowed_chats: allowedChats,\n trusted_chats: trustedChats,\n workspace_dir: workspaceDir,\n })\n\n ctx.tui.info.showToast('plugin-feishu-use', `配置已写入 ${configPath}`)\n\n // ── Step 4: 验证 bot 身份 ──\n const bot = await verifyBotIdentity(pluginDir, appId, appSecret)\n if (bot) {\n ctx.tui.info.showToast('plugin-feishu-use', `Bot 身份验证成功:${bot.name} (${bot.openId})`)\n } else {\n ctx.tui.messages.pushMessage({\n role: 'command_echo',\n command: '/feishu setup',\n status: 'error',\n summary: 'bot 身份验证失败(凭据不正确或网络不可达)',\n detail: '请稍后用 `otto feishu config set` 修正凭据,或手动编辑配置文件。',\n })\n }\n\n return {\n appId,\n botOpenId: bot?.openId,\n botName: bot?.name,\n configPath,\n success: !!bot,\n }\n}\n\n/**\n * 给 runFeishuSetupWizard 准备参数的外层封装:计算 configPath 和 pluginDir。\n *\n * @returns setup 结果,或 undefined(用户取消)\n */\nexport async function launchFeishuSetup(\n ctx: CliContext,\n): Promise<FeishuSetupResult | undefined> {\n const ws = ctx.app.workspaceDir ?? process.cwd()\n const configPath = resolveConfigPath(ws)\n\n // 找到 feishu-use 的安装目录(插件目录 = 含 otto-plugin.json 的目录)\n const allPlugins = discoverPluginsWithBundled({ cwd: ws, homedir: homedir() })\n const feishuPlugin = allPlugins.find(p => p.id === 'plugin-feishu-use')\n if (!feishuPlugin) {\n ctx.tui.info.showToast('plugin-feishu-use', 'feishu-use 插件尚未安装,请先在 `/model` 安装入口安装 feishu-use。')\n return undefined\n }\n\n const pluginDir = feishuPlugin.dir\n const existing = readConfigSafe(configPath)\n\n return runFeishuSetupWizard(ctx, configPath, pluginDir, existing)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feishu-setup-C2UDdpIm.js","names":[],"sources":["../src/commands/handlers/feishu-setup.ts"],"sourcesContent":["/**\n * /feishu-setup 命令:飞书 webhook 绑定交互向导。\n */\nimport { spawn } from 'node:child_process'\nimport { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { findWorkspaceRoot } from '@x-otto/coding'\nimport { discoverPluginsWithBundled } from '../../discover-with-bundled'\nimport type { CliContext } from '../../command-dispatcher'\n\n/** 按优先级计算 feishu-use 配置文件候选路径(project > repo > user),返回最高优先级路径。 */\nfunction resolveConfigPath(cwd: string): string {\n const repoRoot = findWorkspaceRoot(cwd)\n if (repoRoot && join(repoRoot) !== join(cwd)) {\n return join(cwd, '.otto', 'feishu-use.json')\n }\n return join(cwd, '.otto', 'feishu-use.json')\n}\n\nexport interface FeishuSetupResult {\n /** app_id 已写入配置 */\n appId: string\n /** bot/v3/info 返回的 bot 身份;验证失败时为 undefined */\n botOpenId?: string\n botName?: string\n /** 实际写入的配置文件路径 */\n configPath: string\n /** setup 是否完整成功(凭据已写入 + bot 身份已验证) */\n success: boolean\n}\n\n/** 往指定路径写入 feishu-use 配置文件(mode 0o600),覆盖已有文件。 */\nfunction writeFeishuConfigFile(configPath: string, overrides: Record<string, unknown>): string {\n const base = {\n app_id: 'REPLACE_WITH_YOUR_FEISHU_APP_ID',\n app_secret: 'REPLACE_WITH_YOUR_FEISHU_APP_SECRET',\n allowed_chats: [] as string[],\n workspace_dir: join(configPath, '..', '..', 'feishu-use-workspace'),\n max_reply_chunk_length: 4000,\n }\n const merged = { ...base }\n for (const [k, v] of Object.entries(overrides)) {\n if (v !== undefined && v !== '') (merged as Record<string, unknown>)[k] = v\n }\n mkdirSync(join(configPath, '..'), { recursive: true })\n writeFileSync(configPath, JSON.stringify(merged, null, 2) + '\\n', { mode: 0o600 })\n return configPath\n}\n\n/** 从配置文件读取当前值;文件不存在时返回 undefined。 */\nfunction readConfigSafe(configPath: string): Record<string, unknown> | undefined {\n try {\n if (!existsSync(configPath)) return undefined\n return JSON.parse(readFileSync(configPath, 'utf8')) as Record<string, unknown>\n } catch {\n return undefined\n }\n}\n\n/** openSelect 的 Promise 包装:用户选择 → resolve(value),Esc/取消 → resolve(undefined)。 */\nfunction promiseSelect(\n ctx: CliContext,\n opts: { title: string; options: Array<{ label: string; value: string; detail?: string }> },\n): Promise<string | undefined> {\n return new Promise((resolve) => {\n ctx.tui.modal.openModal({\n kind: 'select',\n ...opts,\n onSelect: (v) => resolve(v),\n onCancel: () => resolve(undefined),\n })\n })\n}\n\n/** openConfirm 的 Promise 包装:确认 → resolve(true),取消 → resolve(false)。 */\nfunction promiseConfirm(ctx: CliContext, title: string, message: string | string[]): Promise<boolean> {\n return new Promise((resolve) => {\n ctx.tui.modal.openModal({\n kind: 'confirm',\n title,\n message,\n onConfirm: () => resolve(true),\n onCancel: () => resolve(false),\n })\n })\n}\n\n/**\n * 启动 `registerApp` 子进程并等待结果。\n *\n * 子进程 stdout 输出 JSON `{ client_id, client_secret }` 表示成功;\n * 超时/崩溃/非零退出码 → resolve(undefined)。\n *\n * `pluginDir` 是 feishu-use 插件安装目录(含 node_modules/@larksuiteoapi/node-sdk)。\n *\n * `onQrCodeUrl`(RFC-134 §8 F1 修复):QR 码 URL 由 SDK `onQRCodeReady` 回调在子进程侧\n * 产生,经 `QRCODE_URL::<json>` 前缀行写入 stderr——本函数解析该前缀行并回调给调用方展示,\n * 修复此前\"stderr 从未被读取、URL 被静默丢弃\"的缺陷(用户选择扫码后永远看不到二维码)。\n */\nfunction runRegisterApp(\n pluginDir: string,\n timeoutMs = 5 * 60 * 1000,\n onQrCodeUrl?: (info: { url: string; expireIn: number }) => void,\n): Promise<{ client_id: string; client_secret: string } | undefined> {\n return new Promise((resolve) => {\n const scriptPath = join(pluginDir, 'scripts', 'register-app.mjs')\n if (!existsSync(scriptPath)) {\n resolve(undefined)\n return\n }\n\n const child = spawn('node', [scriptPath], {\n cwd: pluginDir,\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: timeoutMs,\n env: { ...process.env },\n })\n\n let stdout = ''\n let stderr = ''\n let qrEmitted = false\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString()\n })\n child.stderr.on('data', (chunk: Buffer) => {\n stderr += chunk.toString()\n if (qrEmitted || !onQrCodeUrl) return\n const line = stderr.split('\\n').find((l) => l.startsWith('QRCODE_URL::'))\n if (!line) return\n try {\n const info = JSON.parse(line.slice('QRCODE_URL::'.length)) as { url: string; expireIn: number }\n if (info.url) {\n qrEmitted = true\n onQrCodeUrl(info)\n }\n } catch {\n /* 前缀行畸形,忽略,等待后续 data 事件或直到子进程结束都拿不到 URL */\n }\n })\n\n child.on('error', () => resolve(undefined))\n child.on('close', (code) => {\n if (code !== 0) return resolve(undefined)\n try {\n const result = JSON.parse(stdout.trim().split('\\n').pop()!) as {\n client_id: string\n client_secret: string\n }\n if (result.client_id && result.client_secret) {\n resolve(result)\n return\n }\n } catch {\n /* fall through */\n }\n resolve(undefined)\n })\n })\n}\n\n/**\n * 用 app_id/app_secret 调用 `bot/v3/info` 验证凭据并获取 bot 身份。\n *\n * 子进程执行插件自带脚本 `scripts/verify-bot.mjs`(与 `runRegisterApp` 调用\n * `register-app.mjs` 同模式,终局架构 review 2026-07-20 下沉)——宿主 CLI 只负责\n * spawn + 传参 + 解析结果,不内联飞书 SDK 的具体调用细节(`bot/v3/info` 端点/Client\n * 构造方式),保持 RFC-134 D2 的架构隔离:`packages/cli` 对插件内部实现零认知。\n * 失败(网络不通/凭据错误/权限不足/脚本缺失)返回 undefined。\n */\nfunction verifyBotIdentity(\n pluginDir: string,\n appId: string,\n appSecret: string,\n): Promise<{ openId: string; name: string } | undefined> {\n return new Promise((resolve) => {\n const scriptPath = join(pluginDir, 'scripts', 'verify-bot.mjs')\n if (!existsSync(scriptPath)) {\n resolve(undefined)\n return\n }\n\n const child = spawn('node', [scriptPath], {\n cwd: pluginDir,\n stdio: ['ignore', 'pipe', 'pipe'],\n timeout: 15_000,\n env: { ...process.env, FEISHU_VERIFY_APP_ID: appId, FEISHU_VERIFY_APP_SECRET: appSecret },\n })\n\n let stdout = ''\n child.stdout.on('data', (chunk: Buffer) => {\n stdout += chunk.toString()\n })\n\n child.on('error', () => resolve(undefined))\n child.on('close', (code) => {\n if (code !== 0) return resolve(undefined)\n try {\n const r = JSON.parse(stdout.trim()) as { openId: string; name: string }\n resolve(r)\n } catch {\n resolve(undefined)\n }\n })\n })\n}\n\n/** 脱敏 App ID:前 8 字符 + *** + 后 4 字符。 */\nfunction maskAppId(appId: string): string {\n if (appId.length <= 12) return appId.slice(0, 4) + '***'\n return appId.slice(0, 8) + '***' + appId.slice(-4)\n}\n\n/**\n * feishu-use 交互式配置向导主入口(RFC-134 M1)。\n *\n * 在 TUI 内调用(需已有 TUI 上下文),通过 async/await 链式编排对话框。\n * 外部调用方负责提供 configPath 和 pluginDir。\n *\n * @param ctx CliContext(需 TUI 可用)\n * @param configPath 配置文件的目标路径(如 `<cwd>/.otto/feishu-use.json`)\n * @param pluginDir feishu-use 插件的安装目录(含 node_modules)\n * @param existingConfig 已有配置(存在时为重配置模式,展示当前值)\n */\nexport async function runFeishuSetupWizard(\n ctx: CliContext,\n configPath: string,\n pluginDir: string,\n existingConfig?: Record<string, unknown>,\n): Promise<FeishuSetupResult | undefined> {\n // ── 重配置模式:展示当前值 + 确认覆盖 ──\n if (existingConfig?.app_id) {\n const currentAppId = String(existingConfig.app_id)\n const lines = [\n `App ID: ${maskAppId(currentAppId)}`,\n existingConfig.allowed_chats\n ? `allowed_chats: ${(existingConfig.allowed_chats as string[]).length} 个`\n : 'allowed_chats: 空(拒绝所有)',\n `配置路径: ${configPath}`,\n ]\n const confirmed = await promiseConfirm(ctx, 'feishu-use 重配置', ['当前配置:', '', ...lines, '', '确定要重新配置吗?当前凭据将被覆盖。'])\n if (!confirmed) return undefined\n }\n\n // ── Step 1: 选择配置方式 ──\n const method = await promiseSelect(ctx, {\n title: 'feishu-use 配置',\n options: [\n { label: '扫码自动创建飞书应用(推荐)', value: 'qr', detail: '飞书 App 扫码确认后自动获取凭据' },\n { label: '手动输入 App ID / App Secret', value: 'manual', detail: '已有飞书自建应用,直接填入凭据' },\n ],\n })\n if (!method) return undefined // user cancelled\n\n let appId = ''\n let appSecret = ''\n let allowedChats: string[] = []\n let trustedChats: string[] = []\n\n // ── Step 2a: QR 码路径 ──\n if (method === 'qr') {\n ctx.tui.info.showToast('plugin-feishu-use', '正在生成飞书应用注册二维码,请稍候…')\n\n const result = await runRegisterApp(pluginDir, 5 * 60 * 1000, (info) => {\n // RFC-134 §8 F1 修复:QR URL 必须展示给用户才能完成扫码,此前写入 stderr 后\n // 从未被读取,用户永远看不到二维码。用 pushMessage(非 toast)展示——toast 会\n // 在几秒后自动消失,而用户需要足够时间打开飞书 App 扫码。\n const expireMinutes = Math.round(info.expireIn / 60)\n ctx.tui.messages.pushMessage({\n role: 'assistant',\n content: [{\n type: 'text',\n text: `feishu-use:请在飞书 App 中打开以下链接扫码确认创建应用(${expireMinutes} 分钟内有效):\\n${info.url}`,\n }],\n })\n })\n if (!result) {\n // 超时或失败 → 回退到手动输入\n const retry = await promiseConfirm(ctx, 'plugin-feishu-use', '扫码注册失败(超时或网络错误)。是否改为手动输入凭据?')\n if (!retry) return undefined\n // 继续执行 manual 路径(故意 fall-through)\n } else {\n appId = result.client_id\n appSecret = result.client_secret\n ctx.tui.info.showToast('plugin-feishu-use', '扫码注册成功!凭据已自动填充。')\n }\n }\n\n // ── Step 2b: 手动输入路径(或 QR 失败后回退) ──\n if (!appId) {\n const hintId = existingConfig?.app_id ? `(当前: ${maskAppId(String(existingConfig.app_id))},留空保留原值)` : ''\n const enteredId = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '飞书 App ID',\n placeholder: `cli_xxxxxxxxxxxx ${hintId}`,\n description: [],\n })\n if (enteredId === null) return undefined\n appId = enteredId || String(existingConfig?.app_id ?? '')\n\n const enteredSecret = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '飞书 App Secret',\n mask: true,\n description: existingConfig?.app_secret ? ['留空保留当前 Secret'] : [],\n })\n if (enteredSecret === null) return undefined\n appSecret = enteredSecret || String(existingConfig?.app_secret ?? '')\n\n if (!appId || !appSecret) {\n ctx.tui.info.showToast('plugin-feishu-use', 'App ID 和 App Secret 不能为空,配置已取消。')\n return undefined\n }\n\n // 可选字段\n const chatsRaw = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '允许的 chat_id(逗号分隔,留空=拒绝所有)',\n placeholder: existingConfig ? `当前: ${(existingConfig.allowed_chats as string[] | undefined)?.join(', ') ?? '空'}` : '',\n description: [],\n })\n if (chatsRaw === null) return undefined\n if (chatsRaw) {\n allowedChats = chatsRaw.split(',').map(s => s.trim()).filter(Boolean)\n } else if (existingConfig?.allowed_chats) {\n allowedChats = existingConfig.allowed_chats as string[]\n }\n\n const trustedRaw = await ctx.tui.modal.openModal({\n kind: 'input',\n title: '可信 chat_id(逗号分隔,留空=仅只读)',\n placeholder: existingConfig ? `当前: ${(existingConfig.trusted_chats as string[] | undefined)?.join(', ') ?? '空'}` : '',\n description: [],\n })\n if (trustedRaw === null) return undefined\n if (trustedRaw) {\n trustedChats = trustedRaw.split(',').map(s => s.trim()).filter(Boolean)\n } else if (existingConfig?.trusted_chats) {\n trustedChats = existingConfig.trusted_chats as string[]\n }\n }\n\n // ── Step 3: 写入配置 ──\n const workspaceDir = existingConfig?.workspace_dir\n ? String(existingConfig.workspace_dir)\n : join(pluginDir, '..', '..', 'feishu-use-workspace')\n writeFeishuConfigFile(configPath, {\n app_id: appId,\n app_secret: appSecret,\n allowed_chats: allowedChats,\n trusted_chats: trustedChats,\n workspace_dir: workspaceDir,\n })\n\n ctx.tui.info.showToast('plugin-feishu-use', `配置已写入 ${configPath}`)\n\n // ── Step 4: 验证 bot 身份 ──\n const bot = await verifyBotIdentity(pluginDir, appId, appSecret)\n if (bot) {\n ctx.tui.info.showToast('plugin-feishu-use', `Bot 身份验证成功:${bot.name} (${bot.openId})`)\n } else {\n ctx.tui.messages.pushMessage({\n role: 'command_echo',\n command: '/feishu setup',\n status: 'error',\n summary: 'bot 身份验证失败(凭据不正确或网络不可达)',\n detail: '请稍后用 `otto feishu config set` 修正凭据,或手动编辑配置文件。',\n })\n }\n\n return {\n appId,\n botOpenId: bot?.openId,\n botName: bot?.name,\n configPath,\n success: !!bot,\n }\n}\n\n/**\n * 给 runFeishuSetupWizard 准备参数的外层封装:计算 configPath 和 pluginDir。\n *\n * @returns setup 结果,或 undefined(用户取消)\n */\nexport async function launchFeishuSetup(\n ctx: CliContext,\n): Promise<FeishuSetupResult | undefined> {\n const ws = ctx.app.workspaceDir ?? process.cwd()\n const configPath = resolveConfigPath(ws)\n\n // 找到 feishu-use 的安装目录(插件目录 = 含 otto-plugin.json 的目录)\n const allPlugins = discoverPluginsWithBundled({ cwd: ws, homedir: homedir() })\n const feishuPlugin = allPlugins.find(p => p.id === 'plugin-feishu-use')\n if (!feishuPlugin) {\n ctx.tui.info.showToast('plugin-feishu-use', 'feishu-use 插件尚未安装,请先在 `/model` 安装入口安装 feishu-use。')\n return undefined\n }\n\n const pluginDir = feishuPlugin.dir\n const existing = readConfigSafe(configPath)\n\n return runFeishuSetupWizard(ctx, configPath, pluginDir, existing)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const e={"no-provider-plugin":{summary:`No provider plugin detected.`,recoveryAction:"Run `otto` and follow the setup prompt, or `otto extension install <provider>` directly."},"no-credential":{summary:`Provider plugin found, but no credential is registered.`,recoveryAction:"Run `otto` and connect your account, or `otto auth login <provider>`."},"looks-configured":{summary:`Provider and credential look configured (not a readiness guarantee — model usability is verified at runtime).`,recoveryAction:"Run `otto` in a project to start."}};function t(t){let n;return n=t.providerPluginDiscovered?t.hasAnyCredential?`looks-configured`:`no-credential`:`no-provider-plugin`,{status:n,...e[n]}}export{t as deriveDoctorFtueGuidance};
|
|
3
|
+
//# sourceMappingURL=ftue-doctor-recovery-DhiseXnP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ftue-doctor-recovery-DhiseXnP.js","names":[],"sources":["../src/commands/ftue/ftue-doctor-recovery.ts"],"sourcesContent":["/**\n * ftue-doctor-recovery.ts — RFC-326 M6-01:`otto doctor` 的 FTUE 环境自检 + recovery\n * action 映射。\n *\n * 与 `ftue-snapshot.ts`(TUI 运行时权威判定,5 阶段 `provider→authentication→model→\n * ready→first-prompt`)的关系:**本模块不是它的替代品,是它的轻量诊断变体**。\n *\n * 为什么不能直接复用 `deriveFtueSnapshot`:该函数的 `model` 阶段判据依赖\n * `usableModelIds`——必须先构造真实 `ModelRegistry` 并跑完整 `createModelUsabilityGate`\n * (逐模型探查凭据+订阅风险),这正是 `doctor.ts` 头部已声明的设计约束(RFC-150 D3:\n * doctor 是轻量诊断命令,不承担重依赖/不构造完整 App)。构造完整 App 来回答\"配置好了\n * 没有\"违反了这条约束本身。\n *\n * 因此本模块只收集三个**廉价**事实(无需 App/ModelRegistry):\n * 1. 是否发现任一声明 `provider` capability 的插件(`discoverPluginsWithBundled` 已在\n * doctor 的 `collectPlugins()` 跑过,直接复用其产出,零额外扫描);\n * 2. 是否有任一已登记凭据(`AuthStore.listProviders()`,只读本地 auth.json + env,\n * 不发网络请求、不做 OAuth 刷新,见 `getAuthSource` 头注释);\n * 3. 是否已发出过第一条 prompt(`first_prompt_submitted_at` 是否已写入,读 settings 一个\n * 字段)。\n *\n * 代价:**判据比 TUI 运行时权威判定更宽松**——\"有凭据条目\"不等于\"凭据仍然有效\",\n * 更不等于\"至少一个模型可用\"(那需要逐模型探查订阅 429 风险等,doctor 明确不做)。\n * 这是刻意的取舍:doctor 给出的是\"大方向卡在哪一步\"的诊断提示,不是可发 prompt 的\n * 权威裁决——用户装了 provider、连了凭据后,doctor 会显示\"看起来已配置\",但真正的\n * ready 判定仍然只由 TUI 运行时的 `FtueController` 给出。字段命名与文案措辞需体现\n * 这种不确定性(\"looks configured\" 而非 \"ready\")。\n */\n\n/** doctor 能廉价收集到的三个 FTUE 事实——均为只读本地探查,零网络请求。 */\nexport interface DoctorFtueFacts {\n /** 是否发现任一声明 `provider` capability 的插件(builtin/project/repository/user 任一层)。 */\n providerPluginDiscovered: boolean\n /** 是否有任一已登记凭据(`AuthStore.listProviders().length > 0`)。 */\n hasAnyCredential: boolean\n /** 是否已发出过第一条 prompt(`first_prompt_submitted_at` 已写入)。 */\n firstPromptSubmitted: boolean\n}\n\n/** 廉价诊断阶段——刻意用与 `FtueStage` 不同的类型名,避免调用方误当作权威判定复用。 */\nexport type DoctorFtueStatus =\n | 'no-provider-plugin'\n | 'no-credential'\n | 'looks-configured'\n\nexport interface DoctorFtueGuidance {\n status: DoctorFtueStatus\n /** 面向终端用户的一行诊断文案(英文,doctor 全量输出是纯文本、无 i18n 依赖)。 */\n summary: string\n /** 推荐的下一步命令(纯文本,可直接复制执行)。 */\n recoveryAction: string\n}\n\nconst GUIDANCE: Record<DoctorFtueStatus, Omit<DoctorFtueGuidance, 'status'>> = {\n 'no-provider-plugin': {\n summary: 'No provider plugin detected.',\n recoveryAction: 'Run `otto` and follow the setup prompt, or `otto extension install <provider>` directly.',\n },\n 'no-credential': {\n summary: 'Provider plugin found, but no credential is registered.',\n recoveryAction: 'Run `otto` and connect your account, or `otto auth login <provider>`.',\n },\n 'looks-configured': {\n summary: 'Provider and credential look configured (not a readiness guarantee — model usability is verified at runtime).',\n recoveryAction: 'Run `otto` in a project to start.',\n },\n}\n\n/**\n * 纯函数:由三个廉价事实推导诊断状态 + 建议动作。\n *\n * 判定顺序刻意与 `deriveStage`(ftue-snapshot.ts)的前两级保持一致(provider → 凭据),\n * 但到此为止——本模块不判定\"model\"/\"first-prompt\"两级,因为那需要真实可用性探查。\n * `firstPromptSubmitted` 入参目前只影响 `looks-configured` 分支的文案精细度预留,不\n * 参与状态判定本身(doctor 无法验证\"发过 prompt 时是否真的成功\",展示\"看起来已配置\"\n * 已是本模块能给出的诚实上限)。\n */\nexport function deriveDoctorFtueGuidance(facts: DoctorFtueFacts): DoctorFtueGuidance {\n let status: DoctorFtueStatus\n if (!facts.providerPluginDiscovered) {\n status = 'no-provider-plugin'\n } else if (!facts.hasAnyCredential) {\n status = 'no-credential'\n } else {\n status = 'looks-configured'\n }\n return { status, ...GUIDANCE[status] }\n}\n"],"mappings":";AAqDA,MAAM,EAAyE,CAC7E,qBAAsB,CACpB,QAAS,+BACT,eAAgB,2FACjB,CACD,gBAAiB,CACf,QAAS,0DACT,eAAgB,wEACjB,CACD,mBAAoB,CAClB,QAAS,gHACT,eAAgB,oCACjB,CACF,CAWD,SAAgB,EAAyB,EAA4C,CACnF,IAAI,EAQJ,MAPA,CACE,EADG,EAAM,yBAEC,EAAM,iBAGP,mBAFA,gBAFA,qBAMJ,CAAE,SAAQ,GAAG,EAAS,GAAS"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/cli.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/cli.ts"],"mappings":";;iBAyRsB,MAAA,CAAA,GAAU,OAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{$ as e,A as t,B as n,C as r,D as i,E as a,F as o,G as s,H as c,I as l,J as u,K as d,L as f,M as p,N as m,O as h,P as g,Q as _,R as v,S as y,T as b,U as x,V as S,W as ee,X as C,Y as te,Z as w,_ as T,b as E,c as D,d as O,et as
|
|
2
|
+
import{$ as e,A as t,B as n,C as r,D as i,E as a,F as o,G as s,H as c,I as l,J as u,K as d,L as f,M as p,N as m,O as h,P as g,Q as _,R as v,S as y,T as b,U as x,V as S,W as ee,X as C,Y as te,Z as w,_ as T,b as E,c as D,d as O,et as k,f as ne,g as re,h as ie,i as ae,j as A,k as j,l as M,m as oe,n as se,o as N,p as ce,q as le,r as ue,s as de,t as fe,tt as P,u as F,v as I,w as pe,x as me,y as he,z as ge}from"./command-dispatcher-CbFjx7bg.js";import{t as L}from"./version-BaBgJOxV.js";import{n as R,t as _e}from"./parse-cli-Cw5qyM5B.js";import{t as ve}from"./discover-with-bundled-CF8qFP41.js";import{t as ye}from"./create-host-app-BXQ8bU-B.js";import{n as be,r as xe}from"./model-auth-B6ufdM5K.js";import{n as Se}from"./proxy-CMQBvdZC.js";import{r as Ce}from"./registry-Cr5To_5r.js";import{homedir as z}from"node:os";import{execFile as we,spawn as Te}from"node:child_process";import{SANDBOX_ESCALATION_MARKER as Ee,apiCredentialId as De,buildPluginCliRegistry as Oe,collectPluginThemePresets as B,evaluatePluginTrust as ke,evaluateWorkspaceTrustPrompt as Ae,expandCommandBody as je,findPluginCliNameConflict as Me,globalAgentJobRegistry as V,globalAgentObservability as H,globalProcessRegistry as U,readTaskOutputTail as Ne,resolvePluginCliBin as Pe,resolveSessionTitle as W,spawnPluginCli as Fe,trustProject as G}from"@x-otto/coding";import{globalAgentJobRegistry as Ie,globalProcessRuntime as K,installExitReaper as q}from"@x-otto/runtime";import{buildAllowedEnv as Le,checkShellCommand as Re,createLogger as J,markStartupPhase as ze,rankCandidates as Y,setLogLevel as Be,traceStartupPhase as Ve,traceStartupPhaseSync as He}from"@x-otto/shared";import{BUILD_ID as Ue,OTTO_HOME as We,OTTO_SESSIONS_DIR as Ge,SDK_VERSION as Ke,flushEnvWarnings as X,isShadowModeEnabled as qe,loadUserIdentity as Je}from"@x-otto/env";import{dirname as Ye,join as Z,resolve as Xe}from"node:path";import{existsSync as Ze}from"node:fs";import{fileURLToPath as Qe}from"node:url";import{BASH_HISTFILE_SOURCE as $e,COMPACTING_SENTINEL as et,FISH_HISTFILE_SOURCE as tt,ZSH_HISTFILE_SOURCE as nt,createBuiltinThemeRegistry as rt,entriesToCommands as it,formatAgentDiagnosticsText as at,formatTranscriptText as ot,formatTurnTimeline as st,i18next as Q,isUsingOverage as ct,observationLiveFields as lt,observationRow as ut,parseBashHistory as dt,parseFishHistory as ft,parseZshHistory as pt,promptParentWorkspaceChoice as mt,promptWorkspaceTrust as ht,setMarkdownThemeUserOverrides as gt,subagentEntryStatus as _t}from"@x-otto/tui";import{access as vt,mkdir as yt,readFile as bt,readdir as xt,rename as St,stat as Ct,unlink as wt,writeFile as Tt}from"node:fs/promises";import{createModelUsabilityGate as Et}from"@x-otto/ai";import{SESSION_RESUME_WINDOW_MESSAGES as Dt,createProjectorState as Ot,projectSessionEvent as kt,resolveChoiceAnswer as At,resolveTextAnswer as jt,sandboxBypassCommand as Mt,shouldShowPulseSurvey as Nt}from"@x-otto/session-contract";import{ScheduleRegistry as Pt,SchedulerService as Ft,createLocalFireOwnership as It,createRemoteFireOwnership as Lt,createRemoteScheduleStore as Rt,createScheduleStore as zt,parseCron as Bt}from"@x-otto/schedule";function Vt(e=process.stdout){if(process.env.OTTO_TUI_SCOPED_VIEWPORT===`0`&&process.env.OTTO_TUI_CLEAR_ON_EXIT!==`0`&&e.isTTY)try{e.write(`\x1B[2J\x1B[3J\x1B[H`)}catch{}}async function Ht(e,t){let n=e;for(;n.type===`response`&&n.endReason===`max-tool-turns`&&n.notice;){if(!await t.askBudgetContinue()){t.onBudgetStopped();return}t.beforeContinuationTurn();let e=await t.runTurn(`Continue with the remaining work until the task is complete.`);if(t.onTurnResult(e)===`exit`)return;n=e}}function Ut(e,t){return e||t}function Wt(e){let t=[],n=0,r=``,i=()=>{r&&=(t.push(r),``)};for(;n<e.length;){let t=e[n];if(t===` `||t===` `){i(),n++;continue}if(t===`\\`){n++,n<e.length&&(r+=e[n]),n++;continue}if(t===`"`){n++;let t=Gt(e,n,`"`);r+=t.value,n=t.next;continue}if(t===`'`){n++;let t=Gt(e,n,`'`,!1);r+=t.value,n=t.next;continue}r+=t,n++}return i(),{tokens:t}}function Gt(e,t,n,r=!0){let i=``,a=t;for(;a<e.length;){let t=e[a];if(r&&t===`\\`){a++,a<e.length&&(i+=e[a]),a++;continue}if(t===n)return a++,{value:i,next:a};i+=t,a++}return{value:i,next:a}}function Kt(e){let t=e.trim();if(!t.startsWith(`/`)||t===`/`||t.startsWith(`//`))return{isCommand:!1,text:t};let{tokens:n}=Wt(t.slice(1));if(n.length===0)return{isCommand:!1,text:t};let[r,...i]=n;return{isCommand:!0,command:r,args:i}}function qt(e,t){return e===`pin`&&t?`unpin`:e}function Jt(e,t){return e===`pause`&&t?`continue`:e}function Yt(e,t,n){let r=e.list().sort((e,t)=>e.name.localeCompare(t.name)),i=r.map(e=>` /${qt(e.name,t)}${e.aliases?.length?` (${e.aliases.join(`, `)})`:``}`),a=Math.max(...i.map(e=>e.length)),o=[];for(let e=0;e<r.length;e++){let s=r[e],c=n[qt(s.name,t)]??n[s.name]??s.description;o.push(`${i[e].padEnd(a)} — ${c}`)}return o.push(``,`Prefixes: !<cmd> run shell | @<file> read file`),o}function Xt(e,t,n,r,i=!1,a=!1){return e.list().filter(e=>e.name===`pause`?t||a:!0).map(e=>{let o=Jt(qt(e.name,i),a);return{name:o,description:r?.[o]??r?.[e.name]??e.description,disabled:t&&!n.has(e.name)&&e.name!==`abort`,sortKey:e.name}})}function Zt(e){for(let t of ae)t.tuiHidden||t.envGate&&process.env[t.envGate]!==`1`||(e.has(t.name)&&e.unregister(t.name),e.register({name:t.name,description:t.description??t.name,aliases:t.aliases,type:`action`,source:`builtin`,execute:()=>``}))}var Qt=class{estimate;intervalMs;now;text=``;measuredTokens=0;measuredChars=0;measuredAt=-1/0;constructor(e){this.estimate=e.estimate,this.intervalMs=e.intervalMs??250,this.now=e.now??(()=>Date.now())}reset(){this.text=``,this.measuredTokens=0,this.measuredChars=0,this.measuredAt=-1/0}push(e){if(!e)return;this.text+=e;let t=this.now();t-this.measuredAt>=this.intervalMs&&this.measure(t)}flush(){this.measure(this.now())}tokens(){let e=this.text.length-this.measuredChars;if(e<=0)return this.measuredTokens;let t=this.measuredChars>0?this.measuredTokens/this.measuredChars:.25;return this.measuredTokens+Math.ceil(e*t)}measure(e){this.measuredTokens=this.text?this.estimate(this.text):0,this.measuredChars=this.text.length,this.measuredAt=e}};function $t(e,t){if(/^(bash|shell|run_command|execute|exec)$/i.test(e)){let e=t?.command;if(e)return e}return JSON.stringify(t??{}).slice(0,300)}async function en(e,t){let n=[`● ${t.header} — ${t.askedBy} asks:`,t.background?`\n${t.background}`:``,Q.t(`cmd.grillRecommendation`,{rec:t.recommendation}),t.evidence?.length?Q.t(`cmd.grillEvidence`,{joined:t.evidence.map(e=>` · ${e}`).join(`
|
|
3
3
|
`)}):``].join(``);e.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:n}]});let r=t.options??[];if(r.length>0){if(r.length<=2&&!t.multiSelect&&t.allowFreeform===!1){let n=await new Promise(n=>{e.modal.openModal({kind:`confirm`,title:t.question,message:r.map(e=>`${e.label}${e.recommended?` (recommended)`:``}: ${e.rationale}`).join(`
|
|
4
|
-
`),confirmLabel:r[0]?.label??Q.t(`cmd.grillOptionYes`),cancelLabel:r[1]?.label??Q.t(`cmd.grillOptionNo`),onConfirm:()=>n(!0),onCancel:()=>n(!1)})})?r[0]?.label:r[1]?.label;return At(t,n?[n]:[])}let n=await e.modal.openModal({kind:`questions`,title:t.question,questions:[{header:t.header,question:t.question,multiSelect:!!t.multiSelect,freeformInput:t.allowFreeform!==!1,freeformPlaceholder:Q.t(`cmd.grillFreeformPlaceholder`),options:r.map(e=>({label:e.recommended?`${e.label} ★`:e.label,description:e.rationale}))}]});return At(t,(n?.answers?.[t.header]??[]).map(e=>e.replace(/\s*★$/,``)),n?.freeformText)}return jt(t,await e.modal.openModal({kind:`input`,title:t.header,description:[t.question],placeholder:Q.t(`cmd.grillAnswerPlaceholder`)}))}function tn(e){let{getSession:t,app:n,tui:r,projState:i,redState:a,recomputeBudget:o,persistEditedFiles:s,persistSubagents:c,persistTurnCount:u,onContextCompacted:d,markStreamed:f}=e,p=null,m=!1,h=!1,g=null,_=null,y=e=>{let r=t(),i=r.session.getTurnCount();
|
|
5
|
-
`))r.startsWith(`+`)&&!r.startsWith(`+++`)?t++:r.startsWith(`-`)&&!r.startsWith(`---`)&&n++;return`+${t}/-${n}`},k=()=>{let e=H.listForSession(t().id).map(e=>({id:e.id,command:e.command,type:`process`,origin:`main`,status:e.status===`running`?`running`:e.status===`exited`?`exited`:`killed`,port:e.port,startedAt:e.startedAt,exitCode:e.exitCode,detectedService:e.detectedService})),n=new Map(V.list().map(e=>[e.id,e])),i=e=>{let t=n.get(e);return t?ut(t):{}},a=B.listForSession(t().id).map(e=>({id:e.id,command:e.title,type:`agent-session`,origin:e.origin,status:e.status===`running`||e.status===`ready`||e.status===`needs_input`?`running`:e.status===`applied`?`exited`:e.status===`failed`?`failed`:`killed`,agentStatus:e.status,diffStat:e.diff?oe(e.diff):void 0,startedAt:e.startedAt,...i(e.id)})),o=new Set(a.map(e=>e.id)),s=V.list().filter(e=>!o.has(e.id)).map(dt),c=[...e,...a,...s];r.stores.tasks.setBackgroundTasks([...c.filter(e=>e.origin===`user`),...c.filter(e=>e.origin!==`user`)])},A=null,j=()=>{A===null&&(A=setTimeout(()=>{A=null,k()},30))},se=()=>{A!==null&&(clearTimeout(A),A=null),k()},ce=[H.onSpawn(j),H.onExit(se),B.onSpawn(j),B.onUpdate(j),B.onExit(se),B.onRemove(se),V.subscribe(j)];k();let M;return{bgUnsubs:ce,attachSessionHandler:()=>{M?.(),m=!1,M=t().subscribe(e=>{for(let o of kt(e,i,ee)){if(o.kind===`prompt.end`){let e=l(o,a),n={turn:i.currentTurn,completedAt:Date.now(),...e},r=t().session.getTurnSummaries()??[];t().session.setTurnSummaries([...r.filter(e=>e.turn!==n.turn),n])}v(o,{pushMessage:r.messages.pushMessage,echoUserInput:r.messages.echoUserInput,pushEngineEvent:r.engine.pushEngineEvent,getNotifyStats:r.info.getNotifyStats,setTasks:(e,t)=>r.stores.tasks.setTasks(e,t),addTurnBoundary:e=>r.stores.tasks.addTurnBoundary(e)},a),o.kind===`tasks.update`&&(t().session.setTodoList(i.todoList),n.sessionManager.save(t().id).catch(()=>{}))}if(e.type===`stream.event`&&e.event?.type===`text_delta`){f();let t=e.event?.delta??``;T+=t.length,O.push(t),r.engine.pushEngineEvent({kind:`outputTokensThisTurn`,n:Math.floor(T/4)}),re()}if(e.type===`stream.event`&&e.event?.type===`done`){let i=e.event?.providerUsage;if(i!==void 0){let e=i!==null&<(i.status,i.overageStatus);if(i===null||i.status===`rejected`&&!e)r.stores.notification.setProviderUsage(null),p=null;else{let e=t().model.provider;n.authStore.getAuthSource(e).then(n=>{if(t().model.provider!==e)return;let a=n===`oauth`?i:null;r.stores.notification.setProviderUsage(a),p=a}).catch(()=>{})}}}switch(e.type){case`turn.start`:T=0,O.reset(),re(),r.engine.pushEngineEvent({kind:`spinnerMode`,mode:`requesting`});break;case`turn.end`:ne(),o();break;case`streaming.start`:r.engine.pushEngineEvent({kind:`spinnerMode`,mode:`responding`}),r.pending.clearPendingEcho();break;case`streaming.end`:r.engine.pushEngineEvent({kind:`spinnerMode`,mode:null}),r.pending.clearPendingEcho();break;case`prompt.start`:ne(),E=te(e.text),re(),r.info.setTopView({session:t().id}),r.panes.clearEditedFiles(),r.plugins.clearSubagents(),ie=a.messageIndex,r.info.addContextTurn({turnIndex:i.currentTurn,role:`assistant`,messageCount:0,estimatedTokens:0,compacted:!1,truncated:!1,pruned:!1});break;case`compaction.start`:C=e.messageCount,r.engine.pushEngineEvent({kind:`activeTool`,name:tt});break;case`compaction.end`:{let t=C??e.retainedCount,n=e.retainedCount;r.engine.pushEngineEvent({kind:`activeTool`,name:null}),n<t&&(r.messages.pushMessage({role:`compact_boundary`,before:t,after:n}),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`compact`,before:t,after:n,summary:e.summary}),d()),C=void 0,o(void 0,{before:t,after:n});break}case`compaction.reactive.notice`:{let{messagesBefore:t,messagesAfter:n}=e;n<t&&(r.messages.pushMessage({role:`compact_boundary`,before:t,after:n}),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`compact`,before:t,after:n,summary:e.summary}),d()),o(void 0,{before:t,after:n});break}case`image.degradation.notice`:e.degradedCount>0&&r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.imageDegradationNotice`,{count:e.degradedCount,context:e.trigger===`image-constraint`?`image-constraint`:`other`}));break;case`session.history-capped`:r.messages.pushMessage({role:`history_capped`,removedCount:e.removedCount,trigger:e.trigger,...e.lossy?{lossy:!0}:{}}),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`history_capped`,removedCount:e.removedCount});break;case`session.write-lease-denied`:m=!0,r.messages.pushMessage({role:`write_lease_denied`}),r.info.showToast(Q.t(`lease.deniedToastTitle`),Q.t(`lease.deniedToastBody`));break;case`session.write-lease-restored`:m=!1,r.messages.pushMessage({role:`write_lease_restored`}),r.info.showToast(Q.t(`lease.restoredToastTitle`),Q.t(`lease.restoredToastBody`));break;case`session.crash-gap-detected`:r.info.showToast(Q.t(`crashGap.toastTitle`),Q.t(`crashGap.toastBody`,{lostTurns:e.lostTurns}));break;case`run.pause_requested`:h=!0,g={at:Date.now(),toolCount:0},y(`requested`),r.engine.setPauseDialog?.({phase:`requested`,requestedAt:Date.now(),toolCount:0,onCancel:()=>{},onDismiss:()=>{r.engine.setPauseDialog?.(null)}}),_&&clearInterval(_),_=setInterval(()=>{if(!g){clearInterval(_),_=null;return}let e=Math.floor((Date.now()-g.at)/1e3);r.stores.notification.setPausePending({elapsedSec:e,toolCount:g.toolCount})},1e3);break;case`tool.call.end`:{let t=typeof e.resultTokensEstimate==`number`?e.resultTokensEstimate:e.resultText?te(e.resultText):0;t>0&&(D+=t,re()),g&&(g.toolCount++,r.engine.setPauseDialog?.({phase:`requested`,requestedAt:g.at,toolCount:g.toolCount,onCancel:()=>{},onDismiss:()=>{r.engine.setPauseDialog?.(null)}})),(async()=>{try{let t={role:`tool_result`,name:e.toolCall.name,toolCallId:e.toolCall.id,content:[{type:`text`,text:e.resultText??``}],details:e.details},i=await n.resolveA2uiRendererPayload(t);i&&i.length>0&&r.messages.pushMessage({role:`assistant`,content:[{type:`a2ui`,components:i}]})}catch{}})();break}case`run.paused`:y(`paused`),g?(r.engine.setPauseDialog?.({phase:`active`,requestedAt:g.at,toolCount:g.toolCount,totalToolCount:g.toolCount}),r.messages.pushMessage({role:`run_paused`,toolCount:g.toolCount}),b(`run_paused`),_&&=(clearInterval(_),null),r.stores.notification.setPausePending(null),g=null):(r.messages.pushMessage({role:`run_paused`}),b(`run_paused`)),r.stores.notification.setPaused(!0);break;case`run.pause_cancelled`:y(`cancelled`),r.engine.setPauseDialog?.(null),r.messages.pushMessage({role:`run.pause_cancelled`}),b(`run_pause_cancelled`),_&&=(clearInterval(_),null),r.stores.notification.setPausePending(null),g=null,h=!1;break;case`run.resumed`:y(`resumed`),r.engine.setPauseDialog?.(null),r.messages.pushMessage({role:`run_resumed`}),b(`run_resumed`),_&&=(clearInterval(_),null),r.stores.notification.setPausePending(null),g=null,h=!1,r.stores.notification.setPaused(!1);break;case`steer.consumed`:r.pending.commitPendingSteer(e.id);break;case`image.vision-delegate`:!x&&e.describedCount>0&&(x=!0,r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`model.visionDelegateToast`,{count:e.describedCount})));break;case`memory.pruned`:w||(w=!0,r.messages.pushMessage({role:`prune_boundary`})),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`prune`,tokensSaved:e.tokensSaved,prunedCount:e.prunedCount}),o();break;case`error`:s(),c(),r.pending.withdrawPendingEcho();break;case`prompt.continued`:r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.todoGateContinuing`,{round:e.round,cap:e.maxRounds,left:e.incompleteCount}));break;case`prompt.budget.notice`:e.steered&&r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.promptBudgetExceeded`,{context:e.dimension,used:e.used,budget:e.budget}));break;case`budget.notice`:e.extended?r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.budgetExtended`,{maxTurns:e.maxTurns})):e.steered&&r.info.showToast(Q.t(`cmd.titleInfo`),e.progressDenied?Q.t(`cmd.budgetProgressDenied`):Q.t(`cmd.budgetSteered`,{maxTurns:e.maxTurns}));break;case`progress.stall.notice`:r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.progressStallDetected`,{maxRepeat:e.maxRepeat}));break;case`tool.call.mismatch.notice`:e.outcome===`retry`?r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.toolCallMismatchRetry`,{retryCount:e.retryCount})):r.info.showToast(Q.t(`cmd.titleError`),Q.t(`cmd.toolCallMismatchTerminated`));break;case`session.cost-budget-exceeded`:r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.sessionCostBudgetExceeded`,{used:e.totalCostUSD.toFixed(2),budget:e.budgetUSD.toFixed(2)}));break;case`prompt.end`:ne(),r.pending.clearPendingSteers(),o(),r.info.markContextTurns({turnIndex:i.currentTurn,messageCount:Math.max(0,a.messageIndex-ie)}),s(),c(),u();{let e=t(),n=Ie(e.session.metadata().title,e.session.messages(),e.id);r.stores.tasks.setSessionTitle(n),r.lifecycle.setTerminalTitle(n)}if(process.env.OTTO_TUI_DEBUG_NOTIFY_STATS){let e=r.info.getNotifyStats();if(e.coalescedCalls>0){let t=(e.coalescedCalls/Math.max(1,e.coalescedFires)).toFixed(1);console.error(`\x1b[90m\x1b[2m[perf] notify merge ${e.coalescedCalls}→${e.coalescedFires} (${t}x) direct ${e.immediateCalls} flush ${e.flushFires}\x1b[0m`)}}{let e=n.settings.get(`pulse_survey`);n.feedbackRegistry.get()!==void 0&&Nt(i.currentTurn,{enabled:e?.enabled??!0,probability:e?.probability??.05,minTurnGap:e?.min_turn_gap??20,forcedUpgradeActive:r.info.isForcedUpgradeActive()},ae)&&(ae.lastShownTurn=i.currentTurn,r.stores.notification.setPulseSurvey({phase:`rating`,rating:null,selectedIndex:0,commentText:``,commentOffset:0,onSubmit:(e,r)=>{n.feedbackRegistry.get()?.recordPulseSurvey?.({ts:Date.now(),rating:e,comment:r,sdkVersion:Je,modelId:t().model?.id})},onClose:()=>r.stores.notification.setPulseSurvey(null)}))}break;case`ask.user.required`:{let i=e.question,a=e.requestId;(async()=>{let o=n.inquiryCenter;if(!o.enqueue({id:a,origin:{kind:`session`,sessionId:e.sessionId},question:i}).accepted){t().resolveAskUser(a,{answer:``,acceptedRecommendation:!1,resolvedBy:`human`});return}if(!await o.waitForTurn(a)){t().resolveAskUser(a,{answer:``,acceptedRecommendation:!1,resolvedBy:`human`});return}try{let e=await en(r,i);t().resolveAskUser(a,e)}finally{o.release(a)}})();break}case`approval.required`:{let i=e.toolName===`bash`&&typeof e.arguments?.command==`string`?e.arguments.command:``,a=i?n.bashAlwaysAllowPrefix(i):null;r.modal.requestPermission({tool:e.toolName,input:$t(e.toolName,e.arguments),risk:e.risk??`medium`,description:e.description,alwaysAllowLabel:a??void 0}).then(r=>{let i=Mt(e.description,e.arguments,De);r.approved&&i&&n.approveSandboxBypass(i),t().resolveApproval(e.id,r.approved),r.approved&&r.mode===`always`&&(e.toolName===`bash`?a&&n.allowToolAlways(`bash(${a})`,t().id):n.allowToolAlways(e.toolName,t().id))});break}}})},getSessionUnsub:()=>M,getLastProviderUsage:()=>p,isWriteLeaseReadOnly:()=>m,isRunPaused:()=>h}}function nn(e){let t=new Map;if(e?.role===`assistant`&&Array.isArray(e.content))for(let n of e.content)n.type===`tool_call`&&t.set(n.id,n);return t}async function rn(e,t,r){let i,a=new Set,o=new Map,s=new Set,c=new Map;if(r){let n=await e.loadTailEntries(t,Dt);i=n.length>0?n[0].seq:0;for(let e of n)e.type===`message`&&a.add(e.seq)}else i=await e.getEntryCount(t);return{async loadEarlier(r=500){if(i<=0)return null;let l=await e.loadEntriesBefore(t,i,r);if(l.length===0)return null;let u=new Map,d=new Set;for(let e of l){if(e.type!==`message`)continue;let t=e.data;if(t?.role===`assistant`)for(let[e,n]of nn(t))u.set(e,n);else t?.role===`tool_result`&&typeof t.toolCallId==`string`&&d.add(t.toolCallId)}let f=[],p=(e,t)=>({...e,id:`hist-${t}`,seq:t});for(let e of l){if(e.type===`clear`){i=0,f.length=0;continue}if(e.type!==`message`||a.has(e.seq))continue;let t=e.data;if(!t||typeof t.role!=`string`||t.internal)continue;if(t.role===`tool_result`){let r=o.get(t.toolCallId??``)??u.get(t.toolCallId??``);if(r){let i=r.arguments??{};f.push(p({role:`tool`,name:t.toolName||r.name||`tool`,args:n(i),argsObj:i,result:S(t.content),isError:t.isError},e.seq)),s.add(t.toolCallId)}else c.set(t.toolCallId,{toolName:t.toolName,content:t.content,isError:t.isError});continue}if(t.role===`assistant`){let r=nn(t);if(r.size>0){let i=new Set([...d,...s,...c.keys()]),a=_e([t],{resolvedIds:i});for(let t of a)f.push(p(t,e.seq));for(let[t,i]of r){if(d.has(t))continue;let r=c.get(t);if(r){c.delete(t);let a=i.arguments??{};f.push(p({role:`tool`,name:i.name,args:n(a),argsObj:a,result:S(r.content),isError:r.isError??!1},e.seq))}}continue}}let r=_e([t]);for(let t of r)f.push(p(t,e.seq))}for(let[e,t]of u)o.set(e,t);return i>0&&(i=l[0].seq),f.length>0?f:null}}}const an=[`approaching`,`nearing`,`critical`],on={maxReminders:{approaching:1,nearing:3,critical:1},backoffBaseTurns:4,resetMarginPct:10,approachingMarginPct:10};function $(){return{count:0,lastRemindedTurn:void 0,peakPct:0,active:!1}}function sn(e,t,n,r){return e>=n?`critical`:e>=t?`nearing`:e>=t-r?`approaching`:null}function cn(e,t,n,r){return e===`critical`?n:e===`nearing`?t:t-r}function ln(e,t){return t<=1?0:e.backoffBaseTurns*2**(t-2)}var un=class{config;zones;suppressed=!1;constructor(e={}){this.config={...on,...e},this.zones={approaching:$(),nearing:$(),critical:$()}}check(e){if(this.suppressed)return null;let{contextPercent:t,pruneLinePct:n,compactLinePct:r,currentTurn:i}=e,a=sn(t,n,r,this.config.approachingMarginPct);for(let e of an)e!==a&&this.zones[e].active&&t<cn(e,n,r,this.config.approachingMarginPct)-this.config.resetMarginPct&&(this.zones[e]=$());if(a===null)return null;let o=this.zones[a];o.lastRemindedTurn!==void 0&&i<o.lastRemindedTurn&&(this.zones[a]=$());let s=this.zones[a];s.active=!0,s.peakPct=Math.max(s.peakPct,t);let c=this.config.maxReminders[a];if(s.count>=c)return null;let l=s.count+1;if(s.lastRemindedTurn!==void 0){let e=ln(this.config,l);if(i-s.lastRemindedTurn<e)return null}return s.count=l,s.lastRemindedTurn=i,{zone:a,pct:Math.round(t)}}onCompacted(){this.zones={approaching:$(),nearing:$(),critical:$()}}suppress(){this.suppressed=!0}snapshot(){return{approaching:{count:this.zones.approaching.count,lastTurn:this.zones.approaching.lastRemindedTurn},nearing:{count:this.zones.nearing.count,lastTurn:this.zones.nearing.lastRemindedTurn},critical:{count:this.zones.critical.count,lastTurn:this.zones.critical.lastRemindedTurn}}}};function dn(e){let{getSession:t,app:n,tui:r,projState:i,contextWindow:a,currentModelId:o}=e,s,c=new un,l={approaching:e=>Q.t(`cmd.contextPressureApproaching`,{pct:e}),nearing:e=>Q.t(`cmd.contextPressureNearing`,{pct:e}),critical:e=>Q.t(`cmd.contextPressureCritical`,{pct:e})},d=()=>{let e=t(),n=e.session.messages(),r=0,i=0,a=0,o=0,s=!1,c=0,l=0;for(let e=n.length-1;e>=0;e--){let t=n[e]?.usage;t&&(s||=(r=t.inputTokens??0,i=t.outputTokens??0,a=t.cacheReadTokens??0,o=t.cacheWriteTokens??0,!0),n[e]?.role===`assistant`&&(c+=t.inputTokens??0,l+=t.outputTokens??0))}return{sessionId:e.session.id,lastIn:r,lastOut:i,lastCacheRead:a,lastCacheWrite:o,totIn:c,totOut:l,messageCount:n.length}},f=(e,f)=>{let p=e!==void 0,m=p&&s&&s.sessionId===t().session.id?s:d();s=m;let h=f?f.before:1,g=f?f.after/h:1,_=e=>g<1?Math.round(e*g):e,v=n.modelRegistry.find(o.value??``)?.cost,y=v?m.totIn*(v.input??0)+m.totOut*(v.output??0):0,b=u({systemPrompt:t().systemPrompt,tools:t().tools,lastIn:_(m.lastIn),lastOut:_(m.lastOut),lastCacheRead:_(m.lastCacheRead),lastCacheWrite:_(m.lastCacheWrite),contextWindow:a.value,modelName:t().model?.name??``,totIn:m.totIn,totOut:m.totOut,cost:y>0?y:void 0,messageCount:m.messageCount,streamingOutputTokens:e});if(r.stores.budget.setBudget(b),r.stores.context.setBudget(b),!p&&b.contextWindow>0){let e=b.pruneLine/b.contextWindow*100,t=b.compactLine/b.contextWindow*100,n=c.check({contextPercent:b.contextPercent,pruneLinePct:e,compactLinePct:t,currentTurn:i.currentTurn});n&&r.info.pushNotification(Q.t(`cmd.titleContextPressure`),l[n.zone](n.pct),`system`,n.zone===`critical`?`warning`:`info`)}},p=()=>{try{t().session.setEditedFiles(r.messages.getEditedFiles().map(e=>({path:e.path,operation:e.operation,addedLines:e.addedLines,removedLines:e.removedLines,timestamp:e.timestamp,toolCallId:e.toolCallId}))),n.sessionManager.save(t().id).catch(()=>{})}catch(e){console.error(`\x1b[90m\x1b[2m[persist] editedFiles skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}};return{recomputeBudget:f,persistEditedFiles:p,persistSubagents:()=>{try{let e=[...r.plugins.getSubagents().values()].map(e=>({id:e.id,name:e.command||e.id,status:vt(e),startedAt:e.startedAt}));t().session.setSubagents(e),n.sessionManager.save(t().id).catch(()=>{})}catch(e){console.error(`\x1b[90m\x1b[2m[persist] subagents skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}},persistTurnCount:()=>{try{t().session.setTurnCount(i.currentTurn)}catch(e){console.error(`\x1b[90m\x1b[2m[persist] turnCount skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}},editFileCallback:e=>{try{r.stores.tasks.addEditedFile({path:e.path,operation:e.operation,oldContent:e.oldContent,newContent:e.newContent,addedLines:e.addedLines,removedLines:e.removedLines,timestamp:e.timestamp,toolCallId:e.toolCallId})}catch(e){console.error(`\x1b[90m\x1b[2m[panel] addEditedFile skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}p()},onContextCompacted:()=>{c.onCompacted()}}}function fn(e){let{app:t,getTui:n}=e,r=[],i=()=>{for(let e of r)e();r=[]},a,o,s,c,l,u=()=>{a&&=(clearInterval(a),void 0),o&&=(B.retain(o,!1),void 0),l=void 0},d=()=>{s&&=(clearInterval(s),void 0),c&&=(V?.unpin(c),B.get(c)&&B.retain(c,!1),void 0)};return{clearBgSubs:i,stopBgOutputPoll:u,stopBgSubagentPoll:d,setBgUnsubs:e=>{r=e},handlers:{onBackgroundKill:e=>{if(B.get(e)){B.cancel(e);return}V.abort(e)||H.kill(e)},onBackgroundApply:e=>{let r=n(),i=e=>r.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:e}]}),a=t.agentJobs.apply(e);if(a.applied){let n=a.forbiddenZone?.length?Q.t(`cmd.bgForbiddenZone`,{count:a.forbiddenZone.length,files:a.forbiddenZone.join(`
|
|
4
|
+
`),confirmLabel:r[0]?.label??Q.t(`cmd.grillOptionYes`),cancelLabel:r[1]?.label??Q.t(`cmd.grillOptionNo`),onConfirm:()=>n(!0),onCancel:()=>n(!1)})})?r[0]?.label:r[1]?.label;return At(t,n?[n]:[])}let n=await e.modal.openModal({kind:`questions`,title:t.question,questions:[{header:t.header,question:t.question,multiSelect:!!t.multiSelect,freeformInput:t.allowFreeform!==!1,freeformPlaceholder:Q.t(`cmd.grillFreeformPlaceholder`),options:r.map(e=>({label:e.recommended?`${e.label} ★`:e.label,description:e.rationale}))}]});return At(t,(n?.answers?.[t.header]??[]).map(e=>e.replace(/\s*★$/,``)),n?.freeformText)}return jt(t,await e.modal.openModal({kind:`input`,title:t.header,description:[t.question],placeholder:Q.t(`cmd.grillAnswerPlaceholder`)}))}function tn(e){let{getSession:t,app:n,tui:r,projState:i,redState:a,recomputeBudget:o,persistEditedFiles:s,persistSubagents:c,persistTurnCount:u,onContextCompacted:d,markStreamed:f}=e,p=null,m=!1,h=!1,g=null,_=null,y=e=>{let r=t(),i=r.session.getTurnCount();I({traceStore:n.storage.traceStore,sessionId:r.id,...i===void 0?{}:{turn:i}},e,`session-event`)},b=e=>{t().session.append({role:`system`,subtype:e,content:e,level:`info`,timestamp:Date.now()})},x=!1,S,ee={currentModel:()=>t().model.id,cacheHitRatio:()=>t().getLastCacheHitRatio(),turnTokens:()=>{let e=t().session.messages(),n=0;for(let t of e)t.role===`assistant`&&t.usage&&(n+=(t.usage.inputTokens??0)+(t.usage.outputTokens??0)+(t.usage.cacheReadTokens??0)+(t.usage.cacheWriteTokens??0));let r=S;if(S=n,!(r==null||n<=r))return n-r}},C,w=!1,T=0,E=0,D=0,O=new Qt({estimate:te}),k=()=>{E=0,D=0,T=0,O.reset()},ne=()=>{o(E+D+O.tokens())},re=0,ie={},ae=e=>{let t=0,n=0;for(let r of e.split(`
|
|
5
|
+
`))r.startsWith(`+`)&&!r.startsWith(`+++`)?t++:r.startsWith(`-`)&&!r.startsWith(`---`)&&n++;return`+${t}/-${n}`},A=()=>{let e=U.listForSession(t().id).map(e=>({id:e.id,command:e.command,type:`process`,origin:`main`,status:e.status===`running`?`running`:e.status===`exited`?`exited`:`killed`,port:e.port,startedAt:e.startedAt,exitCode:e.exitCode,detectedService:e.detectedService})),n=new Map(H.list().map(e=>[e.id,e])),i=e=>{let t=n.get(e);return t?lt(t):{}},a=V.listForSession(t().id).map(e=>({id:e.id,command:e.title,type:`agent-session`,origin:e.origin,status:e.status===`running`||e.status===`ready`||e.status===`needs_input`?`running`:e.status===`applied`?`exited`:e.status===`failed`?`failed`:`killed`,agentStatus:e.status,diffStat:e.diff?ae(e.diff):void 0,startedAt:e.startedAt,...i(e.id)})),o=new Set(a.map(e=>e.id)),s=H.list().filter(e=>!o.has(e.id)).map(ut),c=[...e,...a,...s];r.stores.tasks.setBackgroundTasks([...c.filter(e=>e.origin===`user`),...c.filter(e=>e.origin!==`user`)])},j=null,M=()=>{j===null&&(j=setTimeout(()=>{j=null,A()},30))},oe=()=>{j!==null&&(clearTimeout(j),j=null),A()},se=[U.onSpawn(M),U.onExit(oe),V.onSpawn(M),V.onUpdate(M),V.onExit(oe),V.onRemove(oe),H.subscribe(M)];A();let N;return{bgUnsubs:se,attachSessionHandler:()=>{N?.(),m=!1,N=t().subscribe(e=>{for(let o of kt(e,i,ee)){if(o.kind===`prompt.end`){let e=l(o,a),n={turn:i.currentTurn,completedAt:Date.now(),...e},r=t().session.getTurnSummaries()??[];t().session.setTurnSummaries([...r.filter(e=>e.turn!==n.turn),n])}v(o,{pushMessage:r.messages.pushMessage,echoUserInput:r.messages.echoUserInput,pushEngineEvent:r.engine.pushEngineEvent,getNotifyStats:r.info.getNotifyStats,setTasks:(e,t)=>r.stores.tasks.setTasks(e,t),addTurnBoundary:e=>r.stores.tasks.addTurnBoundary(e)},a),o.kind===`tasks.update`&&(t().session.setTodoList(i.todoList),n.sessionManager.save(t().id).catch(()=>{}))}if(e.type===`stream.event`&&e.event?.type===`text_delta`){f();let t=e.event?.delta??``;T+=t.length,O.push(t),r.engine.pushEngineEvent({kind:`outputTokensThisTurn`,n:Math.floor(T/4)}),ne()}if(e.type===`stream.event`&&e.event?.type===`done`){let i=e.event?.providerUsage;if(i!==void 0){let e=i!==null&&ct(i.status,i.overageStatus);if(i===null||i.status===`rejected`&&!e)r.stores.notification.setProviderUsage(null),p=null;else{let e=t().model.provider;n.authStore.getAuthSource(e).then(n=>{if(t().model.provider!==e)return;let a=n===`oauth`?i:null;r.stores.notification.setProviderUsage(a),p=a}).catch(()=>{})}}}switch(e.type){case`turn.start`:T=0,O.reset(),ne(),r.engine.pushEngineEvent({kind:`spinnerMode`,mode:`requesting`});break;case`turn.end`:k(),o();break;case`streaming.start`:r.engine.pushEngineEvent({kind:`spinnerMode`,mode:`responding`}),r.pending.clearPendingEcho();break;case`streaming.end`:r.engine.pushEngineEvent({kind:`spinnerMode`,mode:null}),r.pending.clearPendingEcho();break;case`prompt.start`:k(),E=te(e.text),ne(),r.info.setTopView({session:t().id}),r.panes.clearEditedFiles(),r.plugins.clearSubagents(),re=a.messageIndex,r.info.addContextTurn({turnIndex:i.currentTurn,role:`assistant`,messageCount:0,estimatedTokens:0,compacted:!1,truncated:!1,pruned:!1});break;case`compaction.start`:C=e.messageCount,r.engine.pushEngineEvent({kind:`activeTool`,name:et});break;case`compaction.end`:{let t=C??e.retainedCount,n=e.retainedCount;r.engine.pushEngineEvent({kind:`activeTool`,name:null}),n<t&&(r.messages.pushMessage({role:`compact_boundary`,before:t,after:n}),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`compact`,before:t,after:n,summary:e.summary}),d()),C=void 0,o(void 0,{before:t,after:n});break}case`compaction.reactive.notice`:{let{messagesBefore:t,messagesAfter:n}=e;n<t&&(r.messages.pushMessage({role:`compact_boundary`,before:t,after:n}),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`compact`,before:t,after:n,summary:e.summary}),d()),o(void 0,{before:t,after:n});break}case`image.degradation.notice`:e.degradedCount>0&&r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.imageDegradationNotice`,{count:e.degradedCount,context:e.trigger===`image-constraint`?`image-constraint`:`other`}));break;case`session.history-capped`:r.messages.pushMessage({role:`history_capped`,removedCount:e.removedCount,trigger:e.trigger,...e.lossy?{lossy:!0}:{}}),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`history_capped`,removedCount:e.removedCount});break;case`session.write-lease-denied`:m=!0,r.messages.pushMessage({role:`write_lease_denied`}),r.info.showToast(Q.t(`lease.deniedToastTitle`),Q.t(`lease.deniedToastBody`));break;case`session.write-lease-restored`:m=!1,r.messages.pushMessage({role:`write_lease_restored`}),r.info.showToast(Q.t(`lease.restoredToastTitle`),Q.t(`lease.restoredToastBody`));break;case`session.crash-gap-detected`:r.info.showToast(Q.t(`crashGap.toastTitle`),Q.t(`crashGap.toastBody`,{lostTurns:e.lostTurns}));break;case`run.pause_requested`:h=!0,g={at:Date.now(),toolCount:0},y(`requested`),r.engine.setPauseDialog?.({phase:`requested`,requestedAt:Date.now(),toolCount:0,onCancel:()=>{},onDismiss:()=>{r.engine.setPauseDialog?.(null)}}),_&&clearInterval(_),_=setInterval(()=>{if(!g){clearInterval(_),_=null;return}let e=Math.floor((Date.now()-g.at)/1e3);r.stores.notification.setPausePending({elapsedSec:e,toolCount:g.toolCount})},1e3);break;case`tool.call.end`:{let t=typeof e.resultTokensEstimate==`number`?e.resultTokensEstimate:e.resultText?te(e.resultText):0;t>0&&(D+=t,ne()),g&&(g.toolCount++,r.engine.setPauseDialog?.({phase:`requested`,requestedAt:g.at,toolCount:g.toolCount,onCancel:()=>{},onDismiss:()=>{r.engine.setPauseDialog?.(null)}})),(async()=>{try{let t={role:`tool_result`,name:e.toolCall.name,toolCallId:e.toolCall.id,content:[{type:`text`,text:e.resultText??``}],details:e.details},i=await n.resolveA2uiRendererPayload(t);i&&i.length>0&&r.messages.pushMessage({role:`assistant`,content:[{type:`a2ui`,components:i}]})}catch{}})();break}case`run.paused`:y(`paused`),g?(r.engine.setPauseDialog?.({phase:`active`,requestedAt:g.at,toolCount:g.toolCount,totalToolCount:g.toolCount}),r.messages.pushMessage({role:`run_paused`,toolCount:g.toolCount}),b(`run_paused`),_&&=(clearInterval(_),null),r.stores.notification.setPausePending(null),g=null):(r.messages.pushMessage({role:`run_paused`}),b(`run_paused`)),r.stores.notification.setPaused(!0);break;case`run.pause_cancelled`:y(`cancelled`),r.engine.setPauseDialog?.(null),r.messages.pushMessage({role:`run.pause_cancelled`}),b(`run_pause_cancelled`),_&&=(clearInterval(_),null),r.stores.notification.setPausePending(null),g=null,h=!1;break;case`run.resumed`:y(`resumed`),r.engine.setPauseDialog?.(null),r.messages.pushMessage({role:`run_resumed`}),b(`run_resumed`),_&&=(clearInterval(_),null),r.stores.notification.setPausePending(null),g=null,h=!1,r.stores.notification.setPaused(!1);break;case`steer.consumed`:r.pending.commitPendingSteer(e.id);break;case`image.vision-delegate`:!x&&e.describedCount>0&&(x=!0,r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`model.visionDelegateToast`,{count:e.describedCount})));break;case`memory.pruned`:w||(w=!0,r.messages.pushMessage({role:`prune_boundary`})),r.engine.pushEngineEvent({kind:`compactionLog`,entryKind:`prune`,tokensSaved:e.tokensSaved,prunedCount:e.prunedCount}),o();break;case`error`:s(),c(),r.pending.withdrawPendingEcho();break;case`prompt.continued`:r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.todoGateContinuing`,{round:e.round,cap:e.maxRounds,left:e.incompleteCount}));break;case`prompt.budget.notice`:e.steered&&r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.promptBudgetExceeded`,{context:e.dimension,used:e.used,budget:e.budget}));break;case`budget.notice`:e.extended?r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.budgetExtended`,{maxTurns:e.maxTurns})):e.steered&&r.info.showToast(Q.t(`cmd.titleInfo`),e.progressDenied?Q.t(`cmd.budgetProgressDenied`):Q.t(`cmd.budgetSteered`,{maxTurns:e.maxTurns}));break;case`progress.stall.notice`:r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.progressStallDetected`,{maxRepeat:e.maxRepeat}));break;case`tool.call.mismatch.notice`:e.outcome===`retry`?r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.toolCallMismatchRetry`,{retryCount:e.retryCount})):r.info.showToast(Q.t(`cmd.titleError`),Q.t(`cmd.toolCallMismatchTerminated`));break;case`session.cost-budget-exceeded`:r.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.sessionCostBudgetExceeded`,{used:e.totalCostUSD.toFixed(2),budget:e.budgetUSD.toFixed(2)}));break;case`prompt.end`:k(),r.pending.clearPendingSteers(),o(),r.info.markContextTurns({turnIndex:i.currentTurn,messageCount:Math.max(0,a.messageIndex-re)}),s(),c(),u();{let e=t(),n=W(e.session.metadata().title,e.session.messages(),e.id);r.stores.tasks.setSessionTitle(n),r.lifecycle.setTerminalTitle(n)}if(process.env.OTTO_TUI_DEBUG_NOTIFY_STATS){let e=r.info.getNotifyStats();if(e.coalescedCalls>0){let t=(e.coalescedCalls/Math.max(1,e.coalescedFires)).toFixed(1);console.error(`\x1b[90m\x1b[2m[perf] notify merge ${e.coalescedCalls}→${e.coalescedFires} (${t}x) direct ${e.immediateCalls} flush ${e.flushFires}\x1b[0m`)}}{let e=n.settings.get(`pulse_survey`);n.feedbackRegistry.get()!==void 0&&Nt(i.currentTurn,{enabled:e?.enabled??!0,probability:e?.probability??.05,minTurnGap:e?.min_turn_gap??20,forcedUpgradeActive:r.info.isForcedUpgradeActive()},ie)&&(ie.lastShownTurn=i.currentTurn,r.stores.notification.setPulseSurvey({phase:`rating`,rating:null,selectedIndex:0,commentText:``,commentOffset:0,onSubmit:(e,r)=>{n.feedbackRegistry.get()?.recordPulseSurvey?.({ts:Date.now(),rating:e,comment:r,sdkVersion:Ke,modelId:t().model?.id})},onClose:()=>r.stores.notification.setPulseSurvey(null)}))}break;case`ask.user.required`:{let i=e.question,a=e.requestId;(async()=>{let o=n.inquiryCenter;if(!o.enqueue({id:a,origin:{kind:`session`,sessionId:e.sessionId},question:i}).accepted){t().resolveAskUser(a,{answer:``,acceptedRecommendation:!1,resolvedBy:`human`});return}if(!await o.waitForTurn(a)){t().resolveAskUser(a,{answer:``,acceptedRecommendation:!1,resolvedBy:`human`});return}try{let e=await en(r,i);t().resolveAskUser(a,e)}finally{o.release(a)}})();break}case`approval.required`:{let i=e.toolName===`bash`&&typeof e.arguments?.command==`string`?e.arguments.command:``,a=i?n.bashAlwaysAllowPrefix(i):null;r.modal.requestPermission({tool:e.toolName,input:$t(e.toolName,e.arguments),risk:e.risk??`medium`,description:e.description,alwaysAllowLabel:a??void 0}).then(r=>{let i=Mt(e.description,e.arguments,Ee);r.approved&&i&&n.approveSandboxBypass(i),t().resolveApproval(e.id,r.approved),r.approved&&r.mode===`always`&&(e.toolName===`bash`?a&&n.allowToolAlways(`bash(${a})`,t().id):n.allowToolAlways(e.toolName,t().id))});break}}})},getSessionUnsub:()=>N,getLastProviderUsage:()=>p,isWriteLeaseReadOnly:()=>m,isRunPaused:()=>h}}function nn(e){let t=new Map;if(e?.role===`assistant`&&Array.isArray(e.content))for(let n of e.content)n.type===`tool_call`&&t.set(n.id,n);return t}async function rn(e,t,r){let i,a=new Set,o=new Map,s=new Set,c=new Map;if(r){let n=await e.loadTailEntries(t,Dt);i=n.length>0?n[0].seq:0;for(let e of n)e.type===`message`&&a.add(e.seq)}else i=await e.getEntryCount(t);return{async loadEarlier(r=500){if(i<=0)return null;let l=await e.loadEntriesBefore(t,i,r);if(l.length===0)return null;let u=new Map,d=new Set;for(let e of l){if(e.type!==`message`)continue;let t=e.data;if(t?.role===`assistant`)for(let[e,n]of nn(t))u.set(e,n);else t?.role===`tool_result`&&typeof t.toolCallId==`string`&&d.add(t.toolCallId)}let f=[],p=(e,t)=>({...e,id:`hist-${t}`,seq:t});for(let e of l){if(e.type===`clear`){i=0,f.length=0;continue}if(e.type!==`message`||a.has(e.seq))continue;let t=e.data;if(!t||typeof t.role!=`string`||t.internal)continue;if(t.role===`tool_result`){let r=o.get(t.toolCallId??``)??u.get(t.toolCallId??``);if(r){let i=r.arguments??{};f.push(p({role:`tool`,name:t.toolName||r.name||`tool`,args:n(i),argsObj:i,result:S(t.content),isError:t.isError},e.seq)),s.add(t.toolCallId)}else c.set(t.toolCallId,{toolName:t.toolName,content:t.content,isError:t.isError});continue}if(t.role===`assistant`){let r=nn(t);if(r.size>0){let i=new Set([...d,...s,...c.keys()]),a=ge([t],{resolvedIds:i});for(let t of a)f.push(p(t,e.seq));for(let[t,i]of r){if(d.has(t))continue;let r=c.get(t);if(r){c.delete(t);let a=i.arguments??{};f.push(p({role:`tool`,name:i.name,args:n(a),argsObj:a,result:S(r.content),isError:r.isError??!1},e.seq))}}continue}}let r=ge([t]);for(let t of r)f.push(p(t,e.seq))}for(let[e,t]of u)o.set(e,t);return i>0&&(i=l[0].seq),f.length>0?f:null}}}const an=[`approaching`,`nearing`,`critical`],on={maxReminders:{approaching:1,nearing:3,critical:1},backoffBaseTurns:4,resetMarginPct:10,approachingMarginPct:10};function $(){return{count:0,lastRemindedTurn:void 0,peakPct:0,active:!1}}function sn(e,t,n,r){return e>=n?`critical`:e>=t?`nearing`:e>=t-r?`approaching`:null}function cn(e,t,n,r){return e===`critical`?n:e===`nearing`?t:t-r}function ln(e,t){return t<=1?0:e.backoffBaseTurns*2**(t-2)}var un=class{config;zones;suppressed=!1;constructor(e={}){this.config={...on,...e},this.zones={approaching:$(),nearing:$(),critical:$()}}check(e){if(this.suppressed)return null;let{contextPercent:t,pruneLinePct:n,compactLinePct:r,currentTurn:i}=e,a=sn(t,n,r,this.config.approachingMarginPct);for(let e of an)e!==a&&this.zones[e].active&&t<cn(e,n,r,this.config.approachingMarginPct)-this.config.resetMarginPct&&(this.zones[e]=$());if(a===null)return null;let o=this.zones[a];o.lastRemindedTurn!==void 0&&i<o.lastRemindedTurn&&(this.zones[a]=$());let s=this.zones[a];s.active=!0,s.peakPct=Math.max(s.peakPct,t);let c=this.config.maxReminders[a];if(s.count>=c)return null;let l=s.count+1;if(s.lastRemindedTurn!==void 0){let e=ln(this.config,l);if(i-s.lastRemindedTurn<e)return null}return s.count=l,s.lastRemindedTurn=i,{zone:a,pct:Math.round(t)}}onCompacted(){this.zones={approaching:$(),nearing:$(),critical:$()}}suppress(){this.suppressed=!0}snapshot(){return{approaching:{count:this.zones.approaching.count,lastTurn:this.zones.approaching.lastRemindedTurn},nearing:{count:this.zones.nearing.count,lastTurn:this.zones.nearing.lastRemindedTurn},critical:{count:this.zones.critical.count,lastTurn:this.zones.critical.lastRemindedTurn}}}};function dn(e){let{getSession:t,app:n,tui:r,projState:i,contextWindow:a,currentModelId:o}=e,s,c=new un,l={approaching:e=>Q.t(`cmd.contextPressureApproaching`,{pct:e}),nearing:e=>Q.t(`cmd.contextPressureNearing`,{pct:e}),critical:e=>Q.t(`cmd.contextPressureCritical`,{pct:e})},d=()=>{let e=t(),n=e.session.messages(),r=0,i=0,a=0,o=0,s=!1,c=0,l=0;for(let e=n.length-1;e>=0;e--){let t=n[e]?.usage;t&&(s||=(r=t.inputTokens??0,i=t.outputTokens??0,a=t.cacheReadTokens??0,o=t.cacheWriteTokens??0,!0),n[e]?.role===`assistant`&&(c+=t.inputTokens??0,l+=t.outputTokens??0))}return{sessionId:e.session.id,lastIn:r,lastOut:i,lastCacheRead:a,lastCacheWrite:o,totIn:c,totOut:l,messageCount:n.length}},f=(e,f)=>{let p=e!==void 0,m=p&&s&&s.sessionId===t().session.id?s:d();s=m;let h=f?f.before:1,g=f?f.after/h:1,_=e=>g<1?Math.round(e*g):e,v=n.modelRegistry.find(o.value??``)?.cost,y=v?m.totIn*(v.input??0)+m.totOut*(v.output??0):0,b=u({systemPrompt:t().systemPrompt,tools:t().tools,lastIn:_(m.lastIn),lastOut:_(m.lastOut),lastCacheRead:_(m.lastCacheRead),lastCacheWrite:_(m.lastCacheWrite),contextWindow:a.value,modelName:t().model?.name??``,totIn:m.totIn,totOut:m.totOut,cost:y>0?y:void 0,messageCount:m.messageCount,streamingOutputTokens:e});if(r.stores.budget.setBudget(b),r.stores.context.setBudget(b),!p&&b.contextWindow>0){let e=b.pruneLine/b.contextWindow*100,t=b.compactLine/b.contextWindow*100,n=c.check({contextPercent:b.contextPercent,pruneLinePct:e,compactLinePct:t,currentTurn:i.currentTurn});n&&r.info.pushNotification(Q.t(`cmd.titleContextPressure`),l[n.zone](n.pct),`system`,n.zone===`critical`?`warning`:`info`)}},p=()=>{try{t().session.setEditedFiles(r.messages.getEditedFiles().map(e=>({path:e.path,operation:e.operation,addedLines:e.addedLines,removedLines:e.removedLines,timestamp:e.timestamp,toolCallId:e.toolCallId}))),n.sessionManager.save(t().id).catch(()=>{})}catch(e){console.error(`\x1b[90m\x1b[2m[persist] editedFiles skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}};return{recomputeBudget:f,persistEditedFiles:p,persistSubagents:()=>{try{let e=[...r.plugins.getSubagents().values()].map(e=>({id:e.id,name:e.command||e.id,status:_t(e),startedAt:e.startedAt}));t().session.setSubagents(e),n.sessionManager.save(t().id).catch(()=>{})}catch(e){console.error(`\x1b[90m\x1b[2m[persist] subagents skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}},persistTurnCount:()=>{try{t().session.setTurnCount(i.currentTurn)}catch(e){console.error(`\x1b[90m\x1b[2m[persist] turnCount skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}},editFileCallback:e=>{try{r.stores.tasks.addEditedFile({path:e.path,operation:e.operation,oldContent:e.oldContent,newContent:e.newContent,addedLines:e.addedLines,removedLines:e.removedLines,timestamp:e.timestamp,toolCallId:e.toolCallId})}catch(e){console.error(`\x1b[90m\x1b[2m[panel] addEditedFile skipped (non-fatal): ${e instanceof Error?e.message:String(e)}\x1b[0m`)}p()},onContextCompacted:()=>{c.onCompacted()}}}function fn(e){let{app:t,getTui:n}=e,r=[],i=()=>{for(let e of r)e();r=[]},a,o,s,c,l,u=()=>{a&&=(clearInterval(a),void 0),o&&=(V.retain(o,!1),void 0),l=void 0},d=()=>{s&&=(clearInterval(s),void 0),c&&=(H?.unpin(c),V.get(c)&&V.retain(c,!1),void 0)};return{clearBgSubs:i,stopBgOutputPoll:u,stopBgSubagentPoll:d,setBgUnsubs:e=>{r=e},handlers:{onBackgroundKill:e=>{if(V.get(e)){V.cancel(e);return}H.abort(e)||U.kill(e)},onBackgroundApply:e=>{let r=n(),i=e=>r.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:e}]}),a=t.agentJobs.apply(e);if(a.applied){let n=a.forbiddenZone?.length?Q.t(`cmd.bgForbiddenZone`,{count:a.forbiddenZone.length,files:a.forbiddenZone.join(`
|
|
6
6
|
`),id:e}):``;i(Q.t(`cmd.bgJobApplied`,{id:e,message:a.message,zone:n})),a.capabilityTouched&&t.reloadCapabilities().then(e=>{r.plugins.setPluginRegistrations(t.getPluginRegistrations()),r.info.showToast(Q.t(`cmd.titleReload`),Q.t(`cmd.reloadDone`,{mcpTools:e.mcpTools,models:e.models,agents:e.agents,teams:e.teams}))},e=>i(Q.t(`cmd.bgAutoReloadFailed`,{msg:e instanceof Error?e.message:String(e)})))}else{let t=a.conflictPaths.length?Q.t(`cmd.bgConflictFiles`,{joined:a.conflictPaths.join(`
|
|
7
|
-
`)}):``;i(Q.t(`cmd.bgJobIncomplete`,{id:e,status:a.status,message:a.message,conflicts:t}))}},onDelegateSupply:(e,n)=>{t.agentJobs.supply(e,n)},onBackgroundViewOutput:e=>{let t=n(),r=async()=>{let n=e=>{let n=`${e.status}|${e.text}|${e.responseText??``}|${e.diff??``}`;n!==l&&(l=n,t.stores.tasks.setBackgroundOutput(e))},r=
|
|
7
|
+
`)}):``;i(Q.t(`cmd.bgJobIncomplete`,{id:e,status:a.status,message:a.message,conflicts:t}))}},onDelegateSupply:(e,n)=>{t.agentJobs.supply(e,n)},onBackgroundViewOutput:e=>{let t=n(),r=async()=>{let n=e=>{let n=`${e.status}|${e.text}|${e.responseText??``}|${e.diff??``}`;n!==l&&(l=n,t.stores.tasks.setBackgroundOutput(e))},r=V.get(e);if(r){let t=r.status===`running`||r.status===`needs_input`?`running`:r.status===`applied`?`exited`:r.status===`failed`?`failed`:`killed`,i=(r.status===`ready`||r.status===`applied`)&&r.diff?.trim()?r.diff:void 0;n({id:e,command:r.title,status:t,text:Ne(r.outputPath,20),prompt:H.get(e)?.prompt,diff:i}),t!==`running`&&u();return}let i=H.get(e);if(i){let t=ge(H.getMessages(e)??[]),r=H.getStreamingText(e),a=ot(t,r),o=Date.now(),s=at(ut(i),o),c=st(H.getTurns(e),o),l=[s.length?s.join(`
|
|
8
8
|
`):``,c.length?c.join(`
|
|
9
|
-
`):``].filter(Boolean).join(`\n${`─`.repeat(40)}\n\n`),d=i.status===`done`?`exited`:i.status===`error`||i.status===`aborted`?`failed`:`running`;n({id:e,command:`@${i.agentName}`,status:d,text:a,messages:t,streamText:r,responseText:l,prompt:i.prompt}),d!==`running`&&u();return}let a=
|
|
9
|
+
`):``].filter(Boolean).join(`\n${`─`.repeat(40)}\n\n`),d=i.status===`done`?`exited`:i.status===`error`||i.status===`aborted`?`failed`:`running`;n({id:e,command:`@${i.agentName}`,status:d,text:a,messages:t,streamText:r,responseText:l,prompt:i.prompt}),d!==`running`&&u();return}let a=U.get(e);if(!a){u(),t.stores.tasks.setBackgroundOutput(null);return}let o=a.status===`running`?`running`:a.status===`exited`?`exited`:`killed`,s=``;if(a.logPath)try{s=(await bt(a.logPath,`utf-8`)).split(`
|
|
10
10
|
`).slice(-20).join(`
|
|
11
|
-
`).trimEnd()}catch{s=``}n({id:e,command:a.command,status:o,text:s}),o!==`running`&&u()};u(),B.get(e)&&(B.retain(e,!0),o=e),r(),a=setInterval(()=>{r()},500)},onBackgroundOutputClose:()=>{u()},onBackgroundSwitch:e=>{let t=n();d();let r=()=>{let n=V?.getMessages(e),r=V?.get(e),i=r?.agentName??``,a=B.get(e);a&&(i=a.title||i);let o=n?_e(n):[],s=V?.getTurns(e),c=V?.getStreamingText(e),l=Date.now(),u={id:e,title:i,messages:o,status:a?.status??`running`,diagnostics:r?ot(dt(r),l):[],timeline:s?ct(s,l):[],streamText:c};t.panes.switchToSubagentContext(u)};V?.pin(e),B.get(e)&&B.retain(e,!0),c=e,r(),s=setInterval(()=>{r()},500)},onBackgroundDelete:e=>{if(B.get(e)){B.remove(e);return}if(H.get(e)){H.remove(e);return}V.remove(e)},onSubagentExit:()=>{d(),n().panes.switchToSubagentContext(null)}}}}const pn=Be(`@x-otto/cli:theme-preset-wiring`);function mn(e,t){let n={kind:`extension`,extensionId:t.pluginId};return e.register(n,{localId:t.localId,label:t.label,appearance:t.appearance,colors:t.colors,markdown:t.markdown})}function hn(e,t){let n=[];for(let r of t)try{n.push(mn(e,r))}catch(e){pn.warn({pluginId:r.pluginId,localId:r.localId,err:String(e)},`theme preset registration failed, skipped`)}return n}function gn(e){let t=it();return hn(t,z(e.activePlugins())),t}function _n(e){return e.startsWith(`backend/`)?e.slice(8):e}function vn(e){let t=()=>({tasks:e.list(),runningTaskIds:[...e.getRunningTaskIds()],isFireOwner:e.isFireOwner(),fireOwnerFailureReason:e.fireOwnerFailureReason()});return{call:async(n,r)=>{let i=_n(n);switch(i){case`schedule.list`:return t();case`schedule.add`:{let t=r;try{let n=e.add({name:t.name,prompt:t.prompt,cronExpression:t.cronExpression,recurring:t.recurring,origin:`user`,target:t.target});return{ok:!0,taskId:n.id,name:n.name,target:n.target}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}case`schedule.update`:{let t=r,n={};return t.name!==void 0&&(n.name=t.name),t.prompt!==void 0&&(n.prompt=t.prompt),t.cronExpression!==void 0&&(n.cronExpression=t.cronExpression),t.enabled!==void 0&&(n.enabled=t.enabled),{ok:e.update(t.taskId,n)}}case`schedule.runNow`:{let{taskId:t}=r;return e.runNow(t),{ok:!0}}case`schedule.toggle`:{let{taskId:t,enabled:n}=r;return{ok:e.update(t,{enabled:n})}}case`schedule.cancel`:{let{taskId:t}=r;return e.cancel(t)}case`schedule.remove`:{let{taskId:t}=r;return{ok:e.remove(t)}}case`schedule.readLogs`:{let{taskId:t,limit:n}=r;return{entries:e.readFireLogs(t,n??20)}}case`schedule.parseCron`:{let{expr:e}=r;try{return{ok:!0,next:Bt(e).toISOString()}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}default:throw Error(`unknown schedule backend method: ${i}`)}},getSnapshot:t}}function yn(e){return t=>{let n=e.value;if(n.id!==t.boundSessionId||n.isPaused||n.status===`archived`)return!1;try{return n.prompt(t.prompt,{streamingBehavior:`followUp`}).catch(()=>{}),!0}catch{return!1}}}function bn(e,t,n,r){let i=e.workspaceRef?.key??`default`,a=new Pt,o,s;if(e.storage.remoteSessionConfigured&&r){let e=async()=>({token:r.sessionToken});o=Rt({sessionUrl:r.sessionUrl,getAuth:e,wsKey:i}),s=Lt({sessionUrl:r.sessionUrl,wsKey:i,getAuth:e})}else o=zt(i),s=It(i);let c=new Ft({registry:a,store:o,ownership:s,jobRegistry:G,startJob:t=>({id:e.agentJobs.start({title:t.title,prompt:t.prompt,sessionId:t.sessionId,origin:t.origin}).id}),getSessionId:()=>t.value.id,notifySubscriber:(t,n)=>e.notifyPluginServiceSchedule({pluginId:t.pluginId,serviceId:t.serviceId},n),followUpCurrentSession:yn(t),retryBackoffMs:e.getResilienceConfig().schedule.retryBackoffMs});c.start().catch(e=>{console.error(`\x1b[3m\x1b[2m[schedule] scheduler failed to start: ${e instanceof Error?e.message:String(e)}\x1b[0m`)}),O(c),e.setScheduleService(c);let l=vn(c);e.panelBackendController.registerInProcessBackend(`plugin-schedule`,l.call);let u=setInterval(()=>{if(!n)return;let e=c.list().map(e=>({id:e.id,name:e.name,prompt:e.prompt,cronExpression:e.cronExpression,enabled:e.enabled,recurring:e.recurring,nextFireAt:e.nextFireAt,lastFiredAt:e.lastFiredAt,lastFireFailed:e.lastFireFailed,lastFireError:e.lastFireError,lastFireCancelled:e.lastFireCancelled}));n.stores.tasks.setScheduleTasks(e)},5e3);return u.unref(),{pollInterval:u,scheduler:c}}function xn(e){let{tui:t,app:n,themeRegistry:r,sessionRef:i,interactiveRef:a,regRef:o,slashCommandsRef:s,modelReadyRef:c,currentModelIdRef:l,currentLangRef:u,projState:d,agentProcessingRef:p,modelsRef:m,availableModelIds:h,restartRequestedRef:g,applyModel:_,persistAvailable:v,refreshModelsNow:y,refreshSlashCommands:b,events:x,redState:S,agentMessagesToChatMessages:ee,PROVIDER_DISPLAY_NAMES:C,apiCredentialId:te,onContextCompacted:w}=e;return{tui:t,app:n,state:{get session(){return i.value},set session(e){i.value=e},get interactive(){return a.value},set interactive(e){a.value=e},get reg(){return o.value},set reg(e){o.value=e},get slashCommands(){return s.value},set slashCommands(e){s.value=e},get modelReady(){return c.value},set modelReady(e){c.value=e},get currentModelId(){return l.value},set currentModelId(e){l.value=e},get currentLang(){return u.value},set currentLang(e){u.value=e},get todoList(){return d.todoList},set todoList(e){d.todoList=e},get agentProcessing(){return p.value},set agentProcessing(e){p.value=e},get models(){return m.value},set models(e){m.value=e},get availableModelIds(){return h},get restartRequested(){return g.value},set restartRequested(e){g.value=!!e},themeRegistry:r},callbacks:{applyModel:_,persistAvailable:v,refreshModelsNow:y,registerAllTuiCommands:()=>{Zt(o.value)},refreshSlashCommands:b,attachSessionHandler:()=>x.attachSessionHandler(),restoreSwitchedSession:()=>{d.delegated.clear(),d.todoList=[],d.currentTurn=0,Object.assign(S,f()),t.stores.tasks.setTasks([],void 0),t.panes.clearEditedFiles(),t.plugins.clearSubagents(),k({session:i.value,projState:d,tui:t}),w()},resetCurrentTurn:()=>{d.currentTurn=0},onContextCompacted:w,sessionUnsub:()=>x.getSessionUnsub(),getLastProviderUsage:()=>x.getLastProviderUsage(),isWriteLeaseReadOnly:()=>x.isWriteLeaseReadOnly(),isRunPaused:()=>x.isRunPaused(),agentMessagesToChatMessages:ee,PROVIDER_DISPLAY_NAMES:C,apiCredentialId:te}}}function Sn(e){e.setEcosystemSearch(async t=>{try{let{registries:n,warnings:r}=await we(e).loadAll();return{hits:J(n.flatMap(e=>e.entries.map(t=>({entry:t,registry:e}))).map(e=>({text:e.entry.id,aliases:[e.entry.description,...e.entry.keywords??[]],payload:e})),t.join(` `),{maxResults:8}).map(e=>({id:e.item.payload.entry.id,description:e.item.payload.entry.description,capabilities:e.item.payload.entry.capabilities,sourceName:e.item.payload.registry.sourceName,stale:e.item.payload.registry.stale})),warnings:r}}catch{return}})}function Cn(e){let{app:t,tui:n}=e;t.setMcpStartupCallback(e=>{let r=[`HTTP_PROXY`,`HTTPS_PROXY`,`http_proxy`,`https_proxy`].find(e=>process.env[e]),i=r?process.env[r]:void 0,a=t.settings.get(`proxy`);i&&r&&!a?.url&&(Ce(i,r),n.info.showToast(Q.t(`proxy.title`),Q.t(`proxy.envDetectedToast`,{source:r,value:i})))})}function wn(e){let{app:t,tui:n,session:r}=e;n.plugins.registerArgumentSuggester(`model`,(e,n=20)=>J(t.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`).map(e=>({text:e.id,aliases:[e.name,e.provider],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload.id,description:e.item.payload.name})));let i=Ie(r.session.metadata().title,r.session.messages(),r.id);n.lifecycle.setTerminalTitle(i),n.stores.tasks.setSessionTitle(i)}function Tn(e){let{app:t,tui:n,getScheduler:r}=e;n.plugins.registerArgumentSuggester(`schedule`,(e,t=20)=>{let n=[`remove`,`run`,`enable`,`disable`],i=n.find(t=>e.toLowerCase().startsWith(`${t} `));if(!i)return J([...n,`list`,`add`,`logs`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:t}).map(e=>({name:e.item.payload}));let a=r();if(!a)return[];let o=e.slice(i.length+1);return J(a.list().map(e=>({text:e.id,aliases:[e.name],payload:e})),o,{maxResults:t}).map(e=>({name:`${i} ${e.item.payload.id}`,description:e.item.payload.name}))}),n.plugins.registerArgumentSuggester(`replay`,(e,n=20)=>J(t.listSessions().map(e=>({text:e.id,aliases:e.title?[e.title]:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload.id,description:e.item.payload.title??e.item.payload.id.slice(0,8)}))),n.plugins.registerArgumentSuggester(`session`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`unlock `)?e.slice(7):e;return r===e?J([{text:`unlock`,aliases:[],payload:`unlock`}],e,{maxResults:n}).map(e=>({name:e.item.payload,description:`Write-lease diagnostics/force-unlock`})):J(t.listSessions().map(e=>({text:e.id,aliases:e.title?[e.title]:[],payload:e})),r,{maxResults:n}).map(e=>({name:`unlock ${e.item.payload.id}`,description:e.item.payload.title??e.item.payload.id.slice(0,8)}))}),n.plugins.registerArgumentSuggester(`registry`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`remove `)?e.slice(7):e;return r===e?J([`list`,`add`,`remove`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload})):J(we(t).listSources().filter(e=>!e.builtin).map(e=>({text:e.name,aliases:[e.url],payload:e})),r,{maxResults:n}).map(e=>({name:`remove ${e.item.payload.name}`,description:e.item.payload.url}))}),n.plugins.registerArgumentSuggester(`trust`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`plugin `)?e.slice(7):e;return r===e?J([`status`,`trust`,`untrust`,`plugin`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload})):J(be({cwd:t.workspaceDir??process.cwd(),homedir:R()}).map(e=>({text:e.id,aliases:[],payload:e})),r,{maxResults:n}).map(e=>({name:`plugin ${e.item.payload.id}`,description:e.item.payload.scope}))})}function En(e){let t=e[e.length-1];if(t?.type===`message`&&t.message?.role===`user`)return{parentId:t.parentId}}function Dn(e,t){!t||!t.newer||(t.forced?(e.info.pushNotification(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateNotifForced`,{latest:t.latest,current:t.current}),`version`,`error`),e.stores.tasks.setForcedUpgrade(Q.t(`cmd.updateForcedBanner`,{latest:t.latest,current:t.current})),e.stores.notification.setPulseSurvey(null)):(e.info.pushNotification(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateNotifAvailable`,{latest:t.latest,current:t.current}),`version`,`info`),e.info.showToast(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateToast`,{latest:t.latest}))))}async function On(e){let{tui:n,options:r,app:i,session:a,projState:o,resumedNote:s,resumed:c,updateCheckPromise:l,bg:u,events:d}=e;if(s&&t({resumedNote:s,isFound:!!c,session:a,projState:o,tui:n}),r.resumePrompt&&c)if(i.memoryGovernor.sample().level===`critical`)n.info.showToast(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureResumeAbortedMessage`));else{let e=En(a.session.branchEntries());e&&(e.parentId&&a.session.branch(e.parentId),a.prompt(r.resumePrompt).catch(e=>{i.logger.warn({err:e instanceof Error?e.message:String(e)},`[memory-governor] auto-resume prompt failed`),n.info.showToast(Q.t(`cmd.titleError`),Q.t(`cmd.memoryPressureResumeFailedMessage`))}))}l.then(e=>Dn(n,e)),u.setBgUnsubs(d.bgUnsubs),d.attachSessionHandler(),kn(n,i)}function kn(e,t){h(n=>{if(n.status!==`needs-input`)return;let r=n.id.slice(0,8),i=t.listSessions().find(e=>e.id===n.id)?.title??r;e.info.pushNotification(`session needs input`,`Background session '${i}' (${r}) requires your input (/resume ${r})`,`system`,`warning`)}),t.hookRegistry.on(`session.deleted`,`rfc234-background-cleanup`,e=>{A(e.sessionId)})}function An(e){let t=e??et(import.meta.url);t=Ze(t);let n=t===`/`?t:`/`;for(;t!==n;){try{if($e(t+`/.git`))return t}catch{}t=Ze(t)}try{if($e(n+`/.git`))return n}catch{}}var jn=class{repoRoot;currentBuildId;checkIntervalMs;onStale;logger;lastNotifiedBuildId=void 0;disposed=!1;timer;activeChild;constructor(e){this.repoRoot=e.repoRoot,this.currentBuildId=e.currentBuildId,this.checkIntervalMs=e.checkIntervalMs??6e5,this.onStale=e.onStale,this.logger=e.logger}start(){this.disposed||this.scheduleNext()}dispose(){if(this.disposed=!0,this.timer&&=(clearTimeout(this.timer),void 0),this.activeChild){try{this.activeChild.kill()}catch{}this.activeChild=void 0}this.lastNotifiedBuildId=void 0}scheduleNext(){this.disposed||(this.timer=setTimeout(()=>{this.timer=void 0,this.performCheck().then(()=>{this.scheduleNext()})},this.checkIntervalMs),this.timer.unref())}performCheck(){return new Promise(e=>{if(this.disposed){e();return}let t=Te(`git`,[`rev-list`,`--count`,`HEAD`],{cwd:this.repoRoot,timeout:5e3},(t,n)=>{if(this.activeChild=void 0,t){this.logger?.warn({err:t instanceof Error?t.message:String(t)},`[stale-build-detector] git rev-list failed`),e();return}let r=n.trim(),i=parseInt(r,10);if(!Number.isFinite(i)){this.logger?.warn({raw:r},`[stale-build-detector] failed to parse git output as number`),e();return}if(i>this.currentBuildId&&i!==this.lastNotifiedBuildId){this.lastNotifiedBuildId=i;try{this.onStale?.(i)}catch(e){this.logger?.warn({err:e instanceof Error?e.message:String(e)},`[stale-build-detector] onStale callback threw`)}}e()});this.activeChild=t,t.on(`error`,()=>{this.activeChild=void 0})})}};function Mn(e){return e.trim().length===0}function Nn(e){let{tui:t,app:n,submitState:r}=e;return(e,i=`!!`)=>{let a=e.trim();if(!a)return;let o=q(a);if(!o.safe){t.info.showToast(Q.t(`cmd.titleShell`),Q.t(`cmd.dangerousBlocked`,{reason:o.reason})),t.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`cmd.dangerousBlockedDetail`,{reason:o.reason,cmd:a})}]});return}t.messages.echoUserInput(`${i} ${a}`),t.shell.startShellExecution(a),r.shellChild=Ee(a,{shell:!0,cwd:n.workspaceDir,stdio:[`ignore`,`pipe`,`pipe`],env:ze()}),K.registerChild({command:a,args:[],owner:{type:`cli-shell`,id:`!!`},category:`shell`,lifecycle:`evictable`,cwd:n.workspaceDir},r.shellChild),r.shellChild.stdout.on(`data`,e=>{t.shell.appendShellOutput(e.toString(`utf-8`))}),r.shellChild.stderr.on(`data`,e=>{t.shell.appendShellOutput(e.toString(`utf-8`))}),r.shellChild.on(`close`,(e,n)=>{r.shellChild=null,n?t.shell.finishShellExecution(null,void 0,!0):t.shell.finishShellExecution(e)}),r.shellChild.on(`error`,e=>{r.shellChild=null,t.shell.finishShellExecution(null,`\nError: ${e.message}`)})}}function Pn(e){let{agentProcessingRef:t,tui:n,requestStop:r}=e;return(e,i)=>{let a=Kt(e);return a.isCommand&&a.command.toLowerCase()===`abort`&&i===`send`?(t.value?r(`abort`):n.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.noRunningTask`)),!0):!1}}function Fn(e){let{app:t,tui:n}=e;return async e=>{let r=e.trim();if(!r)return;if(!t.storage.autoMemory){n.info.showToast(Q.t(`cmd.titleMemory`),Q.t(`cmd.memoryDisabled`));return}let a=await i(r,process.env.OTTO_MEMORY_LLM_NAMING===`1`?t.completeText:void 0);await t.storage.autoMemory.record(a),n.messages.echoUserInput(`# ${r}`),n.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`cmd.memorySaved`,{name:a.name})}]})}}function In(e){let t=e.terminated===!0?Q.t(`shell.askAiTerminated`):e.exitCode===null?Q.t(`shell.unknownError`):Q.t(`shell.exitCode`,{code:e.exitCode}),n=e.output.length>5e4?`${e.output.slice(0,5e4)}\n${Q.t(`shell.truncated`)}`:e.output;return Q.t(`shell.prompt`,{command:e.command,errorLabel:t,output:n})}function Ln(e,t,n){return e-t<50?`dedup`:n.shellRunning?`kill-shell`:n.busy?n.stopDialogOpen?`escalate-exit`:`open-stop-dialog`:n.idleCtrlCCount+1>=2?`exit-process`:`hint-exit`}function Rn(e){let{getTui:t,getSession:n,dispatchAbort:r,clearTodoLayers:i,markUserAborted:a,resetCtrlCCount:o,markRestartRequested:s,stopTui:c,isBusy:l}=e,u=null,d=()=>u!==null&&t()?.info.getCurrentPath()===`/dialog/confirm`,f=()=>{a(),o(),r(),i()},p=e=>{e&&s(),a(),o();try{r()}catch{}c()},m=e=>{if(e===`abort`)return{title:Q.t(`confirm.abortConfirmTitle`),message:Q.t(`confirm.abortConfirmMessage`),confirmLabel:Q.t(`common.abortButton`),extraLabel:Q.t(`common.pauseButton`),onConfirm:()=>{f(),t()?.info.showToast(Q.t(`cmd.titleAborted`),Q.t(`cmd.runAborted`))}};let n=e===`exit-restart`;return{title:n?Q.t(`confirm.exitRestartConfirmTitle`):Q.t(`confirm.exitConfirmTitle`),message:Q.t(`confirm.exitConfirmMessage`),confirmLabel:n?Q.t(`common.abortAndRestartButton`):Q.t(`common.abortAndExitButton`),extraLabel:void 0,onConfirm:()=>{p(n)}}},h=e=>{let r=t();if(!r)return;let i=m(e);u=e,r.modal.openModal({kind:`confirm`,title:i.title,message:i.message,confirmLabel:i.confirmLabel,confirmColor:`amber`,extraLabel:i.extraLabel,extraColor:`accent`,dangerous:!0,onConfirm:()=>{u=null,i.onConfirm()},onCancel:()=>{u=null},onExtra:i.extraLabel?()=>{u=null,n().pauseRun()?t()?.info.showToast(Q.t(`cmd.titlePaused`),Q.t(`cmd.runWillPauseAfterTurn`)):t()?.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.noRunningTaskToPause`))}:void 0})};return{requestStop:e=>{if(!t()){e===`abort`?f():p(e===`exit-restart`);return}if(e!==`abort`&&!l()){p(e===`exit-restart`);return}h(e)},isStopDialogOpen:d,escalateToExit:()=>{let e=t();!e||!d()||(h(`exit`),e.modal.resolveConfirm(!0))},abortNow:f}}async function zn(e,t,n){if(n){let n=t.settings.get(`model`);if(typeof n==`string`&&n&&e.model?.id!==n){let r=t.modelRegistry.find(n);r&&await t.providerRegistry.hasCredential(r.provider)&&(e.model=r,t.storage.memory?.reconfigure?.({contextWindow:r.contextWindow,maxOutput:r.maxOutputTokens}))}}{let n=t.settings.get(`thinking_level`),r=[`low`,`medium`,`high`,`xhigh`,`max`],i=n===`minimal`?`low`:n;typeof i==`string`&&r.includes(i)&&(e.thinkingLevel=i)}}var Bn=class{entries=[];filePath;constructor(e,t=X(Ke,`sessions`)){this.filePath=X(t,`${e}.history.json`)}list(e){return this.entries.slice(-(e??100))}append(e){e.trim()&&(this.entries.push(e),this.entries.length>100&&(this.entries=this.entries.slice(-100)))}hydrate(e){this.entries=e.slice(-100)}async persist(){if(Ye())return;let e=JSON.stringify(this.entries,null,2),t=`${this.filePath}.tmp`;try{await bt(Ze(this.filePath),{recursive:!0}),await Tt(t,e,`utf-8`),await Ct(t,this.filePath)}catch(e){throw await wt(t).catch(()=>{}),e}}async load(){try{let e=await xt(this.filePath,`utf-8`),t=JSON.parse(e);return Array.isArray(t)&&t.every(e=>typeof e==`string`)?(this.entries=t.slice(-100),this.entries):[]}catch{return[]}}};const Vn={[rt]:e=>mt(e),[Z]:e=>ft(e),[nt]:e=>pt(e)};function Hn(){let e=process.env.SHELL??``,t=R(),n=process.env.HISTFILE;return e.includes(`fish`)?[{id:nt,path:X(t,`.local/share/fish/fish_history`)},{id:nt,path:X(t,`.config/fish/fish_history`)}]:e.includes(`bash`)?[{id:Z,path:n?.startsWith(`~`)?X(t,n.slice(2)):n??X(t,`.bash_history`)}]:e.includes(`zsh`)||!e?[{id:rt,path:n?.startsWith(`~`)?X(t,n.slice(2)):n??X(t,`.zsh_history`)}]:[]}function Un(e){let t=e?.sources?.filter(e=>e?.enabled!==!1&&!!e?.id&&!!e?.path);if(t&&t.length>0){let e=R();return t.map(t=>({id:t.id,path:Wn(t.path,e)}))}return Hn()}function Wn(e,t){return e.startsWith(`~/`)?X(t,e.slice(2)):e===`~`?t:e}async function Gn(e){try{return await yt(e),!0}catch{return!1}}async function Kn(e,t){let n=Vn[e.id];if(!n||!await Gn(e.path))return[];try{return n(await xt(e.path,`utf8`)).slice(-t)}catch{return[]}}async function qn(e){if(e?.enabled!==!0)return[];let t=e.maxEntries??2e3,n=Un(e),r=new Set,i=[];for(let e of n){if(r.has(e.path))continue;r.add(e.path);let n=await Kn(e,t);i.push(...n)}return i.slice(-t)}async function Jn(e,t){let n=new Bn(e.id);return{historyStore:n,inputHistory:await n.load().then(t=>{if(t.length>0)return t;let r=e.session.getInputHistory();return r&&r.length>0?(n.hydrate(r),n.persist().catch(()=>{}),e.session.setInputHistory([]),r):[]}),externalHistoryCommands:t?.enabled===!0?at(await qn(t)):void 0}}function Yn(e){let t=(t,n)=>{e.onError?.(t,n)},n=async n=>{let r=e.gateway(),i=e.bridge();if(!(!r||!i))try{let e=await r.getPaste(n);i.hydratePaste({entries:e.entries,nextId:e.nextId})}catch(e){t(`load`,e);try{i.hydratePaste(null)}catch{}}},r=async n=>{let r=e.gateway(),i=e.bridge();if(!(!r||!i))try{let e=i.exportPaste();if(!e)return;await r.setPaste(n,{sessionId:n,entries:e.entries,nextId:e.nextId})}catch(e){t(`save`,e)}};return{load:n,save:r,async switchTo(e,t){e!==t&&(e!==void 0&&await r(e),await n(t))},async fork(n,r){let i=e.gateway(),a=e.bridge();if(!(!i||!a))try{let e=a.exportPaste()??await i.getPaste(n);await i.setPaste(r,{sessionId:r,entries:e.entries,nextId:e.nextId})}catch(e){t(`fork`,e)}}}}function Xn(e){let{session:t,tui:n,retryAccelerate:r,setRateLimitInfo:i,abortNow:a}=e;t.coreAgent.on(`stream.retry`,({attempt:e,maxRetries:t,delayMs:i,reason:o})=>{n.engine.showRetryDialog(e,t,i,r,()=>{n.engine.clearRetryDialog()},o,()=>{a()})}),t.coreAgent.on(`rate.limit.exhausted`,({limitType:e,resetsAt:t})=>{n.engine.clearRetryDialog(),i({limitType:e,resetsAt:t})}),t.coreAgent.on(`lifecycle.tool.completed.crossBoundary`,({toolName:e,result:t})=>{let r=Q.t(`cmd.titleBackgroundTask`),i=t.isError?Q.t(`cmd.lifecycleCrossBoundaryFailed`,{toolName:e}):Q.t(`cmd.lifecycleCrossBoundaryDone`,{toolName:e});n.info.showToast(r,i)})}function Zn(e,t){let n=e=>`${e.kind}\u0000${e.label}`,r=n(t);return[t,...e.filter(e=>n(e)!==r)].slice(0,5)}function Qn(e){return{label:e.label,value:e.value,kind:e.kind,description:e.description}}function $n(e){return e.map(e=>({label:e.label,value:e.value,kind:e.kind,description:e.description,source:`recent`}))}function er(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0?r:t}function tr(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0&&Number.isInteger(r)?r:t}function nr(e){let{app:t,tui:n,getSession:r,setRestartResumePrompt:i,setRestartMemoryTriggered:a,handleExit:o,onContextCompacted:s,recomputeBudget:c}=e,l=!1,u=0,d,f=!1,p=0,m=!1,h=er(`OTTO_MEMORY_CRITICAL_NOTIFY_INTERVAL_MS`,18e5),g=tr(`OTTO_MEMORY_CRITICAL_NOTIFY_ESCALATION_CYCLES`,4),_,v=()=>{let e=r();if(e.isBusy){let t=e.session.messages(),n=t[t.length-1];if(n?.role===`user`&&!n.internal){let e=S(n.content);e&&i(e)}}a(!0),o({type:`exit`,restart:!0})},y=()=>{_&&=(clearInterval(_),void 0),p=0,m=!1};t.memoryGovernor.setCallbacks({onWarning:()=>{r().compactNow().then(e=>{e.compacted&&(n.info.showToast(Q.t(`cmd.titleAutoCompact`),Q.t(`compact.edResult`,{before:e.before,after:e.after})),s(),c())}).catch(e=>{let r=e instanceof Error?e.message:String(e);t.logger.warn({err:r},`[memory-governor] compactNow (soft degrade) failed`),n.info.showToast(Q.t(`cmd.titleAutoCompact`),Q.t(`cmd.autoCompactFailed`,{msg:r}))})},onCritical:e=>{if(l){n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),`system`,`info`);return}n.info.isFullScreenPaneActive()&&(u++,d??=Date.now(),u<3&&Date.now()-d<300*1e3)||(u=0,f=!0,n.modal.openModal({kind:`confirm`,title:Q.t(`cmd.titleMemoryPressure`),message:Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),confirmLabel:Q.t(`cmd.memoryPressureRestartNow`),cancelLabel:Q.t(`cmd.memoryPressureRemindLater`),confirmColor:`amber`,extraLabel:Q.t(`cmd.memoryPressureSuppress`),onConfirm:()=>{f=!1,y(),v()},onCancel:()=>{f=!1},onExtra:()=>{f=!1,l=!0}}))},onCriticalDuringGrace:e=>{n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),`system`,`warning`)},onCriticalTimeout:e=>{if(f){f=!1,v();return}let i=()=>{p++,n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:t.memoryGovernor.sample().usedPct.toFixed(0)}),`system`,`warning`),!m&&p>=g&&(m=!0,r().compactNow().catch(e=>{let n=e instanceof Error?e.message:String(e);t.logger.warn({err:n},`[memory-governor] critical-unattended-escalation compactNow failed`)}),t.storage.traceStore?.append(r().id,{ts:Date.now(),sessionId:r().id,kind:`lifecycle`,node:`critical-unattended-escalation`,payload:{usedPct:e.usedPct,cycles:p}}).catch(e=>{t.logger.warn({err:e instanceof Error?e.message:String(e)},`[memory-governor] critical-unattended-escalation trace append failed`)}))};_||(i(),_=setInterval(i,h),_.unref?.())},onLevelChange:e=>{e!==`critical`&&(u=0,d=void 0,y()),n.engine.pushEngineEvent({kind:`perf`,indicatorLevel:e,memory:t.memoryGovernor.sample()})}}),t.fleetMonitor.setCallbacks({onBudgetExceeded:e=>{n.info.pushNotification(Q.t(`cmd.titleFleetBudget`),Q.t(`cmd.fleetBudgetExceeded`,{processCount:e.processCount,totalRssMb:e.totalRssMb}),`system`,`warning`)}})}function rr(e){let{app:t,getTui:n,getTuiRef:r,getSession:i,getCliCtx:a,historyStore:o}=e;return{onCyclePermissionMode:()=>{let e=n(),r=s(t.getPermissionMode());e.stores.tasks.setPermissionMode(r),e.info.showToast(Q.t(`cmd.titlePermission`),Q.t(`pref.permModeSwitched`,{label:Q.t(`pref.permModeLabel`,{context:r})})),t.setPermissionMode(r)},onHistoryPush:t=>{try{o.hydrate([...t]),o.persist().catch(()=>{})}catch{}e.getPasteBinder?.()?.save(i().id)},onDraftSave:e=>{let n=i(),a=n.session.getDrafts()??[],o=m(void 0,e,a),s=p([...a,o]);n.session.setDrafts(s),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(g(s))},onDraftDelete:e=>{let n=i(),a=(n.session.getDrafts()??[]).filter(t=>t.id!==e);n.session.setDrafts(a),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(g(a))},onDraftDeleteMany:e=>{let n=i(),a=new Set(e),o=(n.session.getDrafts()??[]).filter(e=>!a.has(e.id));n.session.setDrafts(o),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(g(o))},onA2uiAction:(e,t,n)=>{M(`a2ui-action`,n?[e,t,JSON.stringify(n)]:[e,t],a())},onPerfRefresh:()=>{M(`perf`,[],a())},onProxySubmitUrl:e=>{M(`proxy`,[e],a())},onProxyToggleEnabled:()=>{M(`proxy`,[t.settings.get(`proxy`)?.enabled===!1?`on`:`off`],a())},onProxyClear:()=>{M(`proxy`,[`clear`],a())},onProxyTest:()=>{M(`proxy`,[`test`],a())}}}function ir(e){return{...ar(e),pluginSource:e.pluginSource,intervalSeconds:e.errorRetryIntervalSeconds}}function ar(e){let{msg:t,provider:n,authError:r,isRefreshFailed:i,unsupported:a,rateLimit:o,rateLimitInfo:s,getErrorRetryAttempt:c,incErrorRetryAttempt:l,errorRetryMax:u,retryQueued:d,resetAndRetry:f,cancelRetry:p,switchModelThenRetry:m,goToAuth:h}=e;if(s)return s.resetsAt===void 0?{reason:t,attempt:0,max:u,mode:`manual`,limitType:s.limitType,actions:[{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p}:{reason:t,attempt:0,max:u,mode:`resetsAt`,resetsAt:s.resetsAt,limitType:s.limitType,actions:[{kind:`retryNow`,label:Q.t(`error.retryNow`),run:d},{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m}],onExpired:d,onCancel:p};if(r)return{reason:i?Q.t(`cmd.authRefreshFailed`,{ps:n?` (${n})`:``,ls:n?` ${n}`:``}):Q.t(`cmd.authFailed`,{ps:n?` (${n})`:``,ls:n?` ${n}`:``}),attempt:c(),max:u,mode:`manual`,actions:[{kind:`login`,label:Q.t(`model.goToLoginButton`),run:h},{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p};if(a)return{reason:Q.t(`cmd.modelNotSupported`),attempt:c(),max:u,mode:`manual`,actions:[{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p};let g=l(),_=g>u;return{reason:o?Q.t(`cmd.rateLimitedRetriesExhausted`):Q.t(`cmd.requestFailed`,{msg:t}),attempt:Math.min(g,u),max:u,mode:`auto`,exhausted:_,actions:[{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:_?f:d}],onExpired:_?()=>{}:d,onCancel:p}}function or(e){let{err:t}=e,n=t instanceof Error?t.message:String(t),r=t?.code===`AGENT_ABORTED`;if(!(e.submitState.userAborted||r)){let r=e.provider,i=t?.code,a=t?.pluginSource,{authError:o,isRefreshFailed:s,unsupported:c,rateLimit:l,pluginSource:u}=x(n,i,a),d=e.rateLimitInfoRef.current;e.rateLimitInfoRef.current=void 0;let f=(()=>{let t=e.cliCtx,n=t?.app?.storage?.traceStore,r=t?.state?.session;if(!n||!r)return null;let i=r.session.getTurnCount();return{traceStore:n,sessionId:r.id,...i===void 0?{}:{turn:i}}})(),p=()=>{f&&E(f,{attempt:e.errorRetryAttemptRef.current+1,max:e.ERROR_RETRY_MAX,mode:d?`resetsAt`:o||c?`manual`:`auto`,reason:n.slice(0,120)}),e.retryModeRef.current=!0;let t=e.latestSubmittedPromptRef?.current,r=e.tui.engine.takeLastQueuedFollowUp?.(),i=t!=null&&t.text!==e.text,a=i?t.text:r?.text??e.text,s=i?t.mode:r?.mode??e.mode;queueMicrotask(()=>e.handleSubmit?.(a,s,`send`))};e.tui.engine.showErrorRetry(ir({msg:n,provider:r,authError:o,isRefreshFailed:s,unsupported:c,rateLimit:l,rateLimitInfo:d,pluginSource:u,getErrorRetryAttempt:()=>e.errorRetryAttemptRef.current,incErrorRetryAttempt:()=>++e.errorRetryAttemptRef.current,errorRetryMax:e.ERROR_RETRY_MAX,errorRetryIntervalSeconds:e.ERROR_RETRY_INTERVAL_SECONDS,retryQueued:p,resetAndRetry:()=>{f&&he(f),e.errorRetryAttemptRef.current=0,p()},cancelRetry:()=>{f&&ge(f,{attempt:e.errorRetryAttemptRef.current}),e.errorRetryAttemptRef.current=0},switchModelThenRetry:()=>{e.handleModel([],e.cliCtx,{afterSwitch:p})},goToAuth:()=>{e.handleProviderAuth([r??``].filter(Boolean),e.cliCtx)}}))}}async function sr(t,n,i){let s=!1,l=!1,u,p;try{let m=n.settings.get(`permission_mode`);(m===void 0||m===`auto`)&&await n.settings.update({permission_mode:`confirm`});let h=t.continueSession?n.getSession(t.continueSession)??await n.sessionManager.restore(t.continueSession)??void 0:void 0,v=h?h.session.buildContext().messages.filter(e=>{let t=e.role;return t===`user`||t===`assistant`}).length:0,x={value:h?n.sessionManager.consumeCrashGap(h.id):void 0},S=t.continueSession?h?Q.t(`cmd.resumeRestored`,{idShort:t.continueSession.slice(0,8),count:v}):Q.t(`cmd.resumeNotFound`,{id:t.continueSession}):void 0,te=!!(t.continueSession&&h),E=!!(t.model||n.settings.get(`model`)||n.settings.get(`model_slots`)?.default),O={skip:!1},ne=await n.hydrateModelCache().catch(()=>new Set),oe=!h&&n.modelRegistry.getAll().length===0,k=`__otto_setup__`;oe&&n.modelRegistry.register({id:k,name:`Setup required`,provider:`otto`,api:`otto`,baseUrl:``,reasoning:!1,input:[`text`],contextWindow:32e3,maxOutputTokens:4e3});let A=oe?!1:E,N=h??await n.createSession({interactive:!0,retryAccelerate:O,...A?{}:{model:n.modelRegistry.getAll()[0]}});await zn(N,n,!!h);let F=A||te,he={get value(){return F},set value(e){F=e}},ge=n.modelRegistry.getAll().filter(e=>e.id!==k).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow})),L=new Set([...ne,...n.getSessionAvailableModels(N.id)]),ve=()=>n.setSessionAvailableModels(N.id,[...L]);ve();let ye=L.size===0,be=new me(b({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>N.model?.id,isModelUsable:Et(n.authStore)})),Ce=async e=>{let t=await n.refreshModels().catch(()=>[]);ge=n.modelRegistry.getAll().filter(e=>e.id!==k).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow}));for(let e of t)if(e.status===`ok`)for(let t of e.availableIds??[])L.add(t);ge.length>0&&n.modelRegistry.getAll().some(e=>e.id===k)&&n.modelRegistry.unregister(k),ve();let r=L.size===0;z?.stores.tasks.setNeedsSetup(r);let i=await be.refresh().catch(()=>null);if(i&&z?.stores.tasks.setFtueStage(i.stage),ye&&!r&&(ye=!1,z?.info.showToast(Q.t(`cmd.titleSetupReady`),Q.t(`cmd.setupReadyMessage`))),e){let n=t.filter(e=>e.status===`ok`);e(n.length>0?Q.t(`cmd.modelsRefreshed`,{summary:n.map(e=>`${e.provider} ${e.total}`).join(` · `)}):Q.t(`cmd.modelsRefreshedEmpty`))}};Ce();let we=F?N.model?.id:void 0,R=n.modelRegistry.getAll().filter(e=>e.id!==k).find(e=>e.id===we)?.contextWindow??0,Te={get value(){return R},set value(e){R=e}},Ee=we,De={get value(){return Ee},set value(e){Ee=e}},ke=e=>ee(n,e,N.thinkingLevel),z,Ae={get value(){return z},set value(e){z=e}},je,Me={get value(){return je},set value(e){je=e}},Pe={value:void 0},B={value:t},V=e=>{switch(e.kind){case`steer`:N.steer(e.input);break;case`abort`:U.abort();break;case`pauseAfterTurn`:N.pauseRun();break;case`resumeRun`:N.resumeRun();break}},H=ie({modelReady:he,currentModelId:De,contextWindow:Te,tuiRef:Ae,pushBudgetNow:Me,app:n,getSession:()=>N,options:B,fmtDisplayModel:ke,onEngineModelAction:V}),Fe=T({getSession:()=>N,app:n,tuiRef:Ae,options:B,fmtDisplayModel:ke,applyModel:H,onExitSession:()=>Pe.value?.()}),U=new e(N,{models:ge,currentModel:we,onModelChange:H}),{startTui:Ie}=await import(`@x-otto/tui`),W=U.getRegistry();Zt(W);let Le=ue(W,n),G={agentProcessing:!1,ctrlCCount:0,lastCtrlCTime:0,userAborted:!1,shellChild:null,streamedText:!1,retryMode:!1,errorRetryAttempt:0,lastRateLimitInfo:void 0,latestSubmittedPrompt:void 0},K=()=>Ut(N.isBusy,G.agentProcessing),Re=Xt(W,G.agentProcessing,de,Q.t(`cmdDesc`,{returnObjects:!0}),N.pinned,N.isPaused),ze=()=>(Re=Xt(W,G.agentProcessing,de,Q.t(`cmdDesc`,{returnObjects:!0}),N.pinned,N.isPaused),Re);P(n),j(n,L),D(n),fe(n);let q=Ot(),Be=n.settings.get(`language`)??`auto`,J=Be===`auto`?w():Be,He=gn(n),Ue=n.settings.get(`theme_preset`),We=n.settings.get(`keybinding_overrides`);_(J);let Ke=C({currentVersion:I(),lastCheck:n.settings.get(`last_update_check`),autoCheck:n.settings.get(`auto_update_check`)!==!1,persistLastCheck:()=>n.settings.persist({last_update_check:Date.now()})});await new Promise(async e=>{let m,b=n.getResilienceConfig().errorRetry.maxAttempts,ee,C=!1,T=()=>{if(!C){C=!0;try{p?.clearBgSubs()}catch{}try{p?.stopBgOutputPoll()}catch{}try{p?.stopBgSubagentPoll()}catch{}try{clearInterval(R)}catch{}try{Ae.stop()}catch{}try{ee?.dispose()}catch{}e()}};Pe.value=T;let E=()=>{setTimeout(T,3e3).unref();try{z?.lifecycle.stop()}catch{T()}},D=Rn({getTui:()=>z??null,getSession:()=>N,dispatchAbort:()=>V({kind:`abort`}),clearTodoLayers:()=>{q.todoList.length!==0&&(q.todoList=[],z?.stores.tasks.setTasks([]),N.session.setTodoList([]))},markUserAborted:()=>{G.userAborted=!0},resetCtrlCCount:()=>{G.ctrlCCount=0},markRestartRequested:()=>{s=!0},stopTui:E,isBusy:()=>K()}),ne=pe,{historyStore:ie,inputHistory:oe,externalHistoryCommands:k}=await Jn(N,n.settings.get(`history`)?.external),A=fn({app:n,session:N,getTui:()=>I});p=A;let j,ue,fe,P,me={value:void 0};Ve(`startTui() begin`);let he=r(await y(n.workspaceDir,{readdir:e=>St(e,{withFileTypes:!0})})).map(e=>Q.t(e)),I=await Ie({stdin:process.stdin,stdout:process.stdout,modelName:ke(we),needsSetup:L.size===0,promptSuggestions:he,commands:Re,pluginInput:n.pluginInput,isImmediateCommand:e=>K()?de.has(e):ne.has(e),isInterruptCommand:e=>e===`abort`,isAgentBusy:K,isPaused:()=>N.isPaused,initialPath:te&&v>0?`/`:`/home`,shadow:n._shadow,welcome:{cwd:process.cwd(),version:Je,buildId:Ge,nickname:n.settings.get(`nickname`)||void 0,updateAvailable:void 0},onSessionSelect:e=>{M(`resume`,[e],P)},loadHistory:n.sessionRepoRef?.current?await(async()=>{let e=n.sessionRepoRef.current;if(!e)return;let r=await rn(e,N.id,!!t.continueSession);return e=>r.loadEarlier(e.limit)})():void 0,language:Be,themeRegistry:He,presetSelection:Ue,keybindingOverrides:We,permissionMode:n.getPermissionMode(),onFocusChange:e=>n.setTerminalFocus(e),...A.handlers,initialHistory:oe,externalHistoryCommands:k,residencyGovernor:n._residencyGovernor,resolveWholeFileDiff:async(e,t)=>{try{return await o(Qe(n.workspaceDir,e),t)}catch(e){return{error:e instanceof Error?e.message:String(e)}}},initialDrafts:g(N.session.getDrafts()??[]),initialRecentMentions:$n(n.settings.get(`recent_mentions`)??[]),onSigilSelect:e=>{let t=Zn(n.settings.get(`recent_mentions`)??[],Qn(e));n.settings.persist({recent_mentions:t}).catch(()=>{}),z?.stores.tasks.setRecentMentions($n(t))},...rr({app:n,getTui:()=>I,getTuiRef:()=>z,getSession:()=>N,getCliCtx:()=>P,historyStore:ie,getPasteBinder:()=>P.callbacks.pasteBinder}),onQueueSendNow:(e,t)=>{if(t===`memory`){fe(e);return}if(t===`bash`||t===`bash_async`){j(e,t===`bash`?`!`:`!!`);return}m?.(e,`send`,K()?`steer`:`send`)},onSubmit:m=async(e,t,r)=>{if(G.ctrlCCount=0,ue(e,t))return;if(N.isPaused&&N.resumeRun(),r===`steer`&&N.isBusy){G.latestSubmittedPrompt={text:e,mode:t};let n=se(await ae(e,{currentModelId:N.model?.id,applyModel:H,onSwitchFailed:e=>I.info.showToast(Q.t(`cmd.titleModel`),e)}),{currentEffort:N.thinkingLevel,applyEffort:e=>re(P,e),onInvalidLevel:e=>I.info.showToast(Q.t(`cmd.titleEffort`),Q.t(`cmd.effortUnknown`,{arg:e,levels:le.join(` / `)}))});if(Mn(n))return;let{id:r}=N.steer(n);I.pending.setPendingSteer(n,r);return}if(t===`memory`){await fe(e);return}if(t===`bash`||t===`bash_async`){j(e,t===`bash`?`!`:`!!`);return}let i=Kt(e),a=e,o=!1;if(i.isCommand){if(await M(i.command,i.args,P))return;n.firePluginActivationEvent?.(`onCommand:${i.command}`);let e=Le.find(e=>e.name===i.command);e&&(o=!0,a=await Ne(e.body,{args:i.args,workspaceDir:n.workspaceDir}))}let s=i.isCommand&&!o&&ce.has(i.command.toLowerCase());if(!s&&!F&&(!i.isCommand||o)){I.info.showToast(Q.t(`cmd.titleSetupRequired`),Q.t(`cmd.noModelConfigured`));return}if(q.todoList.length>0&&q.todoList.every(e=>e.status===`done`||e.status===`skipped`||e.status===`failed`)&&(q.todoList=[],I.stores.tasks.setTasks([]),N.session.setTodoList([])),K()&&(!i.isCommand||o)){I.engine.enqueueFollowUp(e,t),I.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`queue.dFollowUpToast`));return}if(s||(await Fe(),I.engine.pushEngineEvent({kind:`agentProcessing`,value:!0}),G.agentProcessing=!0,I.plugins.setCommands(ze())),G.userAborted=!1,a=await ae(a,{currentModelId:N.model?.id,applyModel:H,onSwitchFailed:e=>I.info.showToast(Q.t(`cmd.titleModel`),e)}),a=se(a,{currentEffort:N.thinkingLevel,applyEffort:e=>re(P,e),onInvalidLevel:e=>I.info.showToast(Q.t(`cmd.titleEffort`),Q.t(`cmd.effortUnknown`,{arg:e,levels:le.join(` / `)}))}),!Mn(a)){G.latestSubmittedPrompt={text:e,mode:t},G.retryMode||(G.errorRetryAttempt=0),G.retryMode=!1,$e.lastTasks=q.todoList.slice();try{a=await n.expandSigilChips(a,{skipPrefixes:new Set([`model`])}),(!i.isCommand||o)&&!G.retryMode&&(I.messages.echoUserInput(a,{pending:!0}),I.pending.setPendingEcho(a,t),n.settings.get(`first_prompt_submitted_at`)===void 0&&n.settings.persist({first_prompt_submitted_at:Date.now()}).catch(()=>{}));let e=a;G.streamedText=!1;let r=await U.handleInput(e);if(r.type===`exit`){Me(r);return}if(r.type===`help`){I.modal.openModal({kind:`helpViewer`,title:`Help`,lines:Yt(W,N.pinned,Q.t(`cmdDesc`,{returnObjects:!0})),onDismiss:()=>{}});return}r.type!==`noop`&&r.text&&!G.streamedText&&(r.type===`system`&&r.text.length<=80?I.info.showToast(Q.t(`cmd.titleInfo`),r.text):I.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:r.text}]})),r.type===`response`&&r.endReason&&(I.pending.clearPendingEcho(),r.notice&&I.info.showToast(Q.t(`cmd.titleInfo`),r.notice)),await Ht(r,{runTurn:e=>U.handleInput(e),onTurnResult:e=>e.type===`exit`?(Me(e),`exit`):(e.type!==`noop`&&e.type!==`help`&&e.text&&!G.streamedText&&I.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:e.text}]}),`continue`),askBudgetContinue:()=>new Promise(e=>{I.modal.openModal({kind:`select`,title:Q.t(`budget.exhaustedTitle`),layout:`buttons`,options:[{label:Q.t(`budget.continue`),value:`go`,color:`accent`},{label:Q.t(`budget.stop`),value:`stop`,color:`amber`}],onSelect:t=>e(t===`go`),onCancel:()=>e(!1)})}),onBudgetStopped:()=>{I.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`budget.stoppedNote`)}]})},beforeContinuationTurn:()=>{G.streamedText=!1}})}catch(r){I.pending.withdrawPendingEcho(),or({err:r,submitState:G,provider:N.model?.provider,rateLimitInfoRef:{get current(){return G.lastRateLimitInfo},set current(e){G.lastRateLimitInfo=e}},retryModeRef:{get current(){return G.retryMode},set current(e){G.retryMode=e}},errorRetryAttemptRef:{get current(){return G.errorRetryAttempt},set current(e){G.errorRetryAttempt=e}},ERROR_RETRY_MAX:b,ERROR_RETRY_INTERVAL_SECONDS:n.getResilienceConfig().errorRetry.intervalMs/1e3,handleSubmit:m,latestSubmittedPromptRef:{get current(){return G.latestSubmittedPrompt},set current(e){G.latestSubmittedPrompt=e}},text:e,mode:t,handleModel:xe,handleProviderAuth:Se,cliCtx:P,tui:I})}finally{G.agentProcessing=!1,G.userAborted=!1,I.engine.pushEngineEvent({kind:`agentProcessing`,value:!1}),I.plugins.setCommands(ze())}}},onInterrupt:()=>{let e=Date.now(),t=Ln(e,G.lastCtrlCTime,{shellRunning:!!G.shellChild,busy:K(),stopDialogOpen:D.isStopDialogOpen(),idleCtrlCCount:G.ctrlCCount});if(t!==`dedup`)switch(G.lastCtrlCTime=e,t){case`kill-shell`:G.shellChild.kill(`SIGTERM`),setTimeout(()=>{G.shellChild&&!G.shellChild.killed&&G.shellChild.kill(`SIGKILL`)},3e3);return;case`open-stop-dialog`:D.requestStop(`abort`);return;case`escalate-exit`:D.escalateToExit();return;case`exit-process`:E();return;case`hint-exit`:G.ctrlCCount++,setTimeout(()=>{G.ctrlCCount=0},800).unref(),I.info.showToast(Q.t(`cmd.titleExit`),Q.t(`cmd.pressCtrlCAgain`));return}},onShellAskAi:()=>{let e=z?.shell.getShellExecutionSnapshot();if(!e)return;let t=In(e);m?.(t,`send`,K()?`steer`:`send`)},onWithdrawPending:(e,t)=>{I.pending.withdrawPendingEcho(),I.pending.restoreInputText(e),G.agentProcessing&&(G.userAborted=!0,V({kind:`abort`}),I.info.showToast(Q.t(`cmd.titleAborted`),Q.t(`cmd.runAborted`)))},onWithdrawSteer:e=>{N.removeSteer(e)?I.pending.withdrawPendingSteer(e):D.requestStop(`abort`)},onStop:()=>{T()}});z=I,i&&(i.current=(e,t)=>{I.info.showToast(`Memory Conflict`,`Concurrent edit detected for ${e} — saved to ${t}`)}),Ve(`startTui() ready (first frame mounted)`),n.setUserAskRenderer(e=>en(I,e));let ye=Yn({gateway:()=>n.sessionManager.panelState,bridge:()=>I.pending,onError:(e,t)=>{n.logger?.debug?.({stage:e,error:t},`paste cache binding failed (non-fatal)`)}});Cn({app:n,tui:I}),Sn(n),n.listAllSessions().then(e=>{let t=N.id,n=e.filter(e=>e.status!==`archived`&&(e.entryCount??e.messageCount)>0&&e.id!==t).slice(0,10).map(e=>({id:e.id,title:e.title??e.id.slice(0,8),status:e.id===t?`busy`:`idle-cold`,lastActivityAt:e.updatedAt?new Date(e.updatedAt).toLocaleString():``,isCurrent:e.id===t,isPinned:e.pinned??!1,isArchived:e.status===`archived`,isReadOnly:e.writeLocked??!1}));I.stores.tasks.setSessionList(n)}).catch(()=>{});let{pollInterval:R,scheduler:Ae}=bn(n,{get value(){return N}},I,t.sessionUrl&&t.sessionToken?{sessionUrl:t.sessionUrl,sessionToken:t.sessionToken}:void 0);j=Nn({tui:I,app:n,submitState:G}),ue=Pn({agentProcessingRef:{get value(){return G.agentProcessing},set value(e){G.agentProcessing=e}},tui:I,requestStop:e=>D.requestStop(e)}),fe=Fn({app:n,tui:I}),wn({app:n,tui:I,session:N}),Tn({app:n,tui:I,getScheduler:()=>Ae});let Me=e=>{D.requestStop(e.restart?`exit-restart`:`exit`)};t.memoryRestartGrace&&n.memoryGovernor.markRestarted();let B=t.restartGeneration??0;B>=3&&I.info.pushNotification(Q.t(`cmd.titleFleetBudget`),Q.t(`cmd.restartChainDeep`,{generation:B}),`system`,`warning`),I.engine.pushEngineEvent({kind:`perf`,indicatorLevel:n.memoryGovernor.currentLevel,memory:n.memoryGovernor.sample()}),Xn({session:N,tui:I,retryAccelerate:O,setRateLimitInfo:e=>{G.lastRateLimitInfo=e},abortNow:()=>{D.abortNow()}});let qe=dn({getSession:()=>N,app:n,tui:I,projState:q,contextWindow:Te,currentModelId:De}),{recomputeBudget:Y,persistEditedFiles:Ye,persistSubagents:Xe,persistTurnCount:Ze,onContextCompacted:X}=qe;je=Y,Y(),n.editFileCallback=qe.editFileCallback,nr({app:n,tui:I,getSession:()=>N,setRestartResumePrompt:e=>{u=e},setRestartMemoryTriggered:e=>{l=e},handleExit:Me,onContextCompacted:X,recomputeBudget:Y}),n.registerInAppNotificationChannel((e,t,n)=>I.info.pushNotification(e,t,`system`,d(n))),n.setFollowUpPendingProbe(()=>I.engine.hasQueuedFollowUp());let $e=f(),et=tn({getSession:()=>N,app:n,tui:I,projState:q,redState:$e,recomputeBudget:Y,persistEditedFiles:Ye,persistSubagents:Xe,persistTurnCount:Ze,onContextCompacted:X,markStreamed:()=>{G.streamedText=!0}});me.value=et,P=xn({tui:I,app:n,themeRegistry:He,sessionRef:{get value(){return N},set value(e){N=e}},interactiveRef:{get value(){return U},set value(e){U=e}},regRef:{get value(){return W},set value(e){W=e}},slashCommandsRef:{get value(){return Re},set value(e){Re=e}},modelReadyRef:{get value(){return F},set value(e){F=e}},currentModelIdRef:{get value(){return Ee},set value(e){Ee=e}},currentLangRef:{get value(){return J},set value(e){J=e}},projState:q,agentProcessingRef:{get value(){return G.agentProcessing},set value(e){G.agentProcessing=e}},modelsRef:{get value(){return ge},set value(e){ge=e}},availableModelIds:L,restartRequestedRef:{get value(){return s},set value(e){s=!!e}},applyModel:H,persistAvailable:ve,refreshModelsNow:Ce,refreshSlashCommands:ze,events:et,redState:$e,agentMessagesToChatMessages:_e,PROVIDER_DISPLAY_NAMES:c,apiCredentialId:Oe,onContextCompacted:X}),P.callbacks.pasteBinder=ye,ye.load(N.id),I.plugins.setPluginRegistrations(n.getPluginRegistrations());let Z=await be.refresh();if(process.stderr.write(`[DEBUG] ftueSnapshot=${JSON.stringify(Z)}\n`),process.stderr.write(`[DEBUG] cfgLang=${Be} has_completed_onboarding=${n.settings.get(`has_completed_onboarding`)}\n`),z?.stores.tasks.setFtueStage(Z.stage),a(Z)&&Be===`auto`&&!n.settings.get(`has_completed_onboarding`)){let e=await I.modal.openModal({kind:`onboarding`,onLanguagePreview:e=>{let t=e===`auto`?w():e;_(t),I.lifecycle.setLanguage(t),J=t}});if(e.nickname&&n.settings.persist({nickname:e.nickname}).catch(()=>{}),e.language){let t=e.language===`auto`?w():e.language;_(t),I.lifecycle.setLanguage(t),J=t,n.settings.persist({language:e.language}).catch(()=>{})}n.settings.persist({has_completed_onboarding:!0}).catch(()=>{})}Z.recommendation.autoOpen&&M(`setup`,[],P);let tt=An();tt&&(ee=new jn({repoRoot:tt,currentBuildId:Ge,logger:n.logger,onStale:e=>{I.info.pushNotification(Q.t(`cmd.titleStaleBuild`),Q.t(`cmd.staleBuildMessage`,{current:Ge,latest:e}),`system`,`info`)}}),ee.start()),await On({tui:I,options:t,app:n,session:N,projState:q,resumedNote:S,resumed:h,updateCheckPromise:Ke,bg:A,events:et}),x.value&&I.info.showToast(Q.t(`crashGap.toastTitle`),Q.t(`crashGap.toastBody`,{lostTurns:x.value.lostTurns}))});let qe;if(n.codingSessionPool.autoPersist&&N.session.messages().length>0){let e=t.sessionUrl?` --session-url ${t.sessionUrl}`:``,n=t.sessionToken?` --session-token ${t.sessionToken}`:``;qe=`\n\x1b[2m${Q.t(`cmd.resumeContinueLabel`)}\x1b[0motto --continue ${N.id}${e}${n}\n`}return{restart:s?{sessionId:N.id,memoryTriggered:l,resumePrompt:u}:void 0,resumeHint:qe}}finally{p?.clearBgSubs(),p?.stopBgOutputPoll(),p?.stopBgSubagentPoll()}}async function cr(e){if(e.hasParentWorkspace()){let t=e.parentWorkspaceExisted,n=await ht({parentRoot:t.parentRoot,currentRoot:t.currentRoot,language:e.settings.get(`language`)});n===`exit`&&(process.stdout.write(`
|
|
12
|
-
`),process.exit(0)),n===`use_parent`?await e.adoptParentWorkspace():await e.createLocalWorkspace()}let t=
|
|
13
|
-
`),process.exit(0)),n===`trust`){
|
|
14
|
-
`)}}function
|
|
11
|
+
`).trimEnd()}catch{s=``}n({id:e,command:a.command,status:o,text:s}),o!==`running`&&u()};u(),V.get(e)&&(V.retain(e,!0),o=e),r(),a=setInterval(()=>{r()},500)},onBackgroundOutputClose:()=>{u()},onBackgroundSwitch:e=>{let t=n();d();let r=()=>{let n=H?.getMessages(e),r=H?.get(e),i=r?.agentName??``,a=V.get(e);a&&(i=a.title||i);let o=n?ge(n):[],s=H?.getTurns(e),c=H?.getStreamingText(e),l=Date.now(),u={id:e,title:i,messages:o,status:a?.status??`running`,diagnostics:r?at(ut(r),l):[],timeline:s?st(s,l):[],streamText:c};t.panes.switchToSubagentContext(u)};H?.pin(e),V.get(e)&&V.retain(e,!0),c=e,r(),s=setInterval(()=>{r()},500)},onBackgroundDelete:e=>{if(V.get(e)){V.remove(e);return}if(U.get(e)){U.remove(e);return}H.remove(e)},onSubagentExit:()=>{d(),n().panes.switchToSubagentContext(null)}}}}const pn=[{extensionId:`plugin-browser-use`,reasonKey:`capability.reasonWebApp`,detect:async e=>{let t=await e.packageDependencyNames();return[`react`,`vue`,`next`,`nuxt`,`svelte`,`vite`,`@angular/core`,`express`,`koa`,`fastify`].some(e=>t.has(e))?!0:e.hasFile(`index.html`)}},{extensionId:`plugin-mobile-use`,reasonKey:`capability.reasonMobile`,detect:async e=>{if(await e.hasFile(`AndroidManifest.xml`)||await e.hasFile(`build.gradle`)||await e.hasFile(`build.gradle.kts`)||await e.hasFile(`Info.plist`)||await e.hasFile(`Podfile`))return!0;let t=await e.packageDependencyNames();return t.has(`react-native`)||t.has(`expo`)}},{extensionId:`plugin-schedule`,reasonKey:`capability.reasonSchedule`,detect:async e=>{if(await e.hasFile(`crontab`))return!0;let t=await e.packageDependencyNames();return t.has(`node-cron`)||t.has(`node-schedule`)||t.has(`agenda`)}}];async function mn(e,t,n=pn){let r=[];for(let i of n){if(t.has(i.extensionId))continue;let n=!1;try{n=await i.detect(e)}catch{n=!1}n&&r.push({extensionId:i.extensionId,reasonKey:i.reasonKey})}return r}const hn=J(`@x-otto/cli:theme-preset-wiring`);function gn(e,t){let n={kind:`extension`,extensionId:t.pluginId};return e.register(n,{localId:t.localId,label:t.label,appearance:t.appearance,colors:t.colors,markdown:t.markdown})}function _n(e,t){let n=[];for(let r of t)try{n.push(gn(e,r))}catch(e){hn.warn({pluginId:r.pluginId,localId:r.localId,err:String(e)},`theme preset registration failed, skipped`)}return n}function vn(e){let t=rt();return _n(t,B(e.activePlugins())),t}function yn(e){return e.startsWith(`backend/`)?e.slice(8):e}function bn(e){let t=()=>({tasks:e.list(),runningTaskIds:[...e.getRunningTaskIds()],isFireOwner:e.isFireOwner(),fireOwnerFailureReason:e.fireOwnerFailureReason()});return{call:async(n,r)=>{let i=yn(n);switch(i){case`schedule.list`:return t();case`schedule.add`:{let t=r;try{let n=e.add({name:t.name,prompt:t.prompt,cronExpression:t.cronExpression,recurring:t.recurring,origin:`user`,target:t.target});return{ok:!0,taskId:n.id,name:n.name,target:n.target}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}case`schedule.update`:{let t=r,n={};return t.name!==void 0&&(n.name=t.name),t.prompt!==void 0&&(n.prompt=t.prompt),t.cronExpression!==void 0&&(n.cronExpression=t.cronExpression),t.enabled!==void 0&&(n.enabled=t.enabled),{ok:e.update(t.taskId,n)}}case`schedule.runNow`:{let{taskId:t}=r;return e.runNow(t),{ok:!0}}case`schedule.toggle`:{let{taskId:t,enabled:n}=r;return{ok:e.update(t,{enabled:n})}}case`schedule.cancel`:{let{taskId:t}=r;return e.cancel(t)}case`schedule.remove`:{let{taskId:t}=r;return{ok:e.remove(t)}}case`schedule.readLogs`:{let{taskId:t,limit:n}=r;return{entries:e.readFireLogs(t,n??20)}}case`schedule.parseCron`:{let{expr:e}=r;try{return{ok:!0,next:Bt(e).toISOString()}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}default:throw Error(`unknown schedule backend method: ${i}`)}},getSnapshot:t}}function xn(e){return t=>{let n=e.value;if(n.id!==t.boundSessionId||n.isPaused||n.status===`archived`)return!1;try{return n.prompt(t.prompt,{streamingBehavior:`followUp`}).catch(()=>{}),!0}catch{return!1}}}function Sn(e,t,n,r){let i=e.workspaceRef?.key??`default`,a=new Pt,o,s;if(e.storage.remoteSessionConfigured&&r){let e=async()=>({token:r.sessionToken});o=Rt({sessionUrl:r.sessionUrl,getAuth:e,wsKey:i}),s=Lt({sessionUrl:r.sessionUrl,wsKey:i,getAuth:e})}else o=zt(i),s=It(i);let c=new Ft({registry:a,store:o,ownership:s,jobRegistry:Ie,startJob:t=>({id:e.agentJobs.start({title:t.title,prompt:t.prompt,sessionId:t.sessionId,origin:t.origin}).id}),getSessionId:()=>t.value.id,notifySubscriber:(t,n)=>e.notifyPluginServiceSchedule({pluginId:t.pluginId,serviceId:t.serviceId},n),followUpCurrentSession:xn(t),retryBackoffMs:e.getResilienceConfig().schedule.retryBackoffMs});c.start().catch(e=>{console.error(`\x1b[3m\x1b[2m[schedule] scheduler failed to start: ${e instanceof Error?e.message:String(e)}\x1b[0m`)}),O(c),e.setScheduleService(c);let l=bn(c);e.panelBackendController.registerInProcessBackend(`plugin-schedule`,l.call);let u=setInterval(()=>{if(!n)return;let e=c.list().map(e=>({id:e.id,name:e.name,prompt:e.prompt,cronExpression:e.cronExpression,enabled:e.enabled,recurring:e.recurring,nextFireAt:e.nextFireAt,lastFiredAt:e.lastFiredAt,lastFireFailed:e.lastFireFailed,lastFireError:e.lastFireError,lastFireCancelled:e.lastFireCancelled}));n.stores.tasks.setScheduleTasks(e)},5e3);return u.unref(),{pollInterval:u,scheduler:c}}function Cn(e){let{tui:t,app:n,themeRegistry:r,sessionRef:i,interactiveRef:a,regRef:o,slashCommandsRef:s,modelReadyRef:c,currentModelIdRef:l,currentLangRef:u,projState:d,agentProcessingRef:p,modelsRef:m,availableModelIds:h,restartRequestedRef:g,applyModel:_,persistAvailable:v,refreshModelsNow:y,refreshSlashCommands:b,events:x,redState:S,agentMessagesToChatMessages:ee,PROVIDER_DISPLAY_NAMES:C,apiCredentialId:te,onContextCompacted:w}=e;return{tui:t,app:n,state:{get session(){return i.value},set session(e){i.value=e},get interactive(){return a.value},set interactive(e){a.value=e},get reg(){return o.value},set reg(e){o.value=e},get slashCommands(){return s.value},set slashCommands(e){s.value=e},get modelReady(){return c.value},set modelReady(e){c.value=e},get currentModelId(){return l.value},set currentModelId(e){l.value=e},get currentLang(){return u.value},set currentLang(e){u.value=e},get todoList(){return d.todoList},set todoList(e){d.todoList=e},get agentProcessing(){return p.value},set agentProcessing(e){p.value=e},get models(){return m.value},set models(e){m.value=e},get availableModelIds(){return h},get restartRequested(){return g.value},set restartRequested(e){g.value=!!e},themeRegistry:r},callbacks:{applyModel:_,persistAvailable:v,refreshModelsNow:y,registerAllTuiCommands:()=>{Zt(o.value)},refreshSlashCommands:b,attachSessionHandler:()=>x.attachSessionHandler(),restoreSwitchedSession:()=>{d.delegated.clear(),d.todoList=[],d.currentTurn=0,Object.assign(S,f()),t.stores.tasks.setTasks([],void 0),t.panes.clearEditedFiles(),t.plugins.clearSubagents(),A({session:i.value,projState:d,tui:t}),w()},resetCurrentTurn:()=>{d.currentTurn=0},onContextCompacted:w,sessionUnsub:()=>x.getSessionUnsub(),getLastProviderUsage:()=>x.getLastProviderUsage(),isWriteLeaseReadOnly:()=>x.isWriteLeaseReadOnly(),isRunPaused:()=>x.isRunPaused(),agentMessagesToChatMessages:ee,PROVIDER_DISPLAY_NAMES:C,apiCredentialId:te}}}function wn(e){e.setEcosystemSearch(async t=>{try{let{registries:n,warnings:r}=await Ce(e).loadAll();return{hits:Y(n.flatMap(e=>e.entries.map(t=>({entry:t,registry:e}))).map(e=>({text:e.entry.id,aliases:[e.entry.description,...e.entry.keywords??[]],payload:e})),t.join(` `),{maxResults:8}).map(e=>({id:e.item.payload.entry.id,description:e.item.payload.entry.description,capabilities:e.item.payload.entry.capabilities,sourceName:e.item.payload.registry.sourceName,stale:e.item.payload.registry.stale})),warnings:r}}catch{return}})}function Tn(e){let{app:t,tui:n}=e;t.setMcpStartupCallback(e=>{let r=[`HTTP_PROXY`,`HTTPS_PROXY`,`http_proxy`,`https_proxy`].find(e=>process.env[e]),i=r?process.env[r]:void 0,a=t.settings.get(`proxy`);i&&r&&!a?.url&&(Se(i,r),n.info.showToast(Q.t(`proxy.title`),Q.t(`proxy.envDetectedToast`,{source:r,value:i})))})}function En(e){let{app:t,tui:n,session:r}=e;n.plugins.registerArgumentSuggester(`model`,(e,n=20)=>Y(t.modelRegistry.getAll().filter(e=>e.id!==`__otto_setup__`).map(e=>({text:e.id,aliases:[e.name,e.provider],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload.id,description:e.item.payload.name})));let i=W(r.session.metadata().title,r.session.messages(),r.id);n.lifecycle.setTerminalTitle(i),n.stores.tasks.setSessionTitle(i)}function Dn(e){let{app:t,tui:n,getScheduler:r}=e;n.plugins.registerArgumentSuggester(`schedule`,(e,t=20)=>{let n=[`remove`,`run`,`enable`,`disable`],i=n.find(t=>e.toLowerCase().startsWith(`${t} `));if(!i)return Y([...n,`list`,`add`,`logs`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:t}).map(e=>({name:e.item.payload}));let a=r();if(!a)return[];let o=e.slice(i.length+1);return Y(a.list().map(e=>({text:e.id,aliases:[e.name],payload:e})),o,{maxResults:t}).map(e=>({name:`${i} ${e.item.payload.id}`,description:e.item.payload.name}))}),n.plugins.registerArgumentSuggester(`replay`,(e,n=20)=>Y(t.listSessions().map(e=>({text:e.id,aliases:e.title?[e.title]:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload.id,description:e.item.payload.title??e.item.payload.id.slice(0,8)}))),n.plugins.registerArgumentSuggester(`session`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`unlock `)?e.slice(7):e;return r===e?Y([{text:`unlock`,aliases:[],payload:`unlock`}],e,{maxResults:n}).map(e=>({name:e.item.payload,description:`Write-lease diagnostics/force-unlock`})):Y(t.listSessions().map(e=>({text:e.id,aliases:e.title?[e.title]:[],payload:e})),r,{maxResults:n}).map(e=>({name:`unlock ${e.item.payload.id}`,description:e.item.payload.title??e.item.payload.id.slice(0,8)}))}),n.plugins.registerArgumentSuggester(`registry`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`remove `)?e.slice(7):e;return r===e?Y([`list`,`add`,`remove`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload})):Y(Ce(t).listSources().filter(e=>!e.builtin).map(e=>({text:e.name,aliases:[e.url],payload:e})),r,{maxResults:n}).map(e=>({name:`remove ${e.item.payload.name}`,description:e.item.payload.url}))}),n.plugins.registerArgumentSuggester(`trust`,(e,n=20)=>{let r=e.toLowerCase().startsWith(`plugin `)?e.slice(7):e;return r===e?Y([`status`,`trust`,`untrust`,`plugin`].map(e=>({text:e,aliases:[],payload:e})),e,{maxResults:n}).map(e=>({name:e.item.payload})):Y(ve({cwd:t.workspaceDir??process.cwd(),homedir:z()}).map(e=>({text:e.id,aliases:[],payload:e})),r,{maxResults:n}).map(e=>({name:`plugin ${e.item.payload.id}`,description:e.item.payload.scope}))})}function On(e){let t=e[e.length-1];if(t?.type===`message`&&t.message?.role===`user`)return{parentId:t.parentId}}function kn(e,t){!t||!t.newer||(t.forced?(e.info.pushNotification(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateNotifForced`,{latest:t.latest,current:t.current}),`version`,`error`),e.stores.tasks.setForcedUpgrade(Q.t(`cmd.updateForcedBanner`,{latest:t.latest,current:t.current})),e.stores.notification.setPulseSurvey(null)):(e.info.pushNotification(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateNotifAvailable`,{latest:t.latest,current:t.current}),`version`,`info`),e.info.showToast(Q.t(`cmd.titleUpdate`),Q.t(`cmd.updateToast`,{latest:t.latest}))))}async function An(e){let{tui:n,options:r,app:i,session:a,projState:o,resumedNote:s,resumed:c,updateCheckPromise:l,bg:u,events:d}=e;if(s&&t({resumedNote:s,isFound:!!c,session:a,projState:o,tui:n}),r.resumePrompt&&c)if(i.memoryGovernor.sample().level===`critical`)n.info.showToast(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureResumeAbortedMessage`));else{let e=On(a.session.branchEntries());e&&(e.parentId&&a.session.branch(e.parentId),a.prompt(r.resumePrompt).catch(e=>{i.logger.warn({err:e instanceof Error?e.message:String(e)},`[memory-governor] auto-resume prompt failed`),n.info.showToast(Q.t(`cmd.titleError`),Q.t(`cmd.memoryPressureResumeFailedMessage`))}))}l.then(e=>kn(n,e)),u.setBgUnsubs(d.bgUnsubs),d.attachSessionHandler(),jn(n,i)}function jn(e,t){h(n=>{if(n.status!==`needs-input`)return;let r=n.id.slice(0,8),i=t.listSessions().find(e=>e.id===n.id)?.title??r;e.info.pushNotification(`session needs input`,`Background session '${i}' (${r}) requires your input (/resume ${r})`,`system`,`warning`)}),t.hookRegistry.on(`session.deleted`,`rfc234-background-cleanup`,e=>{j(e.sessionId)})}function Mn(e){let t=e??Qe(import.meta.url);t=Ye(t);let n=t===`/`?t:`/`;for(;t!==n;){try{if(Ze(t+`/.git`))return t}catch{}t=Ye(t)}try{if(Ze(n+`/.git`))return n}catch{}}var Nn=class{repoRoot;currentBuildId;checkIntervalMs;onStale;logger;lastNotifiedBuildId=void 0;disposed=!1;timer;activeChild;constructor(e){this.repoRoot=e.repoRoot,this.currentBuildId=e.currentBuildId,this.checkIntervalMs=e.checkIntervalMs??6e5,this.onStale=e.onStale,this.logger=e.logger}start(){this.disposed||this.scheduleNext()}dispose(){if(this.disposed=!0,this.timer&&=(clearTimeout(this.timer),void 0),this.activeChild){try{this.activeChild.kill()}catch{}this.activeChild=void 0}this.lastNotifiedBuildId=void 0}scheduleNext(){this.disposed||(this.timer=setTimeout(()=>{this.timer=void 0,this.performCheck().then(()=>{this.scheduleNext()})},this.checkIntervalMs),this.timer.unref())}performCheck(){return new Promise(e=>{if(this.disposed){e();return}let t=we(`git`,[`rev-list`,`--count`,`HEAD`],{cwd:this.repoRoot,timeout:5e3},(t,n)=>{if(this.activeChild=void 0,t){this.logger?.warn({err:t instanceof Error?t.message:String(t)},`[stale-build-detector] git rev-list failed`),e();return}let r=n.trim(),i=parseInt(r,10);if(!Number.isFinite(i)){this.logger?.warn({raw:r},`[stale-build-detector] failed to parse git output as number`),e();return}if(i>this.currentBuildId&&i!==this.lastNotifiedBuildId){this.lastNotifiedBuildId=i;try{this.onStale?.(i)}catch(e){this.logger?.warn({err:e instanceof Error?e.message:String(e)},`[stale-build-detector] onStale callback threw`)}}e()});this.activeChild=t,t.on(`error`,()=>{this.activeChild=void 0})})}};function Pn(e){return e.trim().length===0}function Fn(e){let{tui:t,app:n,submitState:r}=e;return(e,i=`!!`)=>{let a=e.trim();if(!a)return;let o=Re(a);if(!o.safe){t.info.showToast(Q.t(`cmd.titleShell`),Q.t(`cmd.dangerousBlocked`,{reason:o.reason})),t.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`cmd.dangerousBlockedDetail`,{reason:o.reason,cmd:a})}]});return}t.messages.echoUserInput(`${i} ${a}`),t.shell.startShellExecution(a),r.shellChild=Te(a,{shell:!0,cwd:n.workspaceDir,stdio:[`ignore`,`pipe`,`pipe`],env:Le()}),K.registerChild({command:a,args:[],owner:{type:`cli-shell`,id:`!!`},category:`shell`,lifecycle:`evictable`,cwd:n.workspaceDir},r.shellChild),r.shellChild.stdout.on(`data`,e=>{t.shell.appendShellOutput(e.toString(`utf-8`))}),r.shellChild.stderr.on(`data`,e=>{t.shell.appendShellOutput(e.toString(`utf-8`))}),r.shellChild.on(`close`,(e,n)=>{r.shellChild=null,n?t.shell.finishShellExecution(null,void 0,!0):t.shell.finishShellExecution(e)}),r.shellChild.on(`error`,e=>{r.shellChild=null,t.shell.finishShellExecution(null,`\nError: ${e.message}`)})}}function In(e){let{agentProcessingRef:t,tui:n,requestStop:r}=e;return(e,i)=>{let a=Kt(e);return a.isCommand&&a.command.toLowerCase()===`abort`&&i===`send`?(t.value?r(`abort`):n.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.noRunningTask`)),!0):!1}}function Ln(e){let{app:t,tui:n}=e;return async e=>{let r=e.trim();if(!r)return;if(!t.storage.autoMemory){n.info.showToast(Q.t(`cmd.titleMemory`),Q.t(`cmd.memoryDisabled`));return}let a=await i(r,process.env.OTTO_MEMORY_LLM_NAMING===`1`?t.completeText:void 0);await t.storage.autoMemory.record(a),n.messages.echoUserInput(`# ${r}`),n.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`cmd.memorySaved`,{name:a.name})}]})}}function Rn(e){let t=e.terminated===!0?Q.t(`shell.askAiTerminated`):e.exitCode===null?Q.t(`shell.unknownError`):Q.t(`shell.exitCode`,{code:e.exitCode}),n=e.output.length>5e4?`${e.output.slice(0,5e4)}\n${Q.t(`shell.truncated`)}`:e.output;return Q.t(`shell.prompt`,{command:e.command,errorLabel:t,output:n})}function zn(e,t,n){return e-t<50?`dedup`:n.shellRunning?`kill-shell`:n.busy?n.stopDialogOpen?`escalate-exit`:`open-stop-dialog`:n.idleCtrlCCount+1>=2?`exit-process`:`hint-exit`}function Bn(e){let{getTui:t,getSession:n,dispatchAbort:r,clearTodoLayers:i,markUserAborted:a,resetCtrlCCount:o,markRestartRequested:s,stopTui:c,isBusy:l}=e,u=null,d=()=>u!==null&&t()?.info.getCurrentPath()===`/dialog/confirm`,f=()=>{a(),o(),r(),i()},p=e=>{e&&s(),a(),o();try{r()}catch{}c()},m=e=>{if(e===`abort`)return{title:Q.t(`confirm.abortConfirmTitle`),message:Q.t(`confirm.abortConfirmMessage`),confirmLabel:Q.t(`common.abortButton`),extraLabel:Q.t(`common.pauseButton`),onConfirm:()=>{f(),t()?.info.showToast(Q.t(`cmd.titleAborted`),Q.t(`cmd.runAborted`))}};let n=e===`exit-restart`;return{title:n?Q.t(`confirm.exitRestartConfirmTitle`):Q.t(`confirm.exitConfirmTitle`),message:Q.t(`confirm.exitConfirmMessage`),confirmLabel:n?Q.t(`common.abortAndRestartButton`):Q.t(`common.abortAndExitButton`),extraLabel:void 0,onConfirm:()=>{p(n)}}},h=e=>{let r=t();if(!r)return;let i=m(e);u=e,r.modal.openModal({kind:`confirm`,title:i.title,message:i.message,confirmLabel:i.confirmLabel,confirmColor:`amber`,extraLabel:i.extraLabel,extraColor:`accent`,dangerous:!0,onConfirm:()=>{u=null,i.onConfirm()},onCancel:()=>{u=null},onExtra:i.extraLabel?()=>{u=null,n().pauseRun()?t()?.info.showToast(Q.t(`cmd.titlePaused`),Q.t(`cmd.runWillPauseAfterTurn`)):t()?.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`cmd.noRunningTaskToPause`))}:void 0})};return{requestStop:e=>{if(!t()){e===`abort`?f():p(e===`exit-restart`);return}if(e!==`abort`&&!l()){p(e===`exit-restart`);return}h(e)},isStopDialogOpen:d,escalateToExit:()=>{let e=t();!e||!d()||(h(`exit`),e.modal.resolveConfirm(!0))},abortNow:f}}async function Vn(e,t,n){if(n){let n=t.settings.get(`model`);if(typeof n==`string`&&n&&e.model?.id!==n){let r=t.modelRegistry.find(n);r&&await t.providerRegistry.hasCredential(r.provider)&&(e.model=r,t.storage.memory?.reconfigure?.({contextWindow:r.contextWindow,maxOutput:r.maxOutputTokens}))}}{let n=t.settings.get(`thinking_level`),r=[`low`,`medium`,`high`,`xhigh`,`max`],i=n===`minimal`?`low`:n;typeof i==`string`&&r.includes(i)&&(e.thinkingLevel=i)}}var Hn=class{entries=[];filePath;constructor(e,t=Z(We,`sessions`)){this.filePath=Z(t,`${e}.history.json`)}list(e){return this.entries.slice(-(e??100))}append(e){e.trim()&&(this.entries.push(e),this.entries.length>100&&(this.entries=this.entries.slice(-100)))}hydrate(e){this.entries=e.slice(-100)}async persist(){if(qe())return;let e=JSON.stringify(this.entries,null,2),t=`${this.filePath}.tmp`;try{await yt(Ye(this.filePath),{recursive:!0}),await Tt(t,e,`utf-8`),await St(t,this.filePath)}catch(e){throw await wt(t).catch(()=>{}),e}}async load(){try{let e=await bt(this.filePath,`utf-8`),t=JSON.parse(e);return Array.isArray(t)&&t.every(e=>typeof e==`string`)?(this.entries=t.slice(-100),this.entries):[]}catch{return[]}}};const Un={[nt]:e=>pt(e),[$e]:e=>dt(e),[tt]:e=>ft(e)};function Wn(){let e=process.env.SHELL??``,t=z(),n=process.env.HISTFILE;return e.includes(`fish`)?[{id:tt,path:Z(t,`.local/share/fish/fish_history`)},{id:tt,path:Z(t,`.config/fish/fish_history`)}]:e.includes(`bash`)?[{id:$e,path:n?.startsWith(`~`)?Z(t,n.slice(2)):n??Z(t,`.bash_history`)}]:e.includes(`zsh`)||!e?[{id:nt,path:n?.startsWith(`~`)?Z(t,n.slice(2)):n??Z(t,`.zsh_history`)}]:[]}function Gn(e){let t=e?.sources?.filter(e=>e?.enabled!==!1&&!!e?.id&&!!e?.path);if(t&&t.length>0){let e=z();return t.map(t=>({id:t.id,path:Kn(t.path,e)}))}return Wn()}function Kn(e,t){return e.startsWith(`~/`)?Z(t,e.slice(2)):e===`~`?t:e}async function qn(e){try{return await vt(e),!0}catch{return!1}}async function Jn(e,t){let n=Un[e.id];if(!n||!await qn(e.path))return[];try{return n(await bt(e.path,`utf8`)).slice(-t)}catch{return[]}}async function Yn(e){if(e?.enabled!==!0)return[];let t=e.maxEntries??2e3,n=Gn(e),r=new Set,i=[];for(let e of n){if(r.has(e.path))continue;r.add(e.path);let n=await Jn(e,t);i.push(...n)}return i.slice(-t)}async function Xn(e,t){let n=new Hn(e.id);return{historyStore:n,inputHistory:await n.load().then(t=>{if(t.length>0)return t;let r=e.session.getInputHistory();return r&&r.length>0?(n.hydrate(r),n.persist().catch(()=>{}),e.session.setInputHistory([]),r):[]}),externalHistoryCommands:t?.enabled===!0?it(await Yn(t)):void 0}}function Zn(e){let t=(t,n)=>{e.onError?.(t,n)},n=async n=>{let r=e.gateway(),i=e.bridge();if(!(!r||!i))try{let e=await r.getPaste(n);i.hydratePaste({entries:e.entries,nextId:e.nextId})}catch(e){t(`load`,e);try{i.hydratePaste(null)}catch{}}},r=async n=>{let r=e.gateway(),i=e.bridge();if(!(!r||!i))try{let e=i.exportPaste();if(!e)return;await r.setPaste(n,{sessionId:n,entries:e.entries,nextId:e.nextId})}catch(e){t(`save`,e)}};return{load:n,save:r,async switchTo(e,t){e!==t&&(e!==void 0&&await r(e),await n(t))},async fork(n,r){let i=e.gateway(),a=e.bridge();if(!(!i||!a))try{let e=a.exportPaste()??await i.getPaste(n);await i.setPaste(r,{sessionId:r,entries:e.entries,nextId:e.nextId})}catch(e){t(`fork`,e)}}}}function Qn(e){let{session:t,tui:n,retryAccelerate:r,setRateLimitInfo:i,abortNow:a}=e;t.coreAgent.on(`stream.retry`,({attempt:e,maxRetries:t,delayMs:i,reason:o})=>{n.engine.showRetryDialog(e,t,i,r,()=>{n.engine.clearRetryDialog()},o,()=>{a()})}),t.coreAgent.on(`rate.limit.exhausted`,({limitType:e,resetsAt:t})=>{n.engine.clearRetryDialog(),i({limitType:e,resetsAt:t})}),t.coreAgent.on(`lifecycle.tool.completed.crossBoundary`,({toolName:e,result:t})=>{let r=Q.t(`cmd.titleBackgroundTask`),i=t.isError?Q.t(`cmd.lifecycleCrossBoundaryFailed`,{toolName:e}):Q.t(`cmd.lifecycleCrossBoundaryDone`,{toolName:e});n.info.showToast(r,i)})}function $n(e,t){let n=e=>`${e.kind}\u0000${e.label}`,r=n(t);return[t,...e.filter(e=>n(e)!==r)].slice(0,5)}function er(e){return{label:e.label,value:e.value,kind:e.kind,description:e.description}}function tr(e){return e.map(e=>({label:e.label,value:e.value,kind:e.kind,description:e.description,source:`recent`}))}function nr(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0?r:t}function rr(e,t){let n=process.env[e];if(!n)return t;let r=Number(n);return Number.isFinite(r)&&r>0&&Number.isInteger(r)?r:t}function ir(e){let{app:t,tui:n,getSession:r,setRestartResumePrompt:i,setRestartMemoryTriggered:a,handleExit:o,onContextCompacted:s,recomputeBudget:c}=e,l=!1,u=0,d,f=!1,p=0,m=!1,h=nr(`OTTO_MEMORY_CRITICAL_NOTIFY_INTERVAL_MS`,18e5),g=rr(`OTTO_MEMORY_CRITICAL_NOTIFY_ESCALATION_CYCLES`,4),_,v=()=>{let e=r();if(e.isBusy){let t=e.session.messages(),n=t[t.length-1];if(n?.role===`user`&&!n.internal){let e=S(n.content);e&&i(e)}}a(!0),o({type:`exit`,restart:!0})},y=()=>{_&&=(clearInterval(_),void 0),p=0,m=!1};t.memoryGovernor.setCallbacks({onWarning:()=>{r().compactNow().then(e=>{e.compacted&&(n.info.showToast(Q.t(`cmd.titleAutoCompact`),Q.t(`compact.edResult`,{before:e.before,after:e.after})),s(),c())}).catch(e=>{let r=e instanceof Error?e.message:String(e);t.logger.warn({err:r},`[memory-governor] compactNow (soft degrade) failed`),n.info.showToast(Q.t(`cmd.titleAutoCompact`),Q.t(`cmd.autoCompactFailed`,{msg:r}))})},onCritical:e=>{if(l){n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),`system`,`info`);return}n.info.isFullScreenPaneActive()&&(u++,d??=Date.now(),u<3&&Date.now()-d<300*1e3)||(u=0,f=!0,n.modal.openModal({kind:`confirm`,title:Q.t(`cmd.titleMemoryPressure`),message:Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),confirmLabel:Q.t(`cmd.memoryPressureRestartNow`),cancelLabel:Q.t(`cmd.memoryPressureRemindLater`),confirmColor:`amber`,extraLabel:Q.t(`cmd.memoryPressureSuppress`),onConfirm:()=>{f=!1,y(),v()},onCancel:()=>{f=!1},onExtra:()=>{f=!1,l=!0}}))},onCriticalDuringGrace:e=>{n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:e.usedPct.toFixed(0)}),`system`,`warning`)},onCriticalTimeout:e=>{if(f){f=!1,v();return}let i=()=>{p++,n.info.pushNotification(Q.t(`cmd.titleMemoryPressure`),Q.t(`cmd.memoryPressureMessage`,{usedPct:t.memoryGovernor.sample().usedPct.toFixed(0)}),`system`,`warning`),!m&&p>=g&&(m=!0,r().compactNow().catch(e=>{let n=e instanceof Error?e.message:String(e);t.logger.warn({err:n},`[memory-governor] critical-unattended-escalation compactNow failed`)}),t.storage.traceStore?.append(r().id,{ts:Date.now(),sessionId:r().id,kind:`lifecycle`,node:`critical-unattended-escalation`,payload:{usedPct:e.usedPct,cycles:p}}).catch(e=>{t.logger.warn({err:e instanceof Error?e.message:String(e)},`[memory-governor] critical-unattended-escalation trace append failed`)}))};_||(i(),_=setInterval(i,h),_.unref?.())},onLevelChange:e=>{e!==`critical`&&(u=0,d=void 0,y()),n.engine.pushEngineEvent({kind:`perf`,indicatorLevel:e,memory:t.memoryGovernor.sample()})}}),t.fleetMonitor.setCallbacks({onBudgetExceeded:e=>{n.info.pushNotification(Q.t(`cmd.titleFleetBudget`),Q.t(`cmd.fleetBudgetExceeded`,{processCount:e.processCount,totalRssMb:e.totalRssMb}),`system`,`warning`)}})}function ar(e){let{app:t,getTui:n,getTuiRef:r,getSession:i,getCliCtx:a,historyStore:o}=e;return{onCyclePermissionMode:()=>{let e=n(),r=s(t.getPermissionMode());e.stores.tasks.setPermissionMode(r),e.info.showToast(Q.t(`cmd.titlePermission`),Q.t(`pref.permModeSwitched`,{label:Q.t(`pref.permModeLabel`,{context:r})})),t.setPermissionMode(r)},onHistoryPush:t=>{try{o.hydrate([...t]),o.persist().catch(()=>{})}catch{}e.getPasteBinder?.()?.save(i().id)},onDraftSave:e=>{let n=i(),a=n.session.getDrafts()??[],o=m(void 0,e,a),s=p([...a,o]);n.session.setDrafts(s),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(g(s))},onDraftDelete:e=>{let n=i(),a=(n.session.getDrafts()??[]).filter(t=>t.id!==e);n.session.setDrafts(a),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(g(a))},onDraftDeleteMany:e=>{let n=i(),a=new Set(e),o=(n.session.getDrafts()??[]).filter(e=>!a.has(e.id));n.session.setDrafts(o),t.sessionManager.save(n.id).catch(()=>{}),r()?.stores.tasks.setDrafts(g(o))},onA2uiAction:(e,t,n)=>{N(`a2ui-action`,n?[e,t,JSON.stringify(n)]:[e,t],a())},onPerfRefresh:()=>{N(`perf`,[],a())},onProxySubmitUrl:e=>{N(`proxy`,[e],a())},onProxyToggleEnabled:()=>{N(`proxy`,[t.settings.get(`proxy`)?.enabled===!1?`on`:`off`],a())},onProxyClear:()=>{N(`proxy`,[`clear`],a())},onProxyTest:()=>{N(`proxy`,[`test`],a())}}}function or(e){return{...sr(e),pluginSource:e.pluginSource,intervalSeconds:e.errorRetryIntervalSeconds}}function sr(e){let{msg:t,provider:n,authError:r,isRefreshFailed:i,unsupported:a,rateLimit:o,rateLimitInfo:s,getErrorRetryAttempt:c,incErrorRetryAttempt:l,errorRetryMax:u,retryQueued:d,resetAndRetry:f,cancelRetry:p,switchModelThenRetry:m,goToAuth:h}=e;if(s)return s.resetsAt===void 0?{reason:t,attempt:0,max:u,mode:`manual`,limitType:s.limitType,actions:[{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p}:{reason:t,attempt:0,max:u,mode:`resetsAt`,resetsAt:s.resetsAt,limitType:s.limitType,actions:[{kind:`retryNow`,label:Q.t(`error.retryNow`),run:d},{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m}],onExpired:d,onCancel:p};if(r)return{reason:i?Q.t(`cmd.authRefreshFailed`,{ps:n?` (${n})`:``,ls:n?` ${n}`:``}):Q.t(`cmd.authFailed`,{ps:n?` (${n})`:``,ls:n?` ${n}`:``}),attempt:c(),max:u,mode:`manual`,actions:[{kind:`login`,label:Q.t(`model.goToLoginButton`),run:h},{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p};if(a)return{reason:Q.t(`cmd.modelNotSupported`),attempt:c(),max:u,mode:`manual`,actions:[{kind:`switchModel`,label:Q.t(`error.switchModel`),run:m},{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:d}],onExpired:()=>{},onCancel:p};let g=l(),_=g>u;return{reason:o?Q.t(`cmd.rateLimitedRetriesExhausted`):Q.t(`cmd.requestFailed`,{msg:t}),attempt:Math.min(g,u),max:u,mode:`auto`,exhausted:_,actions:[{kind:`retryNow`,label:Q.t(`retry.nowButton`),run:_?f:d}],onExpired:_?()=>{}:d,onCancel:p}}function cr(e){let{err:t}=e,n=t instanceof Error?t.message:String(t),r=t?.code===`AGENT_ABORTED`;if(!(e.submitState.userAborted||r)){let r=e.provider,i=t?.code,a=t?.pluginSource,{authError:o,isRefreshFailed:s,unsupported:c,rateLimit:l,pluginSource:u}=x(n,i,a),d=e.rateLimitInfoRef.current;e.rateLimitInfoRef.current=void 0;let f=(()=>{let t=e.cliCtx,n=t?.app?.storage?.traceStore,r=t?.state?.session;if(!n||!r)return null;let i=r.session.getTurnCount();return{traceStore:n,sessionId:r.id,...i===void 0?{}:{turn:i}}})(),p=()=>{f&&E(f,{attempt:e.errorRetryAttemptRef.current+1,max:e.ERROR_RETRY_MAX,mode:d?`resetsAt`:o||c?`manual`:`auto`,reason:n.slice(0,120)}),e.retryModeRef.current=!0;let t=e.latestSubmittedPromptRef?.current,r=e.tui.engine.takeLastQueuedFollowUp?.(),i=t!=null&&t.text!==e.text,a=i?t.text:r?.text??e.text,s=i?t.mode:r?.mode??e.mode;a===e.text&&!i&&r==null&&e.retryLastRound?.()||queueMicrotask(()=>e.handleSubmit?.(a,s,`send`))};e.tui.engine.showErrorRetry(or({msg:n,provider:r,authError:o,isRefreshFailed:s,unsupported:c,rateLimit:l,rateLimitInfo:d,pluginSource:u,getErrorRetryAttempt:()=>e.errorRetryAttemptRef.current,incErrorRetryAttempt:()=>++e.errorRetryAttemptRef.current,errorRetryMax:e.ERROR_RETRY_MAX,errorRetryIntervalSeconds:e.ERROR_RETRY_INTERVAL_SECONDS,retryQueued:p,resetAndRetry:()=>{f&&me(f),e.errorRetryAttemptRef.current=0,p()},cancelRetry:()=>{f&&he(f,{attempt:e.errorRetryAttemptRef.current}),e.errorRetryAttemptRef.current=0},switchModelThenRetry:()=>{e.handleModel([],e.cliCtx,{afterSwitch:p})},goToAuth:()=>{e.handleProviderAuth([r??``].filter(Boolean),e.cliCtx)}}))}}async function lr(t,n,i){let s=!1,l=!1,u,p;try{let m=n.settings.get(`permission_mode`);(m===void 0||m===`auto`)&&await n.settings.update({permission_mode:`confirm`});let h=t.continueSession?n.getSession(t.continueSession)??await n.sessionManager.restore(t.continueSession)??void 0:void 0,v=h?h.session.buildContext().messages.filter(e=>{let t=e.role;return t===`user`||t===`assistant`}).length:0,x={value:h?n.sessionManager.consumeCrashGap(h.id):void 0},S=t.continueSession?h?Q.t(`cmd.resumeRestored`,{idShort:t.continueSession.slice(0,8),count:v}):Q.t(`cmd.resumeNotFound`,{id:t.continueSession}):void 0,te=!!(t.continueSession&&h),E=!!(t.model||n.settings.get(`model`)||n.settings.get(`model_slots`)?.default),O={skip:!1},k=await n.hydrateModelCache().catch(()=>new Set),ae=!h&&n.modelRegistry.getAll().length===0,A=`__otto_setup__`;ae&&n.modelRegistry.register({id:A,name:`Setup required`,provider:`otto`,api:`otto`,baseUrl:``,reasoning:!1,input:[`text`],contextWindow:32e3,maxOutputTokens:4e3});let j=ae?!1:E,P=h??await n.createSession({interactive:!0,retryAccelerate:O,...j?{}:{model:n.modelRegistry.getAll()[0]}});await Vn(P,n,!!h);let I=j||te,me={get value(){return I},set value(e){I=e}},he=n.modelRegistry.getAll().filter(e=>e.id!==A).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow})),R=new Set([...k,...n.getSessionAvailableModels(P.id)]),_e=()=>n.setSessionAvailableModels(P.id,[...R]);_e();let ve=R.size===0,ye=new pe(b({modelRegistry:n.modelRegistry,authStore:n.authStore,settings:n.settings,selectedModelId:()=>P.model?.id,isModelUsable:Et(n.authStore,`delegation`),isModelUsableInMainSession:Et(n.authStore,`main-session`)})),Se=async e=>{let t=await n.refreshModels().catch(()=>[]);he=n.modelRegistry.getAll().filter(e=>e.id!==A).map(e=>({id:e.id,name:e.name,provider:e.provider,api:e.api,strengths:e.strengths??[],contextWindow:e.contextWindow}));for(let e of t)if(e.status===`ok`)for(let t of e.availableIds??[])R.add(t);he.length>0&&n.modelRegistry.getAll().some(e=>e.id===A)&&n.modelRegistry.unregister(A),_e();let r=R.size===0;B?.stores.tasks.setNeedsSetup(r);let i=await ye.refresh().catch(()=>null);if(i&&B?.stores.tasks.setFtueStage(i.stage),ve&&!r&&(ve=!1,B?.info.showToast(Q.t(`cmd.titleSetupReady`),Q.t(`cmd.setupReadyMessage`))),e){let n=t.filter(e=>e.status===`ok`);e(n.length>0?Q.t(`cmd.modelsRefreshed`,{summary:n.map(e=>`${e.provider} ${e.total}`).join(` · `)}):Q.t(`cmd.modelsRefreshedEmpty`))}};Se();let Ce=I?P.model?.id:void 0,z=n.modelRegistry.getAll().filter(e=>e.id!==A).find(e=>e.id===Ce)?.contextWindow??0,we={get value(){return z},set value(e){z=e}},Te=Ce,Ee={get value(){return Te},set value(e){Te=e}},Oe=e=>ee(n,e,P.thinkingLevel),B,ke={get value(){return B},set value(e){B=e}},Ae,Me={get value(){return Ae},set value(e){Ae=e}},V={value:void 0},H={value:t},U=e=>{switch(e.kind){case`steer`:P.steer(e.input);break;case`abort`:W.abort();break;case`pauseAfterTurn`:P.pauseRun();break;case`resumeRun`:P.resumeRun();break}},Ne=re({modelReady:me,currentModelId:Ee,contextWindow:we,tuiRef:ke,pushBudgetNow:Me,app:n,getSession:()=>P,options:H,fmtDisplayModel:Oe,onEngineModelAction:U}),Pe=T({getSession:()=>P,app:n,tuiRef:ke,options:H,fmtDisplayModel:Oe,applyModel:Ne,onExitSession:()=>V.value?.()}),W=new e(P,{models:he,currentModel:Ce,onModelChange:Ne}),{startTui:Fe}=await import(`@x-otto/tui`),G=W.getRegistry();Zt(G);let Ie=le(G,n),K={agentProcessing:!1,ctrlCCount:0,lastCtrlCTime:0,userAborted:!1,shellChild:null,streamedText:!1,retryMode:!1,errorRetryAttempt:0,lastRateLimitInfo:void 0,latestSubmittedPrompt:void 0},q=()=>Ut(P.isBusy,K.agentProcessing),Le=Xt(G,K.agentProcessing,ue,Q.t(`cmdDesc`,{returnObjects:!0}),P.pinned,P.isPaused),Re=()=>(Le=Xt(G,K.agentProcessing,ue,Q.t(`cmdDesc`,{returnObjects:!0}),P.pinned,P.isPaused),Le);F(n),M(n,R),D(n),de(n);let J=Ot(),Y=n.settings.get(`language`)??`auto`,Be=Y===`auto`?w():Y,Ve=vn(n),He=n.settings.get(`theme_preset`),We=n.settings.get(`keybinding_overrides`);_(Be);let Ge=C({currentVersion:L(),lastCheck:n.settings.get(`last_update_check`),autoCheck:n.settings.get(`auto_update_check`)!==!1,persistLastCheck:()=>n.settings.persist({last_update_check:Date.now()})});await new Promise(async e=>{let m,b=n.getResilienceConfig().errorRetry.maxAttempts,ee,C=!1,T=()=>{if(!C){C=!0;try{p?.clearBgSubs()}catch{}try{p?.stopBgOutputPoll()}catch{}try{p?.stopBgSubagentPoll()}catch{}try{clearInterval(z)}catch{}try{ke.stop()}catch{}try{ee?.dispose()}catch{}e()}};V.value=T;let E=()=>{setTimeout(T,3e3).unref();try{B?.lifecycle.stop()}catch{T()}},D=Bn({getTui:()=>B??null,getSession:()=>P,dispatchAbort:()=>U({kind:`abort`}),clearTodoLayers:()=>{J.todoList.length!==0&&(J.todoList=[],B?.stores.tasks.setTasks([]),P.session.setTodoList([]))},markUserAborted:()=>{K.userAborted=!0},resetCtrlCCount:()=>{K.ctrlCCount=0},markRestartRequested:()=>{s=!0},stopTui:E,isBusy:()=>q()}),k=fe,{historyStore:re,inputHistory:ae,externalHistoryCommands:A}=await Xn(P,n.settings.get(`history`)?.external),j=fn({app:n,session:P,getTui:()=>L});p=j;let M,le,de,F,pe={value:void 0};ze(`startTui() begin`);let me=r(await y(n.workspaceDir,{readdir:e=>xt(e,{withFileTypes:!0})})).map(e=>Q.t(e)),L=await Fe({stdin:process.stdin,stdout:process.stdout,modelName:Oe(Ce),needsSetup:R.size===0,promptSuggestions:me,commands:Le,pluginInput:n.pluginInput,isImmediateCommand:e=>q()?ue.has(e):k.has(e),isInterruptCommand:e=>e===`abort`,isAgentBusy:q,isPaused:()=>P.isPaused,initialPath:te&&v>0?`/`:`/home`,shadow:n._shadow,welcome:{cwd:process.cwd(),version:Ke,buildId:Ue,nickname:n.settings.get(`nickname`)||void 0,updateAvailable:void 0},onSessionSelect:e=>{N(`resume`,[e],F)},onInstallCapability:e=>{import(`./extension-plugin-VUdbaAN7.js`).then(({runPluginInstall:t})=>t(e,F))},onDismissCapabilityRecommendations:()=>{B?.stores.tasks.dismissCapabilityRecommendations()},loadHistory:n.sessionRepoRef?.current?await(async()=>{let e=n.sessionRepoRef.current;if(!e)return;let r=await rn(e,P.id,!!t.continueSession);return e=>r.loadEarlier(e.limit)})():void 0,language:Y,themeRegistry:Ve,presetSelection:He,keybindingOverrides:We,permissionMode:n.getPermissionMode(),onFocusChange:e=>n.setTerminalFocus(e),...j.handlers,initialHistory:ae,externalHistoryCommands:A,residencyGovernor:n._residencyGovernor,resolveWholeFileDiff:async(e,t)=>{try{return await o(Xe(n.workspaceDir,e),t)}catch(e){return{error:e instanceof Error?e.message:String(e)}}},initialDrafts:g(P.session.getDrafts()??[]),initialRecentMentions:tr(n.settings.get(`recent_mentions`)??[]),onSigilSelect:e=>{let t=$n(n.settings.get(`recent_mentions`)??[],er(e));n.settings.persist({recent_mentions:t}).catch(()=>{}),B?.stores.tasks.setRecentMentions(tr(t))},...ar({app:n,getTui:()=>L,getTuiRef:()=>B,getSession:()=>P,getCliCtx:()=>F,historyStore:re,getPasteBinder:()=>F.callbacks.pasteBinder}),onQueueSendNow:(e,t)=>{if(t===`memory`){de(e);return}if(t===`bash`||t===`bash_async`){M(e,t===`bash`?`!`:`!!`);return}m?.(e,`send`,q()?`steer`:`send`)},onSubmit:m=async(e,t,r)=>{if(K.ctrlCCount=0,le(e,t))return;if(P.isPaused&&P.resumeRun(),r===`steer`&&P.isBusy){K.latestSubmittedPrompt={text:e,mode:t};let n=oe(await ie(e,{currentModelId:P.model?.id,applyModel:Ne,onSwitchFailed:e=>L.info.showToast(Q.t(`cmd.titleModel`),e)}),{currentEffort:P.thinkingLevel,applyEffort:e=>ne(F,e),onInvalidLevel:e=>L.info.showToast(Q.t(`cmd.titleEffort`),Q.t(`cmd.effortUnknown`,{arg:e,levels:ce.join(` / `)}))});if(Pn(n))return;let{id:r}=P.steer(n);L.pending.setPendingSteer(n,r);return}if(t===`memory`){await de(e);return}if(t===`bash`||t===`bash_async`){M(e,t===`bash`?`!`:`!!`);return}let i=Kt(e),a=e,o=!1;if(i.isCommand){if(await N(i.command,i.args,F))return;n.firePluginActivationEvent?.(`onCommand:${i.command}`);let e=Ie.find(e=>e.name===i.command);e&&(o=!0,a=await je(e.body,{args:i.args,workspaceDir:n.workspaceDir}))}let s=i.isCommand&&!o&&se.has(i.command.toLowerCase());if(!s&&!I&&(!i.isCommand||o)){L.info.showToast(Q.t(`cmd.titleSetupRequired`),Q.t(`cmd.noModelConfigured`));return}if(J.todoList.length>0&&J.todoList.every(e=>e.status===`done`||e.status===`skipped`||e.status===`failed`)&&(J.todoList=[],L.stores.tasks.setTasks([]),P.session.setTodoList([])),q()&&(!i.isCommand||o)){L.engine.enqueueFollowUp(e,t),L.info.showToast(Q.t(`cmd.titleInfo`),Q.t(`queue.dFollowUpToast`));return}if(s||(await Pe(),L.engine.pushEngineEvent({kind:`agentProcessing`,value:!0}),K.agentProcessing=!0,L.plugins.setCommands(Re())),K.userAborted=!1,a=await ie(a,{currentModelId:P.model?.id,applyModel:Ne,onSwitchFailed:e=>L.info.showToast(Q.t(`cmd.titleModel`),e)}),a=oe(a,{currentEffort:P.thinkingLevel,applyEffort:e=>ne(F,e),onInvalidLevel:e=>L.info.showToast(Q.t(`cmd.titleEffort`),Q.t(`cmd.effortUnknown`,{arg:e,levels:ce.join(` / `)}))}),Pn(a))return;K.latestSubmittedPrompt={text:e,mode:t},K.retryMode||(K.errorRetryAttempt=0),K.retryMode=!1,$e.lastTasks=J.todoList.slice();let c=r=>{cr({err:r,submitState:K,provider:P.model?.provider,rateLimitInfoRef:{get current(){return K.lastRateLimitInfo},set current(e){K.lastRateLimitInfo=e}},retryModeRef:{get current(){return K.retryMode},set current(e){K.retryMode=e}},errorRetryAttemptRef:{get current(){return K.errorRetryAttempt},set current(e){K.errorRetryAttempt=e}},ERROR_RETRY_MAX:b,ERROR_RETRY_INTERVAL_SECONDS:n.getResilienceConfig().errorRetry.intervalMs/1e3,handleSubmit:m,retryLastRound:()=>{let n=[...P.session.messages()].reverse().find(e=>e.role===`user`);return!n||(Array.isArray(n.content)?n.content.map(e=>e.type===`text`?e.text:``).join(``):String(n.content??``))!==e?!1:(L.engine.pushEngineEvent({kind:`agentProcessing`,value:!0}),K.agentProcessing=!0,P.retryLastRound().catch(n=>{if(n?.code===`RETRY_NO_RESUMABLE_ROUND`){queueMicrotask(()=>m?.(e,t,`send`));return}L.pending.withdrawPendingEcho(),c(n)}).finally(()=>{K.agentProcessing=!1,L.engine.pushEngineEvent({kind:`agentProcessing`,value:!1})}),!0)},latestSubmittedPromptRef:{get current(){return K.latestSubmittedPrompt},set current(e){K.latestSubmittedPrompt=e}},text:e,mode:t,handleModel:be,handleProviderAuth:xe,cliCtx:F,tui:L})};try{a=await n.expandSigilChips(a,{skipPrefixes:new Set([`model`])}),(!i.isCommand||o)&&!K.retryMode&&(L.messages.echoUserInput(a,{pending:!0}),L.pending.setPendingEcho(a,t),n.settings.get(`first_prompt_submitted_at`)===void 0&&(n.settings.persist({first_prompt_submitted_at:Date.now()}).catch(()=>{}),(async()=>{let e=await mn({hasFile:async e=>{try{return await Ct(Z(n.workspaceDir,e)),!0}catch{return!1}},packageDependencyNames:async()=>{try{let e=await bt(Z(n.workspaceDir,`package.json`),`utf-8`),t=JSON.parse(e);return new Set([...Object.keys(t.dependencies??{}),...Object.keys(t.devDependencies??{})])}catch{return new Set}}},new Set(n.activePlugins().map(e=>e.id))).catch(()=>[]);B?.stores.tasks.setCapabilityRecommendations(e)})()));let e=a;K.streamedText=!1;let r=await W.handleInput(e);if(r.type===`exit`){Me(r);return}if(r.type===`help`){L.modal.openModal({kind:`helpViewer`,title:`Help`,lines:Yt(G,P.pinned,Q.t(`cmdDesc`,{returnObjects:!0})),onDismiss:()=>{}});return}r.type!==`noop`&&r.text&&!K.streamedText&&(r.type===`system`&&r.text.length<=80?L.info.showToast(Q.t(`cmd.titleInfo`),r.text):L.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:r.text}]})),r.type===`response`&&r.endReason&&(L.pending.clearPendingEcho(),r.notice&&L.info.showToast(Q.t(`cmd.titleInfo`),r.notice)),await Ht(r,{runTurn:e=>W.handleInput(e),onTurnResult:e=>e.type===`exit`?(Me(e),`exit`):(e.type!==`noop`&&e.type!==`help`&&e.text&&!K.streamedText&&L.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:e.text}]}),`continue`),askBudgetContinue:()=>new Promise(e=>{L.modal.openModal({kind:`select`,title:Q.t(`budget.exhaustedTitle`),layout:`buttons`,options:[{label:Q.t(`budget.continue`),value:`go`,color:`accent`},{label:Q.t(`budget.stop`),value:`stop`,color:`amber`}],onSelect:t=>e(t===`go`),onCancel:()=>e(!1)})}),onBudgetStopped:()=>{L.messages.pushMessage({role:`assistant`,content:[{type:`text`,text:Q.t(`budget.stoppedNote`)}]})},beforeContinuationTurn:()=>{K.streamedText=!1}})}catch(e){L.pending.withdrawPendingEcho(),c(e)}finally{K.agentProcessing=!1,K.userAborted=!1,L.engine.pushEngineEvent({kind:`agentProcessing`,value:!1}),L.plugins.setCommands(Re())}},onInterrupt:()=>{let e=Date.now(),t=zn(e,K.lastCtrlCTime,{shellRunning:!!K.shellChild,busy:q(),stopDialogOpen:D.isStopDialogOpen(),idleCtrlCCount:K.ctrlCCount});if(t!==`dedup`)switch(K.lastCtrlCTime=e,t){case`kill-shell`:K.shellChild.kill(`SIGTERM`),setTimeout(()=>{K.shellChild&&!K.shellChild.killed&&K.shellChild.kill(`SIGKILL`)},3e3);return;case`open-stop-dialog`:D.requestStop(`abort`);return;case`escalate-exit`:D.escalateToExit();return;case`exit-process`:E();return;case`hint-exit`:K.ctrlCCount++,setTimeout(()=>{K.ctrlCCount=0},800).unref(),L.info.showToast(Q.t(`cmd.titleExit`),Q.t(`cmd.pressCtrlCAgain`));return}},onShellAskAi:()=>{let e=B?.shell.getShellExecutionSnapshot();if(!e)return;let t=Rn(e);m?.(t,`send`,q()?`steer`:`send`)},onWithdrawPending:(e,t)=>{L.pending.withdrawPendingEcho(),L.pending.restoreInputText(e),K.agentProcessing&&(K.userAborted=!0,U({kind:`abort`}),L.info.showToast(Q.t(`cmd.titleAborted`),Q.t(`cmd.runAborted`)))},onWithdrawSteer:e=>{P.removeSteer(e)?L.pending.withdrawPendingSteer(e):D.requestStop(`abort`)},onStop:()=>{T()}});B=L,i&&(i.current=(e,t)=>{L.info.showToast(`Memory Conflict`,`Concurrent edit detected for ${e} — saved to ${t}`)}),ze(`startTui() ready (first frame mounted)`),n.setUserAskRenderer(e=>en(L,e));let ve=Zn({gateway:()=>n.sessionManager.panelState,bridge:()=>L.pending,onError:(e,t)=>{n.logger?.debug?.({stage:e,error:t},`paste cache binding failed (non-fatal)`)}});Tn({app:n,tui:L}),wn(n),n.listAllSessions().then(e=>{let t=P.id,n=e.filter(e=>e.status!==`archived`&&(e.entryCount??e.messageCount)>0&&e.id!==t).slice(0,10).map(e=>({id:e.id,title:e.title??e.id.slice(0,8),status:e.id===t?`busy`:`idle-cold`,lastActivityAt:e.updatedAt?new Date(e.updatedAt).toLocaleString():``,isCurrent:e.id===t,isPinned:e.pinned??!1,isArchived:e.status===`archived`,isReadOnly:e.writeLocked??!1}));L.stores.tasks.setSessionList(n)}).catch(()=>{});let{pollInterval:z,scheduler:ke}=Sn(n,{get value(){return P}},L,t.sessionUrl&&t.sessionToken?{sessionUrl:t.sessionUrl,sessionToken:t.sessionToken}:void 0);M=Fn({tui:L,app:n,submitState:K}),le=In({agentProcessingRef:{get value(){return K.agentProcessing},set value(e){K.agentProcessing=e}},tui:L,requestStop:e=>D.requestStop(e)}),de=Ln({app:n,tui:L}),En({app:n,tui:L,session:P}),Dn({app:n,tui:L,getScheduler:()=>ke});let Me=e=>{D.requestStop(e.restart?`exit-restart`:`exit`)};t.memoryRestartGrace&&n.memoryGovernor.markRestarted();let H=t.restartGeneration??0;H>=3&&L.info.pushNotification(Q.t(`cmd.titleFleetBudget`),Q.t(`cmd.restartChainDeep`,{generation:H}),`system`,`warning`),L.engine.pushEngineEvent({kind:`perf`,indicatorLevel:n.memoryGovernor.currentLevel,memory:n.memoryGovernor.sample()}),Qn({session:P,tui:L,retryAccelerate:O,setRateLimitInfo:e=>{K.lastRateLimitInfo=e},abortNow:()=>{D.abortNow()}});let X=dn({getSession:()=>P,app:n,tui:L,projState:J,contextWindow:we,currentModelId:Ee}),{recomputeBudget:qe,persistEditedFiles:Je,persistSubagents:Ye,persistTurnCount:Ze,onContextCompacted:Qe}=X;Ae=qe,qe(),n.editFileCallback=X.editFileCallback,ir({app:n,tui:L,getSession:()=>P,setRestartResumePrompt:e=>{u=e},setRestartMemoryTriggered:e=>{l=e},handleExit:Me,onContextCompacted:Qe,recomputeBudget:qe}),n.registerInAppNotificationChannel((e,t,n)=>L.info.pushNotification(e,t,`system`,d(n))),n.setFollowUpPendingProbe(()=>L.engine.hasQueuedFollowUp());let $e=f(),et=tn({getSession:()=>P,app:n,tui:L,projState:J,redState:$e,recomputeBudget:qe,persistEditedFiles:Je,persistSubagents:Ye,persistTurnCount:Ze,onContextCompacted:Qe,markStreamed:()=>{K.streamedText=!0}});pe.value=et,F=Cn({tui:L,app:n,themeRegistry:Ve,sessionRef:{get value(){return P},set value(e){P=e}},interactiveRef:{get value(){return W},set value(e){W=e}},regRef:{get value(){return G},set value(e){G=e}},slashCommandsRef:{get value(){return Le},set value(e){Le=e}},modelReadyRef:{get value(){return I},set value(e){I=e}},currentModelIdRef:{get value(){return Te},set value(e){Te=e}},currentLangRef:{get value(){return Be},set value(e){Be=e}},projState:J,agentProcessingRef:{get value(){return K.agentProcessing},set value(e){K.agentProcessing=e}},modelsRef:{get value(){return he},set value(e){he=e}},availableModelIds:R,restartRequestedRef:{get value(){return s},set value(e){s=!!e}},applyModel:Ne,persistAvailable:_e,refreshModelsNow:Se,refreshSlashCommands:Re,events:et,redState:$e,agentMessagesToChatMessages:ge,PROVIDER_DISPLAY_NAMES:c,apiCredentialId:De,onContextCompacted:Qe}),F.callbacks.pasteBinder=ve,ve.load(P.id),L.plugins.setPluginRegistrations(n.getPluginRegistrations());let tt=await ye.refresh();if(B?.stores.tasks.setFtueStage(tt.stage),a(tt)&&Y===`auto`&&!n.settings.get(`has_completed_onboarding`)){let e=await L.modal.openModal({kind:`onboarding`,onLanguagePreview:e=>{let t=e===`auto`?w():e;_(t),L.lifecycle.setLanguage(t),Be=t}});if(e.nickname&&n.settings.persist({nickname:e.nickname}).catch(()=>{}),e.language){let t=e.language===`auto`?w():e.language;_(t),L.lifecycle.setLanguage(t),Be=t,n.settings.persist({language:e.language}).catch(()=>{})}n.settings.persist({has_completed_onboarding:!0}).catch(()=>{})}tt.recommendation.autoOpen&&N(`setup`,[],F);let nt=Mn();nt&&(ee=new Nn({repoRoot:nt,currentBuildId:Ue,logger:n.logger,onStale:e=>{L.info.pushNotification(Q.t(`cmd.titleStaleBuild`),Q.t(`cmd.staleBuildMessage`,{current:Ue,latest:e}),`system`,`info`)}}),ee.start()),await An({tui:L,options:t,app:n,session:P,projState:J,resumedNote:S,resumed:h,updateCheckPromise:Ge,bg:j,events:et}),x.value&&L.info.showToast(Q.t(`crashGap.toastTitle`),Q.t(`crashGap.toastBody`,{lostTurns:x.value.lostTurns}))});let X;if(n.codingSessionPool.autoPersist&&P.session.messages().length>0){let e=t.sessionUrl?` --session-url ${t.sessionUrl}`:``,n=t.sessionToken?` --session-token ${t.sessionToken}`:``;X=`\n\x1b[2m${Q.t(`cmd.resumeContinueLabel`)}\x1b[0motto --continue ${P.id}${e}${n}\n`}return{restart:s?{sessionId:P.id,memoryTriggered:l,resumePrompt:u}:void 0,resumeHint:X}}finally{p?.clearBgSubs(),p?.stopBgOutputPoll(),p?.stopBgSubagentPoll()}}async function ur(e){if(e.hasParentWorkspace()){let t=e.parentWorkspaceExisted,n=await mt({parentRoot:t.parentRoot,currentRoot:t.currentRoot,language:e.settings.get(`language`)});n===`exit`&&(process.stdout.write(`
|
|
12
|
+
`),process.exit(0)),n===`use_parent`?await e.adoptParentWorkspace():await e.createLocalWorkspace()}let t=Ae(e.workspaceDir,{interactive:!0});if(!t.shouldPrompt){e.needsWorkspaceInit()&&await e.confirmWorkspaceInit();return}let n=await ht({root:t.root,language:e.settings.get(`language`)});if(n===`exit`&&(process.stdout.write(`
|
|
13
|
+
`),process.exit(0)),n===`trust`){G(t.root),await e.settings.reload(),e.needsWorkspaceInit()&&await e.confirmWorkspaceInit();return}await e.settings.update({permission_mode:`readonly`}),e.needsWorkspaceInit()&&await e.confirmWorkspaceInit()}function dr(e){throw e instanceof Error&&e.message.startsWith(`No model configured`)?Error("No model configured. Run `otto` (interactive) to complete setup — it walks you through: install a provider plugin → /auth → /model. Or authenticate directly with `otto auth login`."):e}async function fr(e,t){e.prompt&&await P(await t.createSession({listable:!1}).catch(dr),e.prompt,{tui:!0})}async function pr(e,t){if(e.prompt){let n=await k(await t.createSession({listable:!1}).catch(dr),e.prompt);process.stdout.write(JSON.stringify(n,null,2)+`
|
|
14
|
+
`)}}function mr(e){gt(e.settings.get(`theme_overrides`)?.markdown)}ze(`cli.ts imports resolved`);const hr=new Map([[`doctor`,async e=>{let{runDoctorCommand:t}=await import(`./doctor-DbQC8Z7p.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`auth`,async e=>{let{runAuthCommand:t}=await import(`./auth-command-kkJh-O5y.js`);return t(e.args,{bootstrap:{workspaceDir:e.options.projectDir,projectConfigPath:e.options.configPath,verbose:e.options.verbose},stdout:e.stdout,stderr:e.stderr})}],[`serve`,async e=>{let{runServeCommand:t}=await import(`./serve-vWHGydiC.js`);return t(e.args,{projectDir:e.options.projectDir,configPath:e.options.configPath,modelId:e.options.model,verbose:e.options.verbose})}],[`daemon`,async e=>{let{runDaemonCommand:t}=await import(`./daemon-BtiaXSxn.js`);return t(e.args,{projectDir:e.options.projectDir,stdout:e.stdout,stderr:e.stderr})}],[`persistenced`,async e=>{let{runPersistencedCommand:t}=await import(`./persistenced-CcAhVOE7.js`);return t(e.args)}],[`remote-persistence-server`,async e=>{let{runRemotePersistenceServerCommand:t}=await import(`./remote-persistence-server-CLI-y-zp.js`);return t(e.args)}],[`observe`,async e=>{let{runObserveCommand:t}=await import(`./observe-C2jjDNDa.js`);return t(e.args)}],[`debug`,async e=>{let{runDebugCommand:t}=await import(`./debug-DfgcrVCI.js`);return t(e.args)}],[`time-travel`,async e=>{let{runTimeTravelCommand:t}=await import(`./time-travel-D1sg5dEb.js`);return t(e.args)}],[`mcp`,async e=>{let{runMcpCommand:t}=await import(`./mcp-BDfBf6gx.js`);return t(e.args)}],[`config`,async e=>{let{runConfigMigrationCommand:t}=await import(`./config-migration-0zdXsEDB.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`migrate`,async e=>{let{runMigrateCommand:t}=await import(`./migrate-4QDwYLf6.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`extension`,async e=>{let{runExtensionCommand:t}=await import(`./extension-I87MkZYp.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`ps`,async e=>{let{runPsCommand:t}=await import(`./ps-BWGntaR4.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr})}],[`feedback`,async e=>{let{runFeedbackCommand:t}=await import(`./feedback-j4tDn2uI.js`);return t(e.args,{stdout:e.stdout,stderr:e.stderr,projectDir:e.options.projectDir,configPath:e.options.configPath})}]]);async function gr(e,t,n){let r=ve({cwd:n.projectDir,homedir:z()}),i=new Set(_e),a=Oe(r,i).get(e);if(!a){let t=Me(r,i,e);return t?(process.stderr.write(`otto: 命令 "${e}" 被多个插件声明(${t.join(`, `)}),已禁用以避免歧义。\n请重命名其中一个插件的 \`contributes.cli.name\` 后重试(编辑对应插件目录的 otto-plugin.json)。\n`),1):void 0}if(ke(a).gated)return process.stderr.write(`otto: 插件 "${a.id}" 声明了 \`otto ${e}\` 命令但尚未被信任。\n请先在 TUI 内运行 \`/trust plugin ${a.id}\`(或 \`/extension\` 信任该插件)后重试。\n`),1;let o=Pe(a);if(!o)return process.stderr.write(`otto: 插件 "${a.id}" 声明了 \`contributes.cli\` 但找不到可执行入口,请检查其 manifest 的 bin 字段或重新安装该插件。\n`),1;try{return await Fe(o,t,a.dir)}catch(e){return process.stderr.write(`otto: 插件 "${a.id}" 的 CLI 命令执行失败:${e instanceof Error?e.message:String(e)}\n`),1}}function _r(e,t){return e.mode===`interactive`&&!e.verbose&&!t?`fatal`:t}function vr(e,t){return e.mode===`interactive`&&!t?`0`:t}function yr(e,t,n={}){let r=[];for(let t=0;t<e.length;t++){if(e[t]===`--continue`){t++;continue}e[t].startsWith(`--restart-generation=`)||r.push(e[t])}return[...n.execArgv??[],...r,`--continue`,t,...n.generation===void 0?[]:[`--restart-generation=${n.generation}`],...n.sessionUrl?[`--session-url`,n.sessionUrl]:[],...n.sessionToken?[`--session-token`,n.sessionToken]:[],...n.memoryRestartGrace?[`--memory-restart-grace`]:[],...n.resumePrompt?[`--resume-prompt`,n.resumePrompt]:[]]}async function br(){process.stdin.on(`error`,e=>{e.code});let{options:e,subCommand:t,subCommandArgs:n,unresolvedCommandName:r,unresolvedCommandArgs:i}=R(process.argv);e.shadow&&(process.env.OTTO_SHADOW=`1`);let a=e.verbose?`debug`:e.mode===`interactive`?`fatal`:e.quiet?`error`:`info`;Be(a);let o=_r(e,process.env.OTTO_LOG_LEVEL);o&&(process.env.OTTO_LOG_LEVEL=o);let s=vr(e,process.env.OTTO_LOG_STDERR);s&&(process.env.OTTO_LOG_STDERR=s),process.env.OTTO_LOG_STDERR===`0`?X(()=>{}):X(e=>process.stderr.write(`${e}\n`)),process.on(`beforeExit`,()=>{process.env.OTTO_LOG_STDERR!==`0`&&X(e=>process.stderr.write(`${e}\n`))});let c=n.split(` `).filter(Boolean),l=hr.get(t??``);if(l)return l({args:c,options:e,stdout:e=>process.stdout.write(e),stderr:e=>process.stderr.write(e)});if(r){let t=await gr(r,i??[],e);if(t!==void 0)return t}if(e.showHelp){let{getHelpLines:e}=await import(`./parse-cli-Cw5qyM5B.js`).then(e=>e.r);return process.stdout.write(e().join(`
|
|
15
15
|
`)+`
|
|
16
16
|
`),0}if(!e.prompt&&e.mode!==`interactive`)return process.stderr.write(`otto: no prompt provided. Use --help for usage.
|
|
17
|
-
`),1;let u=await
|
|
17
|
+
`),1;let u=await Je(),d=e.sessionUrl??u?.serviceUrl,f=e.sessionToken??u?.token,p={},m=He(`new App() ctor`,()=>ye({inspect:e.inspect!==void 0||e.mode===`interactive`,logger:{name:`otto-cli`,level:a,destination:`stderr`},workspaceDir:e.projectDir,workspaceId:e.workspaceId,projectConfigPath:e.configPath,interactive:e.mode===`interactive`,shadow:e.shadow??!1,modelId:e.model,userIdentity:u??void 0,...e.maxToolTurns===void 0?{}:{maxToolTurns:e.maxToolTurns},...e.maxToolTurnExtensions===void 0?{}:{maxToolTurnExtensions:e.maxToolTurnExtensions},...e.promptTokenBudget===void 0?{}:{promptOutputTokenBudget:e.promptTokenBudget},...e.promptTimeBudgetMin===void 0?{}:{promptWallClockBudgetMs:e.promptTimeBudgetMin*6e4},...e.sessionCostBudget===void 0?{}:{sessionCostBudgetUSD:e.sessionCostBudget},...e.noStallDetection?{stallDetection:!1}:e.stallWindowTurns!==void 0&&e.stallRepeatThreshold!==void 0?{stallDetection:{windowTurns:e.stallWindowTurns,repeatThreshold:e.stallRepeatThreshold}}:{},storage:d&&f?{session:{url:d},remote:{getAuth:async()=>({token:f})}}:{session:{dir:Ge}},onMemoryConflict:(e,t)=>p.current?.(e,t)}));await Ve(`app.start()`,()=>m.start()),mr(m),q(K);let h=!1,g=()=>{h&&process.exit(1),h=!0,Promise.race([m.stop(),new Promise(e=>setTimeout(e,1e4))]).finally(()=>{e.mode===`interactive`&&Vt(),process.exit(1)})};process.on(`SIGTERM`,g),process.on(`SIGHUP`,g);let _,v=!1,y,b;if(e.attachSession){let t=process.env.OTTO_SERVICE_URL??`http://127.0.0.1:8417`,{runAttach:n}=await import(`./run-attach-DZmBqVjI.js`);return await n({sessionId:e.attachSession,baseUrl:t,token:process.env.OTTO_SERVICE_TOKEN,forceWriteLease:e.forceWriteLease}),0}try{switch(e.mode){case`print`:await fr(e,m);break;case`json`:await pr(e,m);break;case`interactive`:{await ur(m);let t=await lr(e,m,p);_=t.restart?.sessionId,v=!!t.restart?.memoryTriggered,y=t.restart?.resumePrompt,t.restart||(b=t.resumeHint);break}}}finally{let t=()=>{};process.on(`SIGINT`,t);let n=setTimeout(()=>{try{process.stdout.write(`\x1B[?25h`)}catch{}e.mode===`interactive`&&Vt(),process.exit(0)},1e4);try{await m.stop()}finally{clearTimeout(n),process.removeListener(`SIGINT`,t)}}if(_){process.removeListener(`SIGTERM`,g),process.removeListener(`SIGHUP`,g);let t=e.sessionUrl,n=e.sessionToken,r=()=>{},i,a=e=>{try{console.error(`\n[otto] 重启陪跑期父进程异常,终止子会话以避免孤儿挂起:${e instanceof Error?e.stack??e.message:String(e)}`)}catch{}try{i?.kill(`SIGTERM`)}catch{}process.exit(1)};return process.on(`SIGINT`,r),process.on(`SIGTERM`,r),process.on(`uncaughtException`,a),process.on(`unhandledRejection`,a),i=Te(process.execPath,yr(process.argv.slice(1),_,{sessionUrl:t,sessionToken:n,memoryRestartGrace:v,resumePrompt:y,execArgv:process.execArgv,generation:(e.restartGeneration??0)+1}),{stdio:`inherit`,env:{...process.env}}),i.on(`exit`,(e,t)=>{process.removeListener(`SIGINT`,r),process.removeListener(`SIGTERM`,r),process.removeListener(`uncaughtException`,a),process.removeListener(`unhandledRejection`,a),process.exit(e??(t?1:0))}),0}if(e.mode===`interactive`){if(Vt(),b)try{process.stdout.write(b)}catch{}process.exit(process.exitCode??0)}return 0}br().then(e=>{e!==0&&(process.exitCode=e)}).catch(e=>{process.stderr.write(`otto: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1});export{br as runCli};
|
|
18
18
|
//# sourceMappingURL=index.js.map
|