@x-otto/tui 0.0.1-alpha.0

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.
@@ -0,0 +1,114 @@
1
+ //#region src/compat.d.ts
2
+ /**
3
+ * compat.ts — Backward-compatible exports for packages/cli(modes/interactive-mode.ts).
4
+ *
5
+ * ESM 入口(`@x-otto/tui/compat`):根入口 ESM 图含 yoga-layout 顶层
6
+ * await,若消费方在自身模块顶层同步 `require()` 会必败,故本文件保持零 Ink/React 依赖,
7
+ * 允许消费方直接 `import`。
8
+ *
9
+ * 命令系统为 M52 前 commands.ts 的原样保留(CommandRegistry + 内置命令)。
10
+ * 控制类命令返回 `CommandAction` 判别联合(RFC-089 A1:取代原 __exit__/__clear__
11
+ * 字符串哨兵协议),interactive-mode._handleCommandResult 按 kind 分发消费。
12
+ * showCommandPalette 在 V2 下退化为路由 /help(Ink 持有 stdin raw
13
+ * mode,旧 readline 选择器会争抢输入流)。
14
+ */
15
+ interface RenderOptions {
16
+ columns?: number;
17
+ showThinking?: boolean;
18
+ contextWindow?: number;
19
+ startTime?: number;
20
+ }
21
+ /** 命令执行上下文。 */
22
+ interface CommandContext {
23
+ /** 中止信号。 */
24
+ signal: AbortSignal;
25
+ /** 终端宽度。 */
26
+ width: number;
27
+ /** 可用模型列表(供 /model 命令)。 */
28
+ models?: Array<{
29
+ id: string;
30
+ name: string;
31
+ provider: string;
32
+ }>;
33
+ /** 当前模型 ID。 */
34
+ currentModel?: string;
35
+ /** 模型切换回调。 */
36
+ onModelChange?: (modelId: string) => Promise<string>;
37
+ /** 任务列表(供 /tasks 命令)。 */
38
+ tasks?: Array<{
39
+ subject: string;
40
+ status: 'pending' | 'in_progress' | 'completed' | 'blocked';
41
+ }>;
42
+ }
43
+ type CommandType = 'action' | 'prompt';
44
+ /**
45
+ * 命令执行的结构化结果(RFC-089 A1:取代原 `__exit__`/`__model:id__` 字符串哨兵协议)。
46
+ * 控制类命令返回判别联合(run-modes 按 kind 分发);文本类命令(模型列表/插件命令等)
47
+ * 继续返回 string(透传为系统消息)。消除了「字符串哨兵 + startsWith 解析」的类型擦除反模式。
48
+ */
49
+ type CommandAction = {
50
+ kind: 'exit';
51
+ restart?: boolean;
52
+ } | {
53
+ kind: 'help';
54
+ } | {
55
+ kind: 'clear';
56
+ } | {
57
+ kind: 'abort';
58
+ } | {
59
+ kind: 'status';
60
+ } | {
61
+ kind: 'copy';
62
+ } | {
63
+ kind: 'model';
64
+ modelId: string;
65
+ };
66
+ type CommandResult = string | CommandAction;
67
+ interface Command {
68
+ /** 命令名(不含 / 前缀)。 */
69
+ name: string;
70
+ /** 简短描述。 */
71
+ description: string;
72
+ /** 别名。 */
73
+ aliases?: string[];
74
+ /** 命令类型。 */
75
+ type: CommandType;
76
+ /** 来源。 */
77
+ source?: 'builtin' | 'plugin' | 'skill' | 'mcp';
78
+ /**
79
+ * action: 本地执行,返回结果(CommandAction 控制指令 或 string 文本)。
80
+ * prompt: 返回注入 agent 对话的 prompt 文本。
81
+ */
82
+ execute: (args: string, ctx: CommandContext) => CommandResult | Promise<CommandResult>;
83
+ }
84
+ declare class CommandRegistry {
85
+ private commands;
86
+ /** 注册命令。重名时抛出。 */
87
+ register(cmd: Command): void;
88
+ /** 按名称获取命令。 */
89
+ get(name: string): Command | undefined;
90
+ /** 按名称或别名查找。 */
91
+ find(nameOrAlias: string): Command | undefined;
92
+ /** 列出所有命令。 */
93
+ list(): Command[];
94
+ /** 列出命令名。 */
95
+ names(): string[];
96
+ /** 是否存在。 */
97
+ has(name: string): boolean;
98
+ /** 注销命令。 */
99
+ unregister(name: string): boolean;
100
+ }
101
+ /** 创建内置命令注册表(对标 CC COMMANDS())。 */
102
+ declare function createBuiltinCommands(): CommandRegistry;
103
+ interface PaletteResult {
104
+ command: string | null;
105
+ args: string;
106
+ }
107
+ /**
108
+ * V2 下 Ink 持有 stdin raw mode,旧 readline 选择器会争抢输入流——
109
+ * bare '/' 退化为路由 /help(列出全部命令),不再弹交互式菜单。
110
+ */
111
+ declare function showCommandPalette(_commands: Command[], _stdin?: NodeJS.ReadStream, _stdout?: NodeJS.WriteStream): Promise<PaletteResult>;
112
+ //#endregion
113
+ export { Command, CommandAction, CommandContext, CommandRegistry, CommandResult, CommandType, PaletteResult, RenderOptions, createBuiltinCommands, showCommandPalette };
114
+ //# sourceMappingURL=compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.d.ts","names":[],"sources":["../src/compat.ts"],"mappings":";;AAgBA;;;;;;;;;;AAQA;;UARiB,aAAA;EACf,OAAA;EACA,YAAA;EACA,aAAA;EACA,SAAA;AAAA;;UAIe,cAAA;EAEP;EAAR,MAAA,EAAQ,WAAA;EAIR;EAFA,KAAA;EAEiB;EAAjB,MAAA,GAAS,KAAA;IAAQ,EAAA;IAAY,IAAA;IAAc,QAAA;EAAA;EAIN;EAFrC,YAAA;EAIQ;EAFR,aAAA,IAAiB,OAAA,aAAoB,OAAA;EAEJ;EAAjC,KAAA,GAAQ,KAAA;IAAQ,OAAA;IAAiB,MAAA;EAAA;AAAA;AAAA,KAGvB,WAAA;;AAOZ;;;;KAAY,aAAA;EACN,IAAA;EAAc,OAAA;AAAA;EACd,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;AAAA;EACA,IAAA;EAAe,OAAA;AAAA;AAAA,KAET,aAAA,YAAyB,aAAA;AAAA,UAEpB,OAAA;EAQT;EANN,IAAA;EAcgD;EAZhD,WAAA;EAYgE;EAVhE,OAAA;EAUuE;EARvE,IAAA,EAAM,WAAA;EAJN;EAMA,MAAA;EAFA;;;;EAQA,OAAA,GAAU,IAAA,UAAc,GAAA,EAAK,cAAA,KAAmB,aAAA,GAAgB,OAAA,CAAQ,aAAA;AAAA;AAAA,cAG7D,eAAA;EAAA,QACH,QAAA;EAJwD;EAOhE,QAAA,CAAS,GAAA,EAAK,OAAA;EAPuE;EAerF,GAAA,CAAI,IAAA,WAAe,OAAA;EAZR;EAiBX,IAAA,CAAK,WAAA,WAAsB,OAAA;;EAU3B,IAAA,CAAA,GAAQ,OAAA;EAfW;EAoBnB,KAAA,CAAA;EALQ;EAUR,GAAA,CAAI,IAAA;EAVW;EAef,UAAA,CAAW,IAAA;AAAA;;iBAMG,qBAAA,CAAA,GAAyB,eAAA;AAAA,UAgGxB,aAAA;EACf,OAAA;EACA,IAAA;AAAA;;;;;iBAOc,kBAAA,CACd,SAAA,EAAW,OAAA,IACX,MAAA,GAAS,MAAA,CAAO,UAAA,EAChB,OAAA,GAAU,MAAA,CAAO,WAAA,GAChB,OAAA,CAAQ,aAAA"}
package/dist/compat.js ADDED
@@ -0,0 +1,3 @@
1
+ import{n as e}from"./i18n-CznO8p1Y.js";var t=class{commands=new Map;register(e){if(this.commands.has(e.name))throw Error(`Command "/${e.name}" is already registered`);this.commands.set(e.name,e)}get(e){return this.commands.get(e)}find(e){let t=this.commands.get(e);if(t)return t;for(let t of this.commands.values())if(t.aliases?.includes(e))return t}list(){return[...this.commands.values()]}names(){return[...this.commands.keys()]}has(e){return this.commands.has(e)}unregister(e){return this.commands.delete(e)}};function n(){let n=new t;return n.register({name:`help`,description:e.t(`cmdDesc.help`),aliases:[`h`,`?`],type:`action`,source:`builtin`,execute:()=>({kind:`help`})}),n.register({name:`exit`,description:e.t(`cmdDesc.exit`),aliases:[`quit`,`q`],type:`action`,source:`builtin`,execute:e=>{let t=e?.trim()??``;return t===`--restart`||t===`-r`?{kind:`exit`,restart:!0}:{kind:`exit`}}}),n.register({name:`clear`,description:e.t(`cmdDesc.clear`),type:`action`,source:`builtin`,execute:()=>({kind:`clear`})}),n.register({name:`abort`,description:e.t(`cmdDesc.abort`),type:`action`,source:`builtin`,execute:()=>({kind:`abort`})}),n.register({name:`copy`,description:e.t(`cmdDesc.copy`),type:`action`,source:`builtin`,execute:()=>({kind:`copy`})}),n.register({name:`model`,description:e.t(`cmdDesc.model`),aliases:[`m`],type:`action`,source:`builtin`,execute:(t,n)=>{if(!n.models||n.models.length===0)return e.t(`model.noRegistry`);if(t&&n.onModelChange){let r=n.models.find(e=>e.id===t||e.name===t);return r?{kind:`model`,modelId:r.id}:e.t(`model.notFound`,{name:t})}let r=new Map;for(let e of n.models){let t=r.get(e.provider)??[];t.push(e),r.set(e.provider,t)}let i=[``];for(let[e,t]of r){i.push(` ${e}:`);for(let e of t){let t=e.id===n.currentModel?` *`:` `;i.push(` ${t} ${e.id} — ${e.name}`)}}return i.push(``,e.t(`model.listFooter`)),i.join(`
2
+ `)}}),n.register({name:`status`,description:e.t(`cmdDesc.status`),type:`action`,source:`builtin`,execute:()=>({kind:`status`})}),n}function r(e,t,n){return Promise.resolve({command:`help`,args:``})}export{t as CommandRegistry,n as createBuiltinCommands,r as showCommandPalette};
3
+ //# sourceMappingURL=compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compat.js","names":[],"sources":["../src/compat.ts"],"sourcesContent":["/**\n * compat.ts — Backward-compatible exports for packages/cli(modes/interactive-mode.ts).\n *\n * ESM 入口(`@x-otto/tui/compat`):根入口 ESM 图含 yoga-layout 顶层\n * await,若消费方在自身模块顶层同步 `require()` 会必败,故本文件保持零 Ink/React 依赖,\n * 允许消费方直接 `import`。\n *\n * 命令系统为 M52 前 commands.ts 的原样保留(CommandRegistry + 内置命令)。\n * 控制类命令返回 `CommandAction` 判别联合(RFC-089 A1:取代原 __exit__/__clear__\n * 字符串哨兵协议),interactive-mode._handleCommandResult 按 kind 分发消费。\n * showCommandPalette 在 V2 下退化为路由 /help(Ink 持有 stdin raw\n * mode,旧 readline 选择器会争抢输入流)。\n */\n\nimport { i18next } from './i18n'\n\nexport interface RenderOptions {\n columns?: number\n showThinking?: boolean\n contextWindow?: number\n startTime?: number\n}\n\n/** 命令执行上下文。 */\nexport interface CommandContext {\n /** 中止信号。 */\n signal: AbortSignal\n /** 终端宽度。 */\n width: number\n /** 可用模型列表(供 /model 命令)。 */\n models?: Array<{ id: string; name: string; provider: string }>\n /** 当前模型 ID。 */\n currentModel?: string\n /** 模型切换回调。 */\n onModelChange?: (modelId: string) => Promise<string>\n /** 任务列表(供 /tasks 命令)。 */\n tasks?: Array<{ subject: string; status: 'pending' | 'in_progress' | 'completed' | 'blocked' }>\n}\n\nexport type CommandType = 'action' | 'prompt'\n\n/**\n * 命令执行的结构化结果(RFC-089 A1:取代原 `__exit__`/`__model:id__` 字符串哨兵协议)。\n * 控制类命令返回判别联合(run-modes 按 kind 分发);文本类命令(模型列表/插件命令等)\n * 继续返回 string(透传为系统消息)。消除了「字符串哨兵 + startsWith 解析」的类型擦除反模式。\n */\nexport type CommandAction =\n | { kind: 'exit'; restart?: boolean }\n | { kind: 'help' }\n | { kind: 'clear' }\n | { kind: 'abort' }\n | { kind: 'status' }\n | { kind: 'copy' }\n | { kind: 'model'; modelId: string }\n\nexport type CommandResult = string | CommandAction\n\nexport interface Command {\n /** 命令名(不含 / 前缀)。 */\n name: string\n /** 简短描述。 */\n description: string\n /** 别名。 */\n aliases?: string[]\n /** 命令类型。 */\n type: CommandType\n /** 来源。 */\n source?: 'builtin' | 'plugin' | 'skill' | 'mcp'\n\n /**\n * action: 本地执行,返回结果(CommandAction 控制指令 或 string 文本)。\n * prompt: 返回注入 agent 对话的 prompt 文本。\n */\n execute: (args: string, ctx: CommandContext) => CommandResult | Promise<CommandResult>\n}\n\nexport class CommandRegistry {\n private commands = new Map<string, Command>()\n\n /** 注册命令。重名时抛出。 */\n register(cmd: Command): void {\n if (this.commands.has(cmd.name)) {\n throw new Error(`Command \"/${cmd.name}\" is already registered`)\n }\n this.commands.set(cmd.name, cmd)\n }\n\n /** 按名称获取命令。 */\n get(name: string): Command | undefined {\n return this.commands.get(name)\n }\n\n /** 按名称或别名查找。 */\n find(nameOrAlias: string): Command | undefined {\n const byName = this.commands.get(nameOrAlias)\n if (byName) return byName\n for (const cmd of this.commands.values()) {\n if (cmd.aliases?.includes(nameOrAlias)) return cmd\n }\n return undefined\n }\n\n /** 列出所有命令。 */\n list(): Command[] {\n return [...this.commands.values()]\n }\n\n /** 列出命令名。 */\n names(): string[] {\n return [...this.commands.keys()]\n }\n\n /** 是否存在。 */\n has(name: string): boolean {\n return this.commands.has(name)\n }\n\n /** 注销命令。 */\n unregister(name: string): boolean {\n return this.commands.delete(name)\n }\n}\n\n/** 创建内置命令注册表(对标 CC COMMANDS())。 */\nexport function createBuiltinCommands(): CommandRegistry {\n const registry = new CommandRegistry()\n\n registry.register({\n name: 'help',\n description: i18next.t('cmdDesc.help')!,\n aliases: ['h', '?'],\n type: 'action',\n source: 'builtin',\n execute: () => ({ kind: 'help' }),\n })\n\n registry.register({\n name: 'exit',\n description: i18next.t('cmdDesc.exit')!,\n aliases: ['quit', 'q'],\n type: 'action',\n source: 'builtin',\n execute: (args) => {\n const trimmed = args?.trim() ?? ''\n if (trimmed === '--restart' || trimmed === '-r') return { kind: 'exit', restart: true }\n return { kind: 'exit' }\n },\n })\n\n registry.register({\n name: 'clear',\n description: i18next.t('cmdDesc.clear')!,\n type: 'action',\n source: 'builtin',\n execute: () => ({ kind: 'clear' }),\n })\n\n registry.register({\n name: 'abort',\n description: i18next.t('cmdDesc.abort')!,\n type: 'action',\n source: 'builtin',\n execute: () => ({ kind: 'abort' }),\n })\n\n registry.register({\n name: 'copy',\n description: i18next.t('cmdDesc.copy')!,\n type: 'action',\n source: 'builtin',\n execute: () => ({ kind: 'copy' }),\n })\n\n registry.register({\n name: 'model',\n description: i18next.t('cmdDesc.model')!,\n aliases: ['m'],\n type: 'action',\n source: 'builtin',\n execute: (args, ctx) => {\n if (!ctx.models || ctx.models.length === 0) {\n return i18next.t('model.noRegistry')\n }\n if (args && ctx.onModelChange) {\n const target = ctx.models.find((m) => m.id === args || m.name === args)\n if (target) {\n return { kind: 'model', modelId: target.id }\n }\n return i18next.t('model.notFound', { name: args })\n }\n const byProvider = new Map<string, typeof ctx.models>()\n for (const m of ctx.models) {\n const list = byProvider.get(m.provider) ?? []\n list.push(m)\n byProvider.set(m.provider, list)\n }\n const lines: string[] = ['']\n for (const [provider, models] of byProvider) {\n lines.push(` ${provider}:`)\n for (const m of models) {\n const marker = m.id === ctx.currentModel ? ' *' : ' '\n lines.push(` ${marker} ${m.id} — ${m.name}`)\n }\n }\n lines.push('', i18next.t('model.listFooter'))\n return lines.join('\\n')\n },\n })\n\n registry.register({\n name: 'status',\n description: i18next.t('cmdDesc.status')!,\n type: 'action',\n source: 'builtin',\n execute: () => ({ kind: 'status' }),\n })\n\n return registry\n}\n\nexport interface PaletteResult {\n command: string | null\n args: string\n}\n\n/**\n * V2 下 Ink 持有 stdin raw mode,旧 readline 选择器会争抢输入流——\n * bare '/' 退化为路由 /help(列出全部命令),不再弹交互式菜单。\n */\nexport function showCommandPalette(\n _commands: Command[],\n _stdin?: NodeJS.ReadStream,\n _stdout?: NodeJS.WriteStream,\n): Promise<PaletteResult> {\n return Promise.resolve({ command: 'help', args: '' })\n}\n"],"mappings":"uCA4EA,IAAa,EAAb,KAA6B,CAC3B,SAAmB,IAAI,IAGvB,SAAS,EAAoB,CAC3B,GAAI,KAAK,SAAS,IAAI,EAAI,KAAK,CAC7B,MAAU,MAAM,aAAa,EAAI,KAAK,yBAAyB,CAEjE,KAAK,SAAS,IAAI,EAAI,KAAM,EAAI,CAIlC,IAAI,EAAmC,CACrC,OAAO,KAAK,SAAS,IAAI,EAAK,CAIhC,KAAK,EAA0C,CAC7C,IAAM,EAAS,KAAK,SAAS,IAAI,EAAY,CAC7C,GAAI,EAAQ,OAAO,EACnB,IAAK,IAAM,KAAO,KAAK,SAAS,QAAQ,CACtC,GAAI,EAAI,SAAS,SAAS,EAAY,CAAE,OAAO,EAMnD,MAAkB,CAChB,MAAO,CAAC,GAAG,KAAK,SAAS,QAAQ,CAAC,CAIpC,OAAkB,CAChB,MAAO,CAAC,GAAG,KAAK,SAAS,MAAM,CAAC,CAIlC,IAAI,EAAuB,CACzB,OAAO,KAAK,SAAS,IAAI,EAAK,CAIhC,WAAW,EAAuB,CAChC,OAAO,KAAK,SAAS,OAAO,EAAK,GAKrC,SAAgB,GAAyC,CACvD,IAAM,EAAW,IAAI,EA4FrB,OA1FA,EAAS,SAAS,CAChB,KAAM,OACN,YAAa,EAAQ,EAAE,eAAe,CACtC,QAAS,CAAC,IAAK,IAAI,CACnB,KAAM,SACN,OAAQ,UACR,aAAgB,CAAE,KAAM,OAAQ,EACjC,CAAC,CAEF,EAAS,SAAS,CAChB,KAAM,OACN,YAAa,EAAQ,EAAE,eAAe,CACtC,QAAS,CAAC,OAAQ,IAAI,CACtB,KAAM,SACN,OAAQ,UACR,QAAU,GAAS,CACjB,IAAM,EAAU,GAAM,MAAM,EAAI,GAEhC,OADI,IAAY,aAAe,IAAY,KAAa,CAAE,KAAM,OAAQ,QAAS,GAAM,CAChF,CAAE,KAAM,OAAQ,EAE1B,CAAC,CAEF,EAAS,SAAS,CAChB,KAAM,QACN,YAAa,EAAQ,EAAE,gBAAgB,CACvC,KAAM,SACN,OAAQ,UACR,aAAgB,CAAE,KAAM,QAAS,EAClC,CAAC,CAEF,EAAS,SAAS,CAChB,KAAM,QACN,YAAa,EAAQ,EAAE,gBAAgB,CACvC,KAAM,SACN,OAAQ,UACR,aAAgB,CAAE,KAAM,QAAS,EAClC,CAAC,CAEF,EAAS,SAAS,CAChB,KAAM,OACN,YAAa,EAAQ,EAAE,eAAe,CACtC,KAAM,SACN,OAAQ,UACR,aAAgB,CAAE,KAAM,OAAQ,EACjC,CAAC,CAEF,EAAS,SAAS,CAChB,KAAM,QACN,YAAa,EAAQ,EAAE,gBAAgB,CACvC,QAAS,CAAC,IAAI,CACd,KAAM,SACN,OAAQ,UACR,SAAU,EAAM,IAAQ,CACtB,GAAI,CAAC,EAAI,QAAU,EAAI,OAAO,SAAW,EACvC,OAAO,EAAQ,EAAE,mBAAmB,CAEtC,GAAI,GAAQ,EAAI,cAAe,CAC7B,IAAM,EAAS,EAAI,OAAO,KAAM,GAAM,EAAE,KAAO,GAAQ,EAAE,OAAS,EAAK,CAIvE,OAHI,EACK,CAAE,KAAM,QAAS,QAAS,EAAO,GAAI,CAEvC,EAAQ,EAAE,iBAAkB,CAAE,KAAM,EAAM,CAAC,CAEpD,IAAM,EAAa,IAAI,IACvB,IAAK,IAAM,KAAK,EAAI,OAAQ,CAC1B,IAAM,EAAO,EAAW,IAAI,EAAE,SAAS,EAAI,EAAE,CAC7C,EAAK,KAAK,EAAE,CACZ,EAAW,IAAI,EAAE,SAAU,EAAK,CAElC,IAAM,EAAkB,CAAC,GAAG,CAC5B,IAAK,GAAM,CAAC,EAAU,KAAW,EAAY,CAC3C,EAAM,KAAK,KAAK,EAAS,GAAG,CAC5B,IAAK,IAAM,KAAK,EAAQ,CACtB,IAAM,EAAS,EAAE,KAAO,EAAI,aAAe,KAAO,KAClD,EAAM,KAAK,MAAM,EAAO,GAAG,EAAE,GAAG,KAAK,EAAE,OAAO,EAIlD,OADA,EAAM,KAAK,GAAI,EAAQ,EAAE,mBAAmB,CAAC,CACtC,EAAM,KAAK;EAAK,EAE1B,CAAC,CAEF,EAAS,SAAS,CAChB,KAAM,SACN,YAAa,EAAQ,EAAE,iBAAiB,CACxC,KAAM,SACN,OAAQ,UACR,aAAgB,CAAE,KAAM,SAAU,EACnC,CAAC,CAEK,EAYT,SAAgB,EACd,EACA,EACA,EACwB,CACxB,OAAO,QAAQ,QAAQ,CAAE,QAAS,OAAQ,KAAM,GAAI,CAAC"}
@@ -0,0 +1,76 @@
1
+ import e from"i18next";import{initReactI18next as t}from"react-i18next";const n={en:{translation:{cmd:{titleInfo:`Info`,titleShell:`Shell`,titleOpen:`Open File`,openNotFound:`File not found: {{path}}`,openBinaryRejected:`Cannot preview binary file: {{path}}`,openBrowserSubtitleRoot:`workspace root`,openBrowserSubtitleDir:`{{relDir}}`,titleMemory:`Memory`,titleExit:`Exit`,titleUpdate:`Update`,titleAborted:`Aborted`,titleLanguage:`Language`,titlePermission:`Permission`,titlePaused:`Paused`,runAborted:`Run aborted`,runWillPauseAfterTurn:`Will pause after the current turn finishes`,noRunningTask:`No task is currently running`,noRunningTaskToPause:`Agent already finished this turn — nothing to pause`,notPaused:`No paused run to continue`,runResumedByCommand:`Resumed`,nothingToPause:`No running task to pause`,pauseCancelled:`Pause request cancelled`,titlePauseRequested:`Pause requested`,memoryDisabled:`Memory is not enabled (no storage)`,memorySaved:`✓ Remembered “{{name}}” → .otto/memory/ (in context from the next turn)`,dangerousBlocked:`Dangerous command blocked: {{reason}}`,dangerousBlockedDetail:`Blocked dangerous command ({{reason}}): {{cmd}}
2
+ Use the bash tool via the agent for privileged operations.`,noModelConfigured:`No model configured yet — type /setup to see onboarding progress, or /model to pick one directly.`,todoGateContinuing:`Continuing {{round}}/{{cap}}… {{left}} remaining`,budgetExtended:`Tool budget extended (+{{maxTurns}} turns)`,budgetProgressDenied:`No progress in budget window (loop suspected) — asked model to wrap up`,budgetSteered:`Tool budget exhausted ({{maxTurns}}/window) — asked model to wrap up`,progressStallDetected:`Stall detected (same tool call repeated {{maxRepeat}}× without progress) — asked model to change approach`,toolCallMismatchRetry:`Response format issue: model claimed a tool call but sent none — auto-corrected and retrying ({{retryCount}})`,toolCallMismatchTerminated:`Response format issue persisted — stopped. Please resend, or try a different model.`,pressCtrlCAgain:`Press Ctrl+C again to exit`,updateToast:`otto v{{latest}} available — type /upgrade`,updateNotifAvailable:`otto v{{latest}} available (current v{{current}})`,updateNotifForced:`otto v{{latest}} forced upgrade (current v{{current}})`,updateForcedBanner:`otto v{{latest}} is a required update. Current: v{{current}}.
3
+
4
+ Type /upgrade --force to install and restart now.`,titleMemoryPressure:`Memory pressure`,memoryPressureRestartNow:`Restart now`,memoryPressureRemindLater:`Remind me later`,titleAutoCompact:`Auto-compact`,autoCompactFailed:`Automatic context compaction failed: {{msg}}`,titleFleetBudget:`Process fleet`,fleetBudgetExceeded:"{{processCount}} otto processes using {{totalRssMb}}MB total - over budget. Run `otto ps` to inspect and sweep orphans.",restartChainDeep:`This session has been restarted {{generation}} times - each restart leaves a chaperone process in the chain. Exit fully and reopen the terminal to release them.`,memoryPressureSuppress:`Don't ask again this session`,memoryPressureResumeAbortedMessage:`Memory pressure is still high after restart — auto-resume was skipped. Your unfinished message is preserved in history; resend it manually when ready.`,memoryPressureResumeFailedMessage:`Auto-resume failed after restart. Please resend your message manually.`,titleStaleBuild:`New build detected`,staleBuildMessage:`You are running build {{current}}, but build {{latest}} is already available on disk. Consider /exit to restart and pick up the latest fixes.`,titleContextPressure:`Context usage`,contextPressureApproaching:`Context usage at {{pct}}%, approaching the auto-prune threshold`,contextPressureNearing:`Context usage at {{pct}}%, within the auto-prune range`,contextPressureCritical:`Context usage at {{pct}}%, auto-compaction imminent`,titleError:`Error`,resumeNotFound:`Session "{{id}}" not found — started a new session.`,modelsRefreshed:`Models refreshed: {{summary}} (/model to view, ✓ = available)`,modelsRefreshedEmpty:`Model refresh: no providers to pull from (using cache/built-in)`,titleSetupRequired:`Setup required`,titleSetupReady:`Ready`,setupReadyMessage:`Model ready — just type a message to start!`,modelNotSupported:`This model may not be supported by your account. Type /model to pick one marked ✓ (available), or /model refresh.`,rateLimitedRetriesExhausted:`The current model hit a server-side rate limit (not an account quota exhaustion) and automatic retries were exhausted. Retry shortly, or type /model to switch to another available model.`,requestFailed:`Request failed: {{msg}}`,resumeContinueLabel:`Continue this session:`,titleEffort:`Effort`,selectEffortTitle:`Select reasoning effort`,selectLanguageTitle:`Language`,titlePreference:`Preferences`,preferenceUsage:`Usage: /preference [general|lang|theme]`,prefOptionLang:`Language`,prefOptionTheme:`Theme`,prefOptionGeneral:`General`,prefDescGeneral:`General behavior, notifications & personalization`,prefDescLang:`Interface display language`,prefDescTheme:`Color appearance (dark / light / system)`,selectGeneralTitle:`General`,genNickname:`Nickname`,genNicknameDesc:`Name shown in sessions & notifications`,genNicknameInputTitle:`Enter nickname`,genNicknamePlaceholder:`Your name…`,genCompletionNotice:`Completion notice`,genCompletionNoticeDesc:`Notify when a task completes`,genSound:`Sound`,genSoundDesc:`Play a sound with notifications`,genUpdateCheck:`Update check`,genUpdateCheckDesc:`Check for updates on startup (notify only)`,toggleOn:`On`,toggleOff:`Off`,genSaved:`Saved`,genSkillLoop:`Skill Loop`,genSkillLoopMissing:`Not installed`,genSkillLoopMissingHint:`Install plugin-skill-inductor to enable`,genSkillLoopEntryDesc:`Auto-extract reusable skills from conversations`,genSkillLoopOn:`On`,genSkillLoopOff:`Off`,genSkillLoopThresholdTitle:`Trigger Threshold`,genSkillLoopThresholdDesc:`Number of messages before skill extraction triggers`,genSkillLoopThreshold:`Threshold`,genSkillLoopThr4:`4 messages (aggressive)`,genSkillLoopThr4Desc:`Triggers after very few messages; for heavy use`,genSkillLoopThr6:`6 messages (default)`,genSkillLoopThr6Desc:`Balanced trigger frequency and quality`,genSkillLoopThr12:`12 messages (conservative)`,genSkillLoopThr12Desc:`Triggers after longer conversations; more stable`,genSkillLoopThr20:`20 messages (very conservative)`,genSkillLoopThr20Desc:`Triggers only in long conversations`,genSkillLoopCooldownTitle:`Cooldown`,genSkillLoopCooldownDesc:`Days before skill extraction can trigger again`,genSkillLoopCooldown:`Cooldown`,genSkillLoopCd3:`3 days`,genSkillLoopCd14:`14 days (default)`,genSkillLoopCd30:`30 days`,genSkillLoopCd365:`365 days`,genSkillLoopCdDays:`{{n}} days`,genSkillLoopStatus:`Skill Loop Status`,genSkillLoopStatusDesc:`View extraction history and skill candidates`,skillLoopOnOff:`On/Off`,skillLoopPanelTitle:`Skill Loop`,skillLoopStatusTitle:`Skill Loop Status`,skillLoopStatusNotInstalled:`Plugin not installed`,skillLoopStatusSuccess:`Successful extractions`,skillLoopStatusPending:`Pending`,skillLoopStatusCandidates:`Skill candidates`,skillLoopStatusCooling:`Cooling down`,skillLoopStatusCount:`count`,skillLoopStatusEpisodes:`episodes`,skillLoopStatusTimes:`times`,skillLoopStatusGroupRecent:`Recent`,skillLoopStatusGroupPending:`Pending`,compatTrusted:`Trusted`,langDescZh:`Simplified Chinese interface`,langDescEn:`English interface`,langDescAuto:`Follow system environment (LANG)`,themeDescDark:`Dark palette, best for low light`,themeDescLight:`Light palette, best for bright light`,themeDescSystem:`Follow terminal / system appearance`,themeUsage:`Unknown theme. Available: dark|light|system. Run /preference theme (no args) to also pick color presets.`,themeDarkPresetOption:`Dark preset`,themeDarkPresetDesc:`Color preset used for dark appearance`,themeLightPresetOption:`Light preset`,themeLightPresetDesc:`Color preset used for light appearance`,themePresetTitleDark:`Dark preset`,themePresetTitleLight:`Light preset`,themePresetBuiltin:`Built-in`,themePresetFromExtension:`From {{id}}`,themePresetReset:`Reset to default`,themePresetResetDesc:`Use the built-in preset for this appearance`,themePresetSaved:`Theme preset saved: {{label}}`,selectCancelled:`Cancelled`,titleCompat:`Trust`,titlePermissions:`Permissions`,titleUpgrade:`Upgrade`,titleCommands:`Commands`,effortUnknown:`Unknown: {{arg}}. Available: {{levels}}`,compatTrusting:`Trusted this project’s .claude executable config — hot-reloading…`,compatReloadFailed:`Reload failed: {{err}}`,compatUntrusted:`Trust revoked (.claude executable surfaces skipped from next startup)`,compatNone:`This project has no .claude executable config (.mcp.json / .claude/commands).`,compatTrustedLabel:`trusted`,compatUntrustedLabel:`untrusted — these surfaces are skipped; type /compat trust to enable`,compatConfigGated:`.otto/config.json high-risk keys ignored ({{keys}}) — type /compat trust to enable`,compatConfigActive:`.otto/config.json high-risk keys active ({{keys}}) — trusted`,listSep:`, `,permsCleared:`Cleared the always-allow list — future actions will prompt again`,upgradeChecking:`Checking for updates… (current v{{current}})`,upgradeNoNetwork:`Cannot reach the npm registry — check your network and retry.`,upgradeLatest:`Already on the latest version v{{current}}`,upgrading:`Upgrading…`,upgradeFailed:`Upgrade failed: {{err}}`,unknownError:`unknown error`,permsSessionLabel:`This session’s always-allow:`,permsProjectLabel:`Project-level always-allow:`,permsClearHint:`Clear this session: /permissions clear`,permsManageHint:`Manage project-level: /permissions add bash(git status) · /permissions remove <entry>`,permsInvalidEntry:`Invalid entry "{{entry}}" — use a tool name like "read" or "bash(git status)" (empty parens "bash()" not allowed)`,permsAdded:`Added to project always-allow: {{entry}}`,permsRemoved:`Removed from project always-allow: {{entry}}`,permsNotFound:`Not in the project always-allow list: {{entry}}`,permsEmpty:`(empty)`,helpGroupSession:`Session`,helpGroupModel:`Model & auth`,helpGroupAgent:`Agent management`,helpGroupDebug:`Debug & diagnostics`,helpGroupUi:`Interface`,helpGroupOther:`Other`,helpPrefixes:`Prefixes`,helpPrefixShell:`Run as shell command`,helpPrefixFile:`Read file into context`,titleJob:`Job`,titleReverted:`Reverted`,titleDelegated:`Delegated`,titlePlugin:`Plugin`,titleExtension:`Extension`,extCategoryLabel:`{{category}}`,extListTitle:`Extensions — {{enabled}}/{{total}} enabled`,extListEmptyTitle:`Extensions — none available`,extListEmptyOption:`No pluggable extensions (add MCP servers / skills / agents / plugins)`,extDiscoverHint:`More plugins available in registries`,extDiscoverButton:`Discover`,jobUsage:`Usage: /job <what to do> — delegate a background agent job (worktree-isolated, full tools). /delegates for progress, /job revert <id> to undo.`,jobReverted:`Job {{id}} reverted: {{msg}}`,jobRevertFailed:`✗ Revert of job {{id}} incomplete ({{status}}): {{msg}}{{conflicts}}`,jobConflictFiles:`
5
+ Conflicting files:
6
+ {{joinedPaths}}`,delegated:`{{title}}
7
+ See progress in the /delegates pane`,delegateFailed:`Delegation failed: {{err}}`,extEnableLabel:`Enable`,extDisableLabel:`Disable`,extReconnectLabel:`↻ Reconnect`,extReloadLabel:`Reload`,extMcpTitle:`{{name}} — status {{status}} · pick an action · Esc to close`,extItemTitle:`{{name}} — pick an action · Esc to close`,extPluginGroupTitle:`Plugin Info`,extPluginLabelDesc:`Description`,extPluginLabelScope:`Scope`,extPluginLabelTrust:`Trust`,extPluginLabelSurfaces:`Contributes`,extPluginLabelContributions:`Axes`,extPluginLabelStatus:`Status`,extSkillGroupOverview:`Overview`,extSkillLabelDesc:`Description`,extSkillLabelStatus:`Status`,extSkillLabelSource:`Source`,extSkillGroupTrigger:`Trigger`,extSkillLabelTriggerMode:`Mode`,extSkillLabelPriority:`Priority`,extSkillGroupDependencies:`Dependencies`,extSkillLabelDependencies:`Depends on`,extSkillGroupTags:`Tags`,extSkillLabelTags:`Tags`,extSkillGroupError:`Error`,extSkillNoDependencies:`No dependencies`,extSkillNoTags:`No tags`,extSkillTriggerAuto:`Auto (matched by description)`,extSkillTriggerManual:`Manual (explicit call only)`,extViewFullTextLabel:`View full text`,extSkillFullTextTitle:`{{name}} — SKILL.md body`,extSkillNoBody:`(no body content)`,extAgentGroupOverview:`Overview`,extAgentLabelDesc:`Description`,extAgentLabelStatus:`Status`,extAgentGroupCapabilities:`Task & Capabilities`,extAgentLabelTaskTypes:`Task types`,extAgentLabelCapabilities:`Capabilities`,extAgentGroupTools:`Tool permissions`,extAgentLabelDefaultTools:`Default tool allowlist`,extAgentLabelDisallowedTools:`Disallowed tool denylist`,extAgentGroupExecution:`Execution config`,extAgentLabelPromptMode:`Prompt injection mode`,extAgentLabelModelTier:`Preferred model tier`,extAgentLabelAllowSubagents:`Allow sub-agent delegation`,extAgentNoTaskTypes:`not declared`,extAgentNoCapabilities:`not declared`,extAgentAllTools:`inherits all (unrestricted)`,extAgentNoDisallowedTools:`none`,extAgentFullTextTitle:`{{name}} — system prompt template`,extPluginTrustLabel:`Trust executable surfaces`,extPluginUntrustLabel:`Revoke trust`,extPluginOpenPanelLabel:`{{title}}`,extPluginTrusted:`trusted`,extPluginUntrusted:`untrusted (project — executable surfaces gated)`,extPluginNoSurface:`no executable surface (always trusted)`,extPluginCapabilityPending:`trusted · high-risk capabilities pending ({{caps}})`,extToggleFailed:`Toggle failed: {{err}}`,extToggleReloadFailed:`{{verb}} {{name}}, but reloading capabilities failed: {{err}} (state saved, retry reload)`,extReconnectUnavailable:`Cannot reconnect {{id}} (not configured or MCP not ready)`,extReconnected:`Reconnected {{id}}`,extReconnectFailed:`Reconnect {{id}} failed: {{err}}`,extLogSectionTitle:`Recent logs`,extNoLogs:`No logs yet`,extRefreshHint:`r refresh`,errorRetryPluginSource:`From plugin: {{pluginId}}`,pluginNotFound:`Plugin "{{id}}" not found (under <.otto>/plugins/)`,pluginTrusting:`Trusted plugin {{id}}’s executable surfaces — hot-reloading…`,pluginUntrusted:`Revoked trust for {{id}} (its executable surfaces skipped from next discovery)`,pluginTrustConfirmTitle:`Trust plugin "{{id}}"?`,pluginTrustConfirmIntro:`Trusting enables its executable surface — this runs code:`,pluginSurfaceMcp:`.mcp.json — launches MCP server binaries`,pluginSurfaceCommands:`commands/ — !cmd expands to a shell command`,pluginSurfaceScripts:`postinstall/setup — runs shell on install/first load`,pluginSurfacePanels:`panels — runs in-process code in the TUI`,pluginSurfaceSkills:`skills/ — injects prompt content the model may follow`,pluginSurfaceAgents:`agents/ — injects an agent profile (inherits all tools by default)`,pluginCapabilityIntro:`This plugin requests the following high-risk capabilities:`,pluginCapabilityProvider:`provider — registers an LLM provider, handling your credentials and request traffic`,pluginCapabilityTools:`tools — registers tools callable by agents`,pluginCapabilityTuiRenderer:`tui.renderer — runs custom rendering code inside the TUI process`,pluginCapabilityNetwork:`network — makes arbitrary network requests`,pluginCapabilityWireProtocol:`wire-protocol — intercepts all provider requests/responses, including credentials`,pluginCapabilityA2uiComponent:`a2ui.component — runs custom rendering code inside the TUI process`,pluginCapabilityPanelBackend:`panel.backend — panel can drive backend actions with side effects`,pluginCapabilityInputResolver:`input.resolver — expands @ references at submit time, injecting content into the prompt`,pluginCapabilityA2uiRenderer:`a2ui.renderer — runs custom code to render messages across TUI and web-ui`,pluginTrustConfirmHint:`Only trust plugins whose source you have reviewed.`,pluginTrustConfirmAction:`Trust`,scopeGlobal:`global`,scopeProject:`project`,scopeRepository:`repository`,commonCancel:`Cancel`,commonClose:`Close`,unknownLabel:`(unknown)`,titleInstall:`Install`,titleDryRun:`Dry-run`,titleUninstall:`Uninstall`,installUsage:`Usage: /install [--global] [--here] [--force] [--dry-run] [--as plugin|skill|mcp] <source>
8
+ source local .zip/.tar.gz path, HTTP URL, git address, or npm package name
9
+ --global install to user-level ~/.otto/ (default: project-level .otto/)
10
+ --here install to the current dir .otto/ (bypass workspace-root lookup; exclusive with --global)
11
+ --force overwrite an existing extension of the same name
12
+ --dry-run preview the install plan, then confirm
13
+ --as <type> force the content type: plugin / skill / mcp`,installMutuallyExclusive:`--global and --here are mutually exclusive; specify only one.`,installLoadingHint:`(probing, please wait)`,dryRunDetectFailed:`Detection failed: {{err}}`,dryRunPreviewOk:`Preview: {{name}} — detection passed`,planSourcePrefix:`Source:`,installActionLabel:`Install`,installFailed:`Install failed: {{err}}`,capRefreshedInstall:`Capabilities refreshed; the new extension applies next turn`,installedRefreshErr:`Installed, but refresh errored: {{err}}. Run /reload to refresh manually.`,pluginInstallConfirmTitle:`Install {{name}}`,pluginInstallConfirmAction:`Install & authorize`,pluginInstallInvalidName:`Invalid plugin name: {{name}}`,pluginInstallNotFound:`Package {{pkg}} not installed. Run pnpm install first, or use /install to install from local path.`,pluginInstallCancelled:`Install cancelled`,pluginInstallFailed:`Install failed: {{err}}`,pluginInstallPendingCaps:`{{id}} installed — some capabilities need authorization in /extension`,uninstallActionLabel:`Uninstall`,uninstalled:`{{type}} "{{name}}" uninstalled from {{scope}}`,uninstallRefreshed:`Capabilities refreshed`,uninstalledRefreshErr:`Uninstalled, but refresh errored: {{err}}`,uninstallConfirmTitle:`Uninstall {{type}} "{{name}}"?`,uninstallConfirmScope:`Scope: {{scopeLabel}} · the following will be deleted (irreversible):`,uninstallConfirmYes:`Uninstall`,uninstallFailed:`Uninstall failed: {{err}}`,titleModel:`Model`,titleModels:`Models`,titleLogin:`Login`,titleLogout:`Logout`,commonNo:`No`,commonSelect:`Select`,modelRefreshLineOk:` ✓ {{provider}} +{{added}} new · {{kept}} known · {{total}} available`,modelRefreshLineErr:` ⚠ {{provider}} {{status}} ({{reason}})`,modelRefreshLineMuted:` ○ {{provider}} {{reason}}`,modelRefreshLineWarning:` ⚠ {{provider}} {{reason}}`,modelRefreshReasonNotAuthenticated:`not authenticated (no action needed)`,modelRefreshReasonPendingCapability:`capability pending — trust the plugin in /extension`,modelRefreshHint:`Run /model again to see the fetched list (✓ = available on your account).`,modelDelegateProviderTitle:`No "{{cand}}" provider — delegate a background job to implement it?`,modelDelegateProviderYes:`Yes, delegate a background agent job to implement the {{cand}} provider (worktree-isolated)`,modelProviderDelegated:`Implementing {{cand}} provider — /delegates to track progress`,modelNotFoundUse:`Not found: {{arg}}. Use /model to pick.`,modelSelectTitle:`Select model`,modelSelectTitleAvail:`Select model (subscription/key = billing)`,modelRecentGroup:`Recently used`,loginNoProviders:`No providers available`,loginNotSet:`not set`,loginPickProvider:`Authenticate provider`,loginAuthMethod:`{{name}} — auth method`,loginMethodOauth:`Browser OAuth (recommended)`,loginMethodKey:`Paste API key`,loginKeyTitle:`{{provider}} API key`,loginKeyPlaceholder:`paste key (hidden)`,loginCancelledNoKey:`Cancelled — no key entered`,loginKeySaved:`✓ Saved API key for {{provider}}`,loginOauthCodeIntro:`Open this URL and enter the code shown below:`,loginOauthCode:`Code: {{code}}`,loginOauthTitle:`{{provider}} OAuth`,loginOauthUrlAuthorize:`Open this URL to authorize:`,loginOauthPasteCode:`{{provider}} OAuth — paste the code shown after authorizing`,loginOauthBrowserOpened:`Browser opened for authorization…`,loginOauthOpenBrowserButton:`Open Browser`,loginSuccess:`✓ Logged in to {{provider}}`,loginFailed:`Login failed: {{msg}}`,logoutNoStored:`No stored credentials to remove`,logoutPickProvider:`Logout provider`,logoutSuccess:`✓ Logged out {{provider}}`,serviceLoginUsage:`usage: /auth --service <url> --token <val>`,serviceLoginNeedValues:`both --service and --token require a value`,serviceLoginFailed:`service login failed: {{err}}`,serviceLoginBadResponse:`service login failed: invalid response from server`,serviceLoginSuccess:`✓ Logged in to {{url}} (user: {{user}})`,serviceLogoutRemoved:`✓ Service identity removed`,serviceLogoutNotFound:`No service identity found`,serviceLogoutFailed:`failed: {{err}}`,titleCleared:`Cleared`,titleResume:`Resume`,titleReload:`Reload`,titleDiagnose:`Diagnose`,titleArchive:`Archive`,titleUnarchive:`Unarchive`,titlePin:`Pin`,titleUnpin:`Unpin`,pinGroupDone:`{{idShort}} · {{title}} pinned to {{group}}`,pinGroupMissingValue:`Usage: /pin --group <name> [<session-id>...] (missing group name after --group)`,clearedDone:`Conversation reset — context released (history still time-travelable)`,sessionNoMatch:`No session matching "{{arg}}"`,resumeAlreadyOn:`Already on this session`,resumeSessionNotFound:`Session {{idShort}} not found`,resumeSwitched:`{{idShort}} · {{count}} msgs`,resumeNoSaved:`No saved sessions`,resumeFailed:`Resume failed: {{msg}}`,agoJustNow:`just now`,agoSeconds:`{{n}}s ago`,agoMinutes:`{{n}}m ago`,agoHours:`{{n}}h ago`,agoDays:`{{n}}d ago`,resumeSubtitle:`{{sessions}} sessions · {{msgs}} msgs · most recent {{recent}}`,resumeSelectTitle:`Resume session — {{n}} available`,resumeArchivedSuffix:` (archived)`,resumeReadOnlySuffix:` (read-only)`,resumePinnedPrefix:`* `,resumeStatusBusy:`running`,resumeStatusNeedsInput:`needs input`,resumeStatusIdle:`idle`,resumeDefaultPinGroup:`Pinned`,resumeRecentGroup:`Recent`,reloadDone:`MCP tools {{mcpTools}} · models {{models}} · agents {{agents}} · teams {{teams}}`,reloadFailed:`Reload failed: {{msg}}`,diagnoseNone:`No recurring hard failures to propose`,diagnoseLine:`{{n}}. [{{signalKind}} ×{{count}}] {{directive}}
14
+ fix via job: /job {{directive}}`,diagnoseSummary:`Diagnosed {{count}} improvement proposal(s) (L1 — needs your review; runs only when delegated)`,archiveCannot:`Session {{idShort}} does not exist or cannot be archived`,archiveDone:`{{idShort}} · {{title}} archived (run /archive again to undo)`,unarchiveNotLoaded:`Session {{idShort}} is not loaded in memory`,unarchiveDone:`{{idShort}} · {{title}} unarchived`,pinNotLoaded:`Session {{idShort}} is not loaded in memory`,pinDone:`{{idShort}} · {{title}} pinned`,unpinDone:`{{idShort}} · {{title}} unpinned`,titleSessionUnlock:`Session Unlock`,unlockUsage:`Usage: /session unlock <session-id> [--force]`,unlockNotLocked:`Session {{idShort}} is not locked — nothing to unlock`,unlockInspect:`{{idShort}} is locked by pid={{pid}} on {{hostname}} ({{aliveLabel}}, last heartbeat {{mtimeAgoSec}}s ago).
15
+ Run "/session unlock {{idShort}} --force" to force-release it.`,unlockAliveConfirmed:`confirmed alive`,unlockDeadConfirmed:`confirmed dead`,unlockUnknownAlive:`liveness unknown (different host or legacy lock)`,unlockRecentReleaseHint:`Note: this lock was released very recently (< 5s ago) — it may just be a normal handoff in progress (e.g. another otto process exiting). Consider retrying before forcing unlock on session {{idShort}}.`,unlockHungWarning:`Warning: session {{idShort}}'s lock holder process is confirmed alive but its heartbeat has stopped — this looks like a hung process, not a normal live writer.`,unlockConfirmTitle:`Force-unlock a session held by a live process?`,unlockConfirmMessage:`Session {{idShort}} is currently held by a LIVE process (pid={{pid}}, host={{hostname}}).
16
+
17
+ Forcing this unlock while that process is still writing may cause data races —
18
+ both processes could end up saving conflicting changes.
19
+
20
+ Only proceed if you are certain that process is hung/unresponsive, not just slow.`,unlockConfirmLabel:`Force unlock anyway`,unlockCancelLabel:`Cancel`,unlockForcedDone:`{{idShort}} force-unlocked — the next save from a live process will succeed`,unlockCancelled:`Force unlock cancelled`,titleSessionCmd:`Session`,sessionUsage:`Usage: /session <fork|unlock> [...]`,titleSessionFork:`Session Fork`,forkFailed:`Failed to fork the current session`,forkSuccess:`Forked and switched to new session {{idShort}}`,forkNameTitle:`Name the forked session`,forkSuccessNamed:`Forked and switched to "{{title}}"`,resumeArchivedOnlyTitle:`Archived sessions — {{n}} total`,titleInspector:`Inspector`,titleBreakpoints:`Breakpoints`,titleBreakpoint:`Breakpoint`,titleReplay:`Replay`,titleStatus:`Status`,inspectUnavailable:`Debugging unavailable (Inspector not enabled)`,bpAllCleared:`All breakpoints disabled`,inspectUnknownArg:`Unknown arg "{{arg}}" — /inspect sources to see all`,replayNoTrace:`No recorded trace for session "{{id}}"`,statusModelUnset:`(unset)`,statusLineTitle:`Title: {{title}}`,statusLineSessionId:`Session ID: {{idShort}}`,statusLineModel:`Model: {{model}}`,statusLineMsgs:`Messages: {{n}}`,statusLineCumOutput:`Cumulative output tokens: {{n}}`,statusLineWriteLeaseReadOnly:`Write access: read-only (lease held by another process)`,statusLineWriteLeaseOk:`Write access: normal`,statusLineRunPaused:`Run status: paused (type to continue or /continue)`,statusRowTitle:`Title`,statusRowSessionId:`Session ID`,statusRowModel:`Model`,statusRowMsgs:`Messages`,statusRowOccupancy:`Context occupancy`,statusRowCumOutput:`Cumulative output tokens`,statusRowWriteAccess:`Write access`,statusValueOccupancy:`{{occ}} / {{window}}{{seg}}`,statusValueWriteLeaseReadOnly:`Read-only (lease held by another process)`,statusValueWriteLeaseOk:`Normal`,titleUsage:`Usage`,usageNotSubscription:`Usage quota display is only available for Anthropic OAuth subscription plans (Claude Pro/Max). API key / other providers use standard per-minute rate limits instead.`,usageNoSnapshotYet:`No usage snapshot yet — send a message first, then run /usage again.`,usageLineType:`Limit: {{type}}`,usageLineStatus:`Status: {{status}}`,usageLineResetsAt:`Resets: {{when}}`,usageLinePercent:`Used: {{pct}}%`,usageLineStandardLimits:`API limits: {{reqR}}/{{reqL}} req, {{tokRk}}k/{{tokLk}}k tok, reset {{reset}}s`,usageSubPoolNotInHeaders:`Subscription pool quota is not available via API headers — check chatgpt.com usage dashboard instead.`,titleAbout:`About otto`,aboutVersion:`Version`,aboutBranch:`Branch`,aboutCommit:`Commit`,aboutRuntime:`Runtime`,aboutCPU:`CPU`,aboutMemory:`Memory`,aboutShell:`Shell`,aboutTerminal:`Terminal`,aboutModel:`Model`,aboutModelNotSet:`(not set)`,aboutSession:`Session ID`,aboutUpdateHint:`Run /upgrade to check for updates.`,aboutGroupVersion:`Version`,aboutGroupRuntime:`Runtime`,aboutGroupSession:`Session`,titleCompact:`Compact`,memoryUserSaved:`✓ Remembered "{{name}}" → ~/.otto/memory (user-level, cross-project)`,memoryForgetUsage:`Usage: /memory forget <name>`,memoryDeleted:`✓ Deleted memory "{{name}}"`,memoryNotFound:`Memory "{{name}}" not found`,memoryDialogEmptyHint:"No memory entries yet — type `#content` to save one across sessions",memoryDialogDetailTitle:`{{name}} ({{source}})`,memoryDialogDetailSourceProject:`Project memory`,memoryDialogDetailSourceUser:`User memory`,memoryDialogDetailEmpty:`(no content)`,memoryDialogConfirmForgetTitle:`Delete memory`,memoryDialogConfirmForgetMessage:`Delete "{{name}}"? This cannot be undone.`,memoryDialogHintView:`view`,memoryDialogHintForget:`delete`,memoryDialogHintBack:`back`,titleShortcuts:`Shortcuts Manager`,shortcutsPanelEmptyHint:`No shortcuts yet. Press n to create your first one.`,shortcutsPanelListHint:`Defined`,shortcutsPanelNewTitle:`New Shortcut`,shortcutsPanelEditTitle:`Edit shortcut "{{name}}"`,shortcutsPanelNameLabel:`Name (follows @, e.g. review):`,shortcutsPanelTextLabel:`Expansion text (replaces [@shortcut:name] on submit):`,shortcutsPanelNameInvalid:`Name may only contain letters, digits, underscore, hyphen`,shortcutsPanelNameDuplicate:`This name is already in use`,shortcutsPanelTextEmpty:`Expansion text cannot be empty`,shortcutsPanelConfirmDeleteTitle:`Delete Shortcut`,shortcutsPanelConfirmDeleteMessage:`Confirm delete "{{name}}"? This cannot be undone.`,shortcutsPanelHintNew:`new`,shortcutsPanelHintEdit:`edit`,shortcutsPanelHintDelete:`delete`,compactFailed:`Compaction failed: {{msg}}`,titleUpgradeCheck:`Extension Upgrade Check`,upgradeCheckScanning:`Checking extension versions…`,upgradeCheckNoVersioned:`No versioned installed extensions found (skill/plugin).`,upgradeCheckLineUpdate:`{{tag}} {{name}} v{{installed}} → v{{latest}} *update available*`,upgradeCheckLineLatest:`{{tag}} {{name}} v{{installed}} (latest)`,upgradeCheckSummary:`{{count}} extension(s) can be updated; run /install --force to reinstall and upgrade.`,upgradeCheckFailed:`Version check failed: {{err}}`,titleSessionResumed:`Session resumed`,titleSession:`Session`,resumeTodosAllDone:`Previous tasks were all completed.`,bgForbiddenZone:`
21
+ ⚠️ This change touches a governance no-go zone ({{count}} file(s), high-risk self-modification):
22
+ {{files}}
23
+ Review carefully; if wrong, run /job revert {{id}} immediately.`,bgJobApplied:`✓ Applied job {{id}}: {{message}} (undo: /job revert {{id}}){{zone}}`,bgConflictFiles:`
24
+ Conflicting files:
25
+ {{joined}}`,bgJobIncomplete:`✗ Job {{id}} did not complete ({{status}}): {{message}}{{conflicts}}`,bgAutoReloadFailed:`Auto hot-reload failed (run /reload manually): {{msg}}`,modelCompactedFor:`Compacted for {{window}} window`,grillRecommendation:`
26
+ Recommendation: {{rec}}`,grillEvidence:`
27
+ Evidence:
28
+ {{joined}}`,grillFreeformPlaceholder:`Enter your own option / extra info…`,grillAnswerPlaceholder:`Type your answer…`,titleBackgroundTask:`Background Task`,lifecycleCrossBoundaryDone:`"{{toolName}}" finished (started in a previous task — result not added to this conversation)`,lifecycleCrossBoundaryFailed:`"{{toolName}}" failed (started in a previous task — result not added to this conversation)`,titleFeedback:`Feedback`,feedbackStepTitle:`Short title for the issue`,feedbackStepRepro:`Steps to reproduce (optional)`,feedbackStepExpected:`Expected behavior (optional)`,feedbackStepActual:`Actual behavior (optional)`,feedbackConfirmTitle:`Submit feedback?`,feedbackConfirmMessage:`Title: {{title}}
29
+
30
+ {{bodyPreview}}`,feedbackChannelSubmitting:`Submitting…`,feedbackRepoUnresolved:`Could not resolve a target repository — set "feedback_repo" in .otto/config.json`,feedbackCreated:`Opened: {{url}}`,feedbackUnavailable:`Feedback plugin is not available (disabled or not installed)`,compatTrusted_one:`Trusted · {{count}} MCP tool`,compatTrusted_other:`Trusted · {{count}} MCP tools`,resumeProbeHiddenHint_one:`({{count}} probe session hidden, use /resume --all to view)`,resumeProbeHiddenHint_other:`({{count}} probe sessions hidden, use /resume --all to view)`,resumeArchivedHiddenHint_one:`({{count}} archived session hidden, use /resume --archived to view)`,resumeArchivedHiddenHint_other:`({{count}} archived sessions hidden, use /resume --archived to view)`,memoryDialogProjGroup_one:`Project memory (.otto/memory) · {{count}} entry`,memoryDialogProjGroup_other:`Project memory (.otto/memory) · {{count}} entries`,memoryDialogUserGroup_one:`User memory (~/.otto/memory) · {{count}} entry`,memoryDialogUserGroup_other:`User memory (~/.otto/memory) · {{count}} entries`,pluginTrusted_one:`Trusted {{id}} · {{count}} MCP tool`,pluginTrusted_other:`Trusted {{id}} · {{count}} MCP tools`,resumeRestored_one:`↻ Resumed session {{idShort}} ({{count}} past message in context; continuing from here)`,resumeRestored_other:`↻ Resumed session {{idShort}} ({{count}} past messages in context; continuing from here)`,"imageDegradationNotice_image-constraint_one":`{{count}} older image dropped (exceeded provider image limits)`,"imageDegradationNotice_image-constraint_other":`{{count}} older images dropped (exceeded provider image limits)`,imageDegradationNotice_other_one:`{{count}} older image dropped to fit context`,imageDegradationNotice_other_other:`{{count}} older images dropped to fit context`,promptBudgetExceeded_tokens:`Output-token budget exceeded ({{used}}/{{budget}}) — asked model to wrap up`,promptBudgetExceeded_other:`Time budget exceeded ({{used}}/{{budget}}) — asked model to wrap up`,sessionCostBudgetExceeded:"Session cost budget exceeded (${{used}}/${{budget}}) — not blocking, check /cost for details",memoryPressureMessage:`otto's memory usage is high ({{usedPct}}% of the heap limit). Restarting now will save all progress and continue safely, avoiding an unpredictable crash.`,authFailed:`Authentication failed — the API key for the current model{{ps}} is invalid or expired. Type /auth{{ls}} to reconfigure credentials, then retry.`,authRefreshFailed:`Login refresh failed{{ps}} — this may be a network issue or a concurrent refresh conflict across multiple otto processes. Please retry shortly; if it keeps failing, run /auth{{ls}} to re-authenticate.`,extToggled:`{{verb}} {{name}}{{seg}}`,pluginUsage:`Usage: /trust plugin {{seg}}<id>`,installedTo:`{{name}} installed to {{scope}}{{seg}}`,statusLineOccupancy:`Context occupancy: {{occ}} / {{window}}{{seg}}`,extPluginTitle:`{{name}} — {{state}} · pick an action · Esc to close`,extSkillTitle:`{{name}} — {{state}} · pick an action · Esc to close`,extAgentTitle:`{{name}} — {{state}} · pick an action · Esc to close`,bpToggled:`{{point}} {{state}}`,pluginInstalled:`{{seg}}`,pinBatchSummary:`{{seg}}`,extSkillSourceLabel:`{{seg}}`,upgradeAvailableLines:[`Current: v{{current}}`,`Latest: v{{latest}}`,``,`Hot-upgrade flow: npm install -g @x-otto/cli@latest → auto-restart`,``,`⚠ The current session will be interrupted during the upgrade.`,`Type /upgrade --force to confirm.`],extHealthSummary:`health {{hookTimeouts}} hook timeout(s) · {{toolTimeouts}} tool timeout(s)`,extHealthSummary_err:`health {{hookTimeouts}} hook timeout(s) · {{toolTimeouts}} tool timeout(s) · last error: {{lastError}}`,keybindTitle:`Keybindings`,keybindSavedRestartHint:`Saved. Restart the session for the new key to take effect.`},permission:{allowTool:`Allow tool:`,bashCommand:`Bash command`,approve:`Approve`,deny:`Deny`,alwaysAllow:`Always allow`,riskLabel_low:`low risk`,riskLabel_medium:`medium risk`,riskLabel_high:`high risk`},hint:{select:`select`,confirm:`confirm`,execute:`execute`,cancel:`cancel`,delOne:`delete one`,choose:`choose`,option:`option`,question:`question`,shortcut:`shortcut`,toInterrupt:`to interrupt`,pausedContinue:`type to continue or /continue`,steer:`steer`,queue:`queue`,history:`history`,autosuggestAccept:`accept suggestion`,autosuggestMenu:`completions`,submit:`submit`,kill:`kill`,output:`output`,apply:`apply`,switch:`switch`,delete:`delete`,close:`close`,collapse:`collapse`,retry:`Retry`,view:`view`,load:`load`,check:`check`,grab:`grab`,drop:`drop`,move:`move`,edit:`edit`,exit:`exit`,dismiss:`dismiss`,quick:`quick`,refresh:`refresh`,subagents:`agents`,tasks:`tasks`,viewDetail:`↵ view details`,back:`back`,scroll:`scroll`,find:`find`,tabSwitchOutput:`switch view`,tabFocus:`switch panel`,tabZone:`switch area`,toggle:`Toggle`,add:`add`,run:`run`,runNow:`run now`,detail:`detail`,logs:`logs`,switchField:`switch field`,discard:`discard`,confirmCancel:`confirm cancel`,confirmRemove:`confirm remove`,abort:`abort`},history:{label:`History`,capped_one:`earliest {{count}} message removed from the in-memory view (session message count limit reached; still fully kept in storage)`,capped_other:`earliest {{count}} messages removed from the in-memory view (session message count limit reached; still fully kept in storage)`,cappedBytes_one:`earliest {{count}} message removed from the in-memory view (session content exceeded the byte budget; still fully kept in storage)`,cappedBytes_other:`earliest {{count}} messages removed from the in-memory view (session content exceeded the byte budget; still fully kept in storage)`,cappedMemoryPressure_one:`earliest {{count}} message removed from the in-memory view (memory pressure tightened session residency; still fully kept in storage)`,cappedMemoryPressure_other:`earliest {{count}} messages removed from the in-memory view (memory pressure tightened session residency; still fully kept in storage)`,cappedLossy_one:`⚠ earliest {{count}} message dropped from the model context **without a summary** — the model can no longer see it (fallback trim after repeated compaction failures). The raw record is still fully kept in storage; use /history to review.`,cappedLossy_other:`⚠ earliest {{count}} messages dropped from the model context **without a summary** — the model can no longer see them (fallback trim after repeated compaction failures). Raw records are still fully kept in storage; use /history to review.`},common:{more:`more`,disabled:`disabled`,wordOr:`or`,moreLinesLabel:`… +{{n}} more lines`,thoughtLines:`Thought ({{n}} lines)`,noContentAvailable:`(no content to display)`,contentUnavailable:`(content unavailable — session was resumed, original file content was not persisted)`,cancelButton:`Cancel`,upgradeButton:`Upgrade`,escClose:`Esc close`,noMatches:`no matches`,confirmButton:`Confirm`,genericCancelButton:`Cancel`,dontRemind:`Don't remind again`,okButton:`OK`,abortButton:`Abort`,pauseButton:`Pause`,abortAndExitButton:`Abort & Exit`,abortAndRestartButton:`Abort & Restart`},model:{noneAvailable:`No usable model — first`,goLogin:`Log in`,setKey:`Set API key`,pendingCapabilities:`{{count}} provider plugin(s) awaiting authorization`,goGrantCapability:`Authorize`,noProviderPlugin:`No provider plugins installed — install one to get started.`,goInstallPlugin:`Install provider plugin`,switchedTo:`switched to {{label}}`,title:`configured model unavailable`,reasonNotFound:`Reason: model id not found (may be retired or misspelled)`,reasonUnauthenticated:`Reason: {{provider}} is not authenticated`,hint:`/auth to authenticate the provider · /model to switch`,permanent:`Switch`,login:`Go to Login`,dismiss:`Exit`,goToLoginButton:`Go to login`,goToExtensionButton:`Authorize`,forcedUpgradeTitle:`Forced Upgrade Required`,noRegistry:`No model registry available.`,notFound:`Model not found: {{name}}. Use /model to list.`,listFooter:` /model <id> to switch. * = current`,visionDelegateToast_one:`{{count}} image described by a vision model (current model has no vision input support)`,visionDelegateToast_other:`{{count}} images described by a vision model (current model has no vision input support)`,fallbackLoginToast:`Opening login for {{provider}}…`},welcome:{providerDesc:{"anthropic-provider":`Anthropic Claude — OAuth login (recommended)`,"deepseek-provider":`DeepSeek — requires DEEPSEEK_API_KEY`,"openai-codex-provider":`OpenAI Codex — requires credentials`},version:`Version`,workspace:`Workspace`,extensions:`Extensions`,msgCountLabel_one:`{{count}} msg`,msgCountLabel_other:`{{count}} msgs`,itemCountLabel_one:`{{count}} item`,itemCountLabel_other:`{{count}} items`,greeting_late:`It's late on {{wday}}{{who}} — a quiet time to think deeply.`,greeting_earlyMorning:`Rise and shine{{who}}! {{wday}} morning — fresh ideas await.`,greeting_morning:`Good {{wday}} morning{{who}} — let's build something great.`,greeting_afternoon:`Happy {{wday}} afternoon{{who}} — keep the momentum going.`,greeting_evening:`Good {{wday}} evening{{who}} — time to wrap up and reflect.`,greeting_night:`Late {{wday}} night{{who}} — the best ideas come after dark.`,tipLabel:`OTTO Tip`,shadowBadge:`SHADOW`,shadowChip:`shadow — nothing written to disk`,shadowBannerTitle:`Shadow session — zero disk footprint`,shadowGuarantee:`Guaranteed: otto state (credentials, sessions, memory, lessons, config, trace, logs) stays in memory only — nothing written to disk this session.`,shadowNotGuaranteedTitle:`NOT covered (may still leave traces):`,shadowNg1:`Files you have otto edit/write in your project (your intended output)`,shadowNg2:`Shell commands, git, MCP servers, third-party plugins writing on their own`,shadowNg3:`Provider-side logs, telemetry and billing records`,shadowNg4:`OS traces: your shell history, process list, network connections`},onboarding:{title:`Get Started`,nameQuestion:`What should I call you?`,langQuestion:`Choose your language`,namePlaceholder:`e.g. aniwei`,nameDesc:`Your nickname helps personalize conversations and notifications.`,langFootnote:`You can change this later with /preference lang.`,langOptions:{en:`English (en)`,zh:`中文 (zh)`,auto:`Auto-detect from system`},skip:`Skip`,done:`Done`,stepName:`Nickname`,stepLang:`Language`,stepTheme:`Theme`,stepCounter:`Step {{current}}/{{total}}`,langAuto:`Auto-detect from system`,themeQuestion:`Color theme`,themeFootnote:`Move the highlight to preview live; System detects your terminal background`,themeDark:`Dark`,themeLight:`Light`,themeSystem:`Follow terminal`,hintNext:`next`,hintDone:`done`,hintSkip:`skip`,hintBack:`back`,hintQuick:`quick`},prompt:{ready:`ready`,streaming:`streaming`,default:`Type a message or /help…`,working:`Agent is working — type to steer this turn…`,setup:`Not set up yet — /setup to continue where you left off`,fallback:`Type a message…`,submit:`Submit`,readySuffix:`{{n}} ready`,upgradeRequired:`Update required — /upgrade to continue`,submitButton:`Submit`,defaultTitle:`Prompt`,reviewingPlaceholder:`Reviewing history · Esc to return`,unfocused:`Input preserved — continue anytime…`},questions:{readyToSubmit:`Ready to submit your answers.`,someUnanswered:`Some questions unanswered — submit anyway?`},freeform:{tab:`Notes`,filled:`*`,empty:`-`,label:`Add notes or clarification (optional):`,placeholder:`Type your notes here…`,advance:`done (advance to submit)`},panelTitle:{memory:`memory`,editedFilesTitle:`Edited files`},inspText:{thinking:`thinking`,thinkingLabel:`Thinking…`},update:{forcedBanner:`⚡ Forced upgrade to v{{latest}} — type /upgrade now`,availableBanner:`🆕 v{{latest}} available — type /upgrade for details`},status:{failed:`failed`,interrupted:`interrupted`,done:`done`,stopped:`paused`},task:{leftLabel:`{{done}}/{{total}} · {{left}} left`,title:`Task`,collapsedHint:`collapsed`,detailTitle:`Task Detail`,turnInfo:`(turn #{{turn}}, {{shown}}/{{total}} messages)`,turnTag:`(turn #{{turn}})`,truncated:`... {{n}} more messages truncated`,statusLabel_pending:`pending`,statusLabel_in_progress:`in progress`,statusLabel_done:`done`,statusLabel_skipped:`skipped`,statusLabel_failed:`failed`},tool:{edit:`Edit`,write:`Write`,read:`Read`,tasks:`Tasks`,subagent:`Subagent`,unknown:`unknown`,fallback:`tool`,compact:`Compact`,prune:`Prune`,history:`History`,session:`Session`,run:`Run`,model:`Model`,effort:`Effort`,budgetLabel:`{{used}}/{{max}} tools`,countLabel_one:`{{count}} tool`,countLabel_other:`{{count}} tools`,chainSummary_one:`[{{count}} tool: {{names}}]`,chainSummary_other:`[{{count}} tools: {{names}}]`},diff:{modeLabel:`vs HEAD`,loading:`Loading whole-file diff…`,error:`Whole-file diff unavailable: {{message}}`,linesTotalLabel_one:`{{count}} line`,linesTotalLabel_other:`{{count}} lines`,fileCountLabel_one:`{{count}} file`,fileCountLabel_other:`{{count}} files`,fileOpLabel_edit:`modified`,fileOpLabel_write:`created`,fileOpLabel_other:`deleted`},compact:{ed:`earlier messages compacted`,pruned:`tool outputs trimmed to fit context`,ing:`Compacting context…`,edResult:`✓ Context compacted: {{before}} → {{after}} messages (full transcript preserved)`,noop:`Nothing to compact — context is already small.`,unavailable:`Compaction unavailable: memory/compaction is not enabled for this session.`,logTitle:`Compaction & Prune Log`,logEmpty:`No compaction or prune events yet this session.`,logCompactRow:`{{before}} → {{after}} ({{pct}}% kept)`,logDetailTitle:`{{kind}} · {{time}}`,logNoSummary:`No summary available for this event.`,logViewSummary:`view summary`,ingVerb:`Compacting`,logHistoryCappedRow_one:`{{count}} message removed from memory (still kept in storage)`,logHistoryCappedRow_other:`{{count}} messages removed from memory (still kept in storage)`,ionStageLabel_analyze:`Analyzing context`,ionStageLabel_summarize:`Generating summary`,ionStageLabel_finalize:`Finalizing`,logPruneRow:`saved ~{{tokensSaved}} tokens`,logPruneRow_pruned_one:`saved ~{{tokensSaved}} tokens ({{count}} tool output)`,logPruneRow_pruned_other:`saved ~{{tokensSaved}} tokens ({{count}} tool outputs)`},lease:{denied:`this turn’s changes were NOT saved — another otto process owns this session’s write lease`,restored:`write access restored — changes will save normally from now on`,deniedToastTitle:`Session read-only (changes not saved)`,deniedToastBody:`Why: another otto process is writing this session (e.g. another terminal window, or an /exit -r restart handoff that hasn’t completed).
31
+ This window still works normally, but changes will not be saved.
32
+ Fix: ① close the other otto process — this session will automatically become writable again on the next successful save; ② or exit this window and /resume a different session to continue working.`,restoredToastTitle:`Session write access restored`,restoredToastBody:`Changes will save normally from now on.`},pause:{titleRequested:`Waiting to pause`,bodyRequested:`Will pause once the current turn finishes`,titleActive:`Paused`,bodyActive:`Agent is paused — queued messages will not run`,btnCancel:`Cancel pause`,btnResume:`Resume`,footerDismiss:`Esc to dismiss overlay (pause request continues in background)`,footerActive:`Enter to accept · Esc to dismiss`,toolCount:`{{n}} tools · {{s}}s`,toolTotal:`Ran {{n}} tools this turn`},run:{messageFooter:`Type anything or /continue to resume`,resumedMessageBody:`Agent resumed`,pauseCancelledMessageBody:`Pause request cancelled — agent continues running`,messageBody:`Agent paused — queued messages will not run automatically`,messageBody_n:`Agent paused after {{n}} tools this turn — queued messages will not run automatically`},shell:{running:`running`,terminated:`terminated`,errored:`error`,exit:`exit {{code}}`,copyHint:`copy output`,copiedTitle:`Shell`,copiedBody:`Copied to clipboard`,hint:`ask AI`,exitCode:`exit code {{code}}`,askAiTerminated:`terminated by signal`,unknownError:`unknown error`,prompt:"The command `{{command}}` failed ({{errorLabel}}). Here is the output, please help diagnose:\n\n```\n{{output}}\n```",truncated:`...(truncated — press c to copy the full output to clipboard)`,viewAll_one:`view all output ({{count}} line total)`,viewAll_other:`view all output ({{count}} lines total)`,moreLines_one:`... {{count}} more line ...`,moreLines_other:`... {{count}} more lines ...`},spinner:{verbs:[`Working`,`Thinking`,`Crunching`,`Running`],outputPercent:`{{pct}}% of limit`,estimatedPercent:`~{{pct}}%`},bg:{runningVerb:`Running {{tool}}`,tasksTitle:`Delegates`,empty:`(no background tasks)`,noOutput:`(no output yet)`,live:`live`,following:`following…`,jobsLabel:`{{n}} delegates`,runningSuffix:`{{n}} running`,doneSuffix:`{{n}} done`,needInputSuffix:`{{n}} need input`,metaReady:`ready`,metaNeedsInput:`needs input`,agentStatusLabel:`{{st}}`,procStatusLabel:`{{s}}`,categoryLabel_job:`Jobs`,categoryLabel_bash:`Bash`,categoryLabel_other:`Sub-agents`,metaExited:`exited`,metaExited_code:`exited {{code}}`},subagent:{sTitle:`Subagents`,sRunning:`{{n}} running`,header:`Sub-agent @{{title}} · {{status}}`,contextEarlierLines:`↑ {{n}} lines earlier · ↵ for full scrollable transcript`,sWorking_one:`Subagent working ({{count}} subagent)`,sWorking_other:`Subagent working ({{count}} subagents)`},agent:{interruptTitle:`Interrupt agent?`,interruptMessage:`The current agent turn is still running. Interrupting will stop it and mark the turn as interrupted.`,interruptConfirm:`Interrupt`},queue:{label:`Queue`,empty:`No queued commands`,editTitle:`Edit queued item {{index}}/{{total}}`,editSendNowButton:`Send Now`,editConfirmButton:`Confirm`,editSendNowHintBusy:`Will be injected as a supplement to the current turn`,editSendNowHintIdle:`Will be sent immediately as a new message`,exitTitle:`Exit Queue Panel`,exitConfirm:`Clear and Exit`,exitMessage:`The panel has %d queued commands that will be cleared.`,popTitle:`Remove queued message?`,popMessage:`One follow-up message is queued. Remove the newest queued message instead of interrupting the running turn?`,popConfirm:`Remove queued message`,dFollowUpToast:`Model still running — queued as a follow-up, will send when it finishes`},retry:{reason:`{{reason}}`,defaultTitle:`Error details`,attempt:`Retry {{attempt}}/{{max}}`,countdown:`Retrying in {{s}}s…`,progressSep:` · `,nowButton:`Retry now`,hint:`↵/r`,stopButton:`Stop`,hintWithStop:`↵/r retry · Esc stop`},error:{typeLabel:`{{type}} limit reached`,retryNow:`Retry now`,switchModel:`Switch model`,title:`Request failed: {{reason}}`,defaultTitle:`Request failed`,exhaustedTitle:`Request failed after retries`,autoCountdown:`Attempt {{attempt}}/{{max}} · retrying in {{seconds}}s`,manualBody:`Attempt {{attempt}}/{{max}} · action required to retry`,exhaustedBody:`Retried {{max}} times, still failing`,resetsIn:`Quota resets in {{hms}}`,unknownReset:`Reset time unknown`,hint:`←/→ select · ↵ confirm · r retry now · Esc cancel`},pulse:{title:`How was this session?`,ratingGood:`Good`,ratingNeutral:`Neutral`,ratingBad:`Needs work`,commentTitle:`{{ratingLabel}} · Anything to add? (optional)`,commentPlaceholder:`Type your thoughts…`,hintRating:`←/→/Tab switch · ↵ select · Esc close`,hintComment:`↵ submit · Esc close (rating is saved either way)`},find:{inputLabel:`Find:`,matchCount:`{{current}}/{{total}}`,tabPrompt:`Prompt`,tabConversation:`Conversation`,tabDiff:`Diff`,tabDiagnostics:`Diagnostics`,searchNoMatches:`no matches`},schedule:{sLabel:`Schedules`,sEmpty:`No scheduled tasks. Create one with /schedule add`,oneShot:`one-shot`,next:`next: `,panel:{noTasks:`No scheduled tasks.`,pressToAdd:`Press {{key}} to create your first schedule.`,examples:`Examples: {{c1}} daily at 09:00 · {{c2}} every 30 minutes`,running:`running`,failedCanceled:`failed/canceled`,readonlyNet:`{{cross}} network error — cannot reach schedule service`,readonlyLease:`{{cross}} read-only — another terminal holds the fire-ownership lease`,moreAbove:`... {{n}} more above`,moreBelow:`... {{n}} more below`,failedErr:`(failed: {{err}})`,detail:{id:`ID`,status:`Status`,type:`Type`,cron:`Cron`,prompt:`Prompt`,nextFire:`Next fire`,lastFire:`Last fire`,never:`never`,jobRunning:`{{cross}} job running — {{id}}`,recent:`Recent (last {{n}})`,loadingLogs:`Loading logs...`,noLogs:`No logs yet`},logsTitle:`Logs: {{id}}`,form:{newTitle:`New Schedule`,editTitle:`Edit: {{id}}`,name:`Name`,cron:`Cron`,type:`Type`,status:`Status`,prompt:`Prompt`,preview:`Preview`,auto:`(auto)`,cronPlaceholder:`________________`,recurring:`recurring`,enabled:`enabled`,disabled:`disabled`,toggleHint:`(←/→ to toggle)`,templatesHint:`press ←/→ for templates`,templates:`templates`,previewNext:`Next fire: {{time}}`,previewJitter:`Next fire: {{time}} + 0-30min jitter`,previewJitterOnce:`Next fire: {{time}} + ~90s jitter`,previewCron:`cron: {{cron}} (recurring)`,previewCronOnce:`cron: {{cron}} (one-shot)`,previewEmpty:`enter a valid cron expression`,invalidCron:`invalid cron`,required:`Cron and prompt are required`,saving:`Saving...`,createFailed:`Failed to create`,saveFailed:`Failed to save`},confirmCancelTitle:`Cancel job?`,confirmCancelBody:`This will cancel the currently running job of {{name}}.`,confirmCancelNote:`The schedule definition will not be affected.`,confirmRemoveTitle:`Remove schedule?`,confirmRemoveBody:`This will permanently delete {{name}} ({{id}}).`,confirmRemoveWarn:`This action cannot be undone.`}},draft:{sLabel:`Drafts`,sEmpty:`No drafts. Save one with Ctrl+S`,saved:`Saved to drafts`,saveEmpty:`Nothing to save — input is empty`},prompts:{label:`Prompts`,empty:`No prompts yet`},service:{sTitle:`Services`,sEmpty:`(no running services detected)`,countLabel_one:`svc`,countLabel_other:`svcs`},scroll:{above:`↑ {{n}} lines above`,below:`↓ {{n}} lines below`,viewportLinesAbove:`lines above`,viewportLinesBelow:`lines below`},insp:{live:`live · {{n}} rows`,row:`row {{cur}}/{{total}}`,replay:`replay`,paused:`⏸ paused`,pausedBig:`⏸ PAUSED`,inspect:`inspect`,hintPause:`c continue · s step · n next · o step-out · x stop`,hintFocus:`Ctrl+G to focus`,hintBp:`↑↓ select · Tab switch · space toggle · Esc exit`,bpIdle:`▶ ⤼ ⤓ ⤴ ⏹ idle — run a prompt to pause at an enabled breakpoint`,variablesIdle:`Variables appear when paused — enable a point in Sources, then run`,breakpoints:`BREAKPOINTS`,noneInteractive:`— none (need interactive inspector) —`,noTools:`— no tool calls yet —`,noEvents:`— no trace events yet (run a prompt) —`,noUsage:`— no usage yet (run a prompt) —`,noLineage:`— no lineage —`,toolbar:`▶ continue(c) ⤼ over(n) ⤓ step(s) ⤴ out(o) ⏹ stop(x)`,variables:`VARIABLES`,editKeys:` Enter=save Esc=cancel`,injectMsg:`inject msg`,changeData:`change data: t think · [ ]temp · i inject · e sys`,budgetOverhead:`overhead`,budgetMessages:`messages`,budgetFree:`free`,budgetLastTotal:`last {{lastIn}}→{{lastOut}} · total {{totalIn}}→{{totalOut}}`,liveTag:`▸ live`,userPrefix:`user: `,thinkingFull:`thinking (full):`,toolRunning:`{{tool}} (running)`,toolCall:`{{tool}} (call)`,assistantFallback:`assistant text`,emptyPrompt:`(prompt)`,endTurn:`· end_turn`,treeThinking:`thinking ⟨{{n}} · {{chars}} chars⟩`,bpCatAgentWorkLoop:`Agent Work Loop`,bpCatWorkLoopInjection:`Work-loop Injection`,bpCatToolExecutor:`Tool Executor`,bpCatSessionPrompt:`Session Prompt Lifecycle`,bpCatLifecycleHook:`Lifecycle Hook`,bpCatTurnObservable:`Turn Observable`,bpCatCustom:`Custom`,debugCall:`Call`,debugLlmParams:`LLM Params`,debugSystemPrompt:`System Prompt`,debugMessages:`Messages ({{n}})`,debugTokens:`Tokens in {{inTokens}} · out {{outTokens}}`,debugEmpty:`(empty)`,debugEditsPending:`edits: {{parts}} (apply on resume)`,debugEditSysPrompt:`system prompt`,asstPrefix:`asst: `,thinkingPrefix:`thinking… `,noTurnData:`No turn data available.`,treeAssistantDeltas_one:`assistant ⟨{{count}} delta · {{chars}} chars⟩`,treeAssistantDeltas_other:`assistant ⟨{{count}} deltas · {{chars}} chars⟩`,hintTree:`↑↓ move · Tab switch · w why{{whySeg}} · z expand{{expandSeg}} · space fold · Esc exit`},budget:{exhaustedTitle:`Hit this turn’s tool-step budget — the task may be unfinished. Keep going?`,continue:`Keep going`,stop:`Stop`,stoppedNote:`⏸ Stopped at the tool-step budget — the task may be unfinished. Just keep instructing me to continue (each prompt resets this turn’s tool budget).`,tokensLabel_one:`{{count}} token`,tokensLabel_other:`{{count}} tokens`,tokenBudgetLabel:`{{used}}/{{budget}} tok`},cmdDesc:{help:`Show available commands`,exit:`Exit the TUI; /exit --restart to restart into the same session`,clear:`Clear screen and reset session`,abort:`Abort the current agent run`,copy:`Copy last assistant response`,model:`List models or switch with /model <id>`,setup:`Show onboarding progress (provider → login → model) with jump-to-next-step`,status:`Show session status`,inspect:`Open inspector (Events/Tools/Sources/Budget); /inspect sources|<point>|off`,replay:`Replay a session trace (/replay [<id>|off])`,delegates:`Toggle the Delegates pane (↑↓ select · k kill · o output · a apply). Aliases: /jobs /bg`,job:`Start a background agent job: /job <directive> (worktree-isolated, full tools incl. MCP). Code changes → a diff to apply; chores/research → a text result (view with o).`,extension:`Manage pluggable extensions (MCP / skills / agents): ↑↓ select · Enter toggle · Esc close`,compact:`Compact the conversation context now (summarize earlier messages to free up tokens)`,memory:`Project + user memory: /memory [user|project|<name>|forget <name>]; /memory user <text> saves a cross-project note (# writes project)`,login:`Authenticate a provider (OAuth or API key); /auth [<provider>]`,logout:`Remove stored credentials for a provider; /logout [<provider>]`,effort:`Switch reasoning effort (/effort low|medium|high|xhigh|max)`,preference:`Preferences: /preference [lang|theme]`,permissions:`View / clear the always-allow list (/permissions [clear])`,context:`Show context usage breakdown (system/tools/messages/cache/free bar)`,attach:"Attach to a session running on `otto serve`: /attach <sessionId> (read-only preview in this phase)",history:`Open input history search panel. Aliases: /hist`,prompts:`View prompt log (list of submitted prompts this session)`,notification:`Toggle the notification center panel (≡ Ctrl+N). Aliases: /notif`,pin:`Pin current session (sorts to top of /resume); batch/group: /pin [<session-id>...] [--group <name>]`,unpin:`Unpin current session`},pref:{permModeSwitched:`Permission mode → {{label}}`,languageUsage:`Usage: /preference lang <en|zh>`,languageName_zh:`中文`,languageName_other:`English`,permModeLabel_confirm:`Approve`,permModeLabel_auto:`Auto`,permModeLabel_bypass:`Autopilot`,permModeLabel:`{{context}}`,authModeLabel_oauth:`subscription`,authModeLabel_api_key:`API key`,authModeLabel_env:`API key`,authModeLabel:`{{context}}`,languageSwitched:`Language → {{name}} ({{l}})`},time:{justNow:`just now`,minAgo:`{{min}}m ago`,hourAgo:`{{hr}}h ago`,dayAgo:`{{day}}d ago`},paste:{confirmTitle:`Paste large text?`,collapseLabel:`Collapse to `,confirm:`Confirm`,cancel:`Cancel`,view:`View`,viewTitle:`Pasted content`,titlePasteExpired:`Paste expired`,expiredToast_one:`{{count}} pasted content reference expired — please paste again`,expiredToast_other:`{{count}} pasted content references expired — please paste again`,previewSummary_body:`─── Total {{lines}} {{lineWord}}, {{chars}} {{charWord}} ───`},select:{filterPlaceholder:`type to filter...`,noMatches:`no matches`,clearHint:`clear / `,matchCount_one:`{{count}} match`,matchCount_other:`{{count}} matches`},sigil:{filterPlaceholder:`type to filter...`,noMatches:`no matches`,searching:`searching…`,catAgent:`Agent`,catRecent:`Recently used`,catResource:`Custom resource`,catShortcut:`Shortcut`,catExtension:`Extension`,catPerson:`Member`,catHashtag:`Template`,catPlugin:`Plugin`,catFile:`File`,catModel:`Model`,loadingFile:`Loading file…`,readFullFile:`Read full file`,catSkill:`Skill`,titleMention:`Mention`,titleHashtag:`Hashtag`},toast:{editorError:`Editor error`},context:{tokensLabel:`{{formatted}} tokens`,title:`Context`,noData:`No context data yet — wait for the first API response.`,viewDetails:`Enter details`,systemHeading:`System context`,systemMeta:`{{tokens}}t · {{stable}} stable + {{volatile}} volatile`,laneVolatile:`volatile`,laneCache:`cache`,conversationHeading:`Conversation`,conversationMeta:`{{tokens}}t · {{turns}} turns`,earlierTurns:`{{count}} earlier turns ({{tokens}}t)`,turnRow:`turn #{{index}} · {{messages}} msg · {{tokens}}t`,totalLine:`Total {{used}} / {{window}} ({{percent}}%) · free {{free}}t`,tagPruned:`pruned`,tagCompacted:`compacted`,tagTruncated:`truncated`},transcript:{frozenNew:`new`,escToLive:`Esc back to latest`,you:`you`,assistant:`assistant`,loadingEarlier:`loading earlier history…`,emptyEarlier:`— no earlier messages — (PgUp/↑ scroll · Esc latest)`,findBar:`/{{query}} · {{count}}`},trust:{title:`Trust this folder?`,body:`Accessing workspace:
33
+ {{path}}
34
+
35
+ Is this a project you created or trust (your own code, a well-known
36
+ open-source project, or work from your team)? Otto will read, edit, and
37
+ run files here. If unsure, review the folder first or open it read-only.`,optTrust:`Trust — full access (read / edit / run + apply its config)`,optReadonly:`Read-only this session — safe look, no write / run / network`,optExit:`No, exit`},parent:{title:`Parent workspace detected`,body:`No workspace identity found in {{currentRoot}},
38
+ but parent directory {{parentRoot}} already has one.`,optUseParent:`Use parent workspace — share sessions & memory`,optCreateNew:`Create new workspace here — independent identity`,optExit:`Exit`},notif:{title:`Notifications`,readDivider:`──── Read ────`},confirm:{reset:`Confirm Reset`,replace:`Confirm Replace`,abortConfirmTitle:`Abort agent?`,abortConfirmMessage:`The agent is currently working. If you abort, the current turn will be lost and any pending writes may be incomplete.`,exitConfirmTitle:`Abort and exit otto?`,exitConfirmMessage:`The agent is currently working. Exiting will abort the current turn, and any pending writes may be incomplete.`,exitRestartConfirmTitle:`Abort and restart otto?`},cache:{sessionLabel:`session`,lastTurnLabel:`last turn`},recovery:{titleProvider:`No AI provider yet`,hintProvider:`otto needs a provider to talk to a model.`,ctaProvider:`Run /setup to install one`,titleAuth:`Provider installed, not connected`,hintAuth:`Sign in or paste an API key to continue.`,ctaAuth:`Run /setup to connect`,titleModel:`No usable model yet`,hintModel:`Credentials may be missing or expired.`,ctaModel:`Run /setup to choose a model`},setup:{wizardApiKeyPlaceholder:`Type or paste your key, then press Enter to confirm`,title:`Setup Wizard`,welcomeTitle:`Welcome to otto, your AI coding companion`,welcomeGreeting:``,welcomeDescription:`This wizard will guide you through setting up otto in 4 quick steps: choose an AI provider, log in, pick a model, then start chatting.`,welcomeDontShowAgain:`Don't show this wizard again`,welcomeStart:`Start`,welcomeCancel:`Cancel`,step1Subtitle:`otto needs at least one AI provider to work. Pick one to install — you can add more later with /extension.`,step3Subtitle:`Choose how to authenticate with your provider.`,step4Subtitle:`Pick a model to start chatting.`,step5Done:`All set! Type a message to start.`,installing:`Installing…`,installed:`Installed!`,installFailed:`Installation failed: {{reason}}`,loginOAuth:`Sign in with OAuth (recommended)`,loginApiKey:`Paste an API key`,loggingIn:`Logging in…`,loginFailed:`Login failed: {{reason}}`,exitTitle:`Exit Wizard`,exitConfirm:`Exit the setup wizard? Progress will be saved — you can resume later with /setup.`,errorTitle:`Setup Error`,errorMessage:`Setup step {{step}} failed: {{msg}}
39
+ A crash report has been recorded.`,stepNameProvider:`Provider`,stepNameLogin:`Login`,stepNameModel:`Model`,stepNameStart:`Start`,actionInstall:`install`,actionLogin:`log in`,installPendingCapabilities:`Installed, but some capabilities still need authorization — run /extension to grant them, or this provider will offer no models.`,modelRecommendedTag:`Recommended`,modelRecommendedHint:`Recommended first — you can switch anytime with /model.`,modelUnusableUnauthenticated:`needs sign-in`,modelUnusableOauthRisk:`subscription plan may be rate-limited`,authFailedNetwork:`Could not reach the sign-in service. Your network or proxy may be blocking it.`,authFailedRejected:`Authorization did not complete.`,actionOpenProxySettings:`Open proxy settings`,actionRetryAuth:`Try signing in again`,oauthWaiting:`Waiting for approval in your browser…`,actionOpenAgain:`Open the sign-in page again`,actionUseApiKeyInstead:`Use an API key instead`,apiKeyStorageNote:`Saved to your local credentials file — never written to this project or the chat history.`,installFailedRecovery:`Could not install {{provider}}. Pick what to do next:`,actionRetryInstall:`Retry install`,actionChooseAnotherProvider:`Choose another provider`,capabilityGranted:`Granted capabilities: {{caps}}`,capabilityRevokeHint:`You can revoke this anytime in /extension.`},install:{title:`Installing {{source}}`,phaseResolving:`Resolving source…`,phaseDetecting:`Detecting content…`,phaseInstalling:`Installing…`,phaseRefreshing:`Refreshing…`,reloadingDetail:`Reloading capabilities…`,done:`Installed`,summaryFailed:`Install failed`,summaryPartial:`Partially installed`,nextStepForce:`Tip: add --force to overwrite the existing item`,nextStepReload:`Tip: run /reload to refresh capabilities manually`,failureOverflow:` (full list in the message below)`,partialCounts:`{{ok}} installed, {{fail}} failed: `},proxy:{title:`Proxy`,groupConfig:`configuration`,groupAbout:`about`,fieldUrl:`Proxy address`,fieldEnabled:`Status`,dialogSetUrl:`Set proxy address`,dialogEditUrl:`Edit proxy address`,urlPlaceholder:`http://127.0.0.1:7890`,urlEmpty:`not set — e.g. http://127.0.0.1:7890`,stateEnabled:`Enabled`,stateDisabled:`Disabled`,actionClear:`Clear configuration`,clearTitle:`Clear proxy configuration`,clearMessage:`Clear the proxy configuration? ({{url}})`,clearConfirm:`Clear`,aboutScope:`Applies to all outbound HTTP: model APIs, sign-in, web fetch, updates.`,aboutLoopback:`Local addresses (localhost / 127.0.0.1) always connect directly.`,aboutStorage:`Stored in {{path}}`,aboutCommand:`Command line: /proxy [<url>|on|off|status|clear]`,actionTest:`Test connection`,actionAdoptEnv:`Use system proxy {{value}} (from {{source}})`,probeProbing:`Testing…`,probeOk:`Reachable via proxy — {{latency}}ms ({{target}})`,probeFailedProxy:`Proxy unreachable — {{reason}}`,probeFailedTarget:`Proxy works, but target unreachable — {{reason}}`,probeNoModel:`Configure a model first, then test the connection`,effectiveMismatch:`In effect: {{effective}} — restart the session to apply changes`,effectiveNotApplied:`Not in effect yet — restart the session to apply changes`,envDetectedToast:`Detected {{source}}={{value}} — open /proxy to use it`},crashGap:{toastTitle:`Some messages were lost in the previous crash`,toastBody:`About {{lostTurns}} turn(s) of messages could not be saved when the previous process terminated abnormally (e.g. out of memory or force-killed) and cannot be recovered. Earlier conversation history is intact.`},signalBar:{tabHint:`Tab to switch`,clipboard:`Clipboard`,clipboardFailed:`Copy blocked — hold {{modifier}} and drag for native copy`},clipboard:{paneTitle:`Clipboard`,viewerTitle:`Clipboard content`,charsLabel:`{{count}} chars`,empty:`Nothing copied yet`,openHint:`view`},mouse:{toggleTitle:`Mouse`,enabledBody:`On — drag selects and copies; hold {{modifier}} for terminal native selection; wheel scrolls`,disabledBody:`Off — terminal native selection restored, wheel disabled (use Alt+↑/↓)`}}},zh:{translation:{cmd:{titleInfo:`提示`,titleShell:`Shell`,titleOpen:`打开文件`,openNotFound:`文件不存在:{{path}}`,openBinaryRejected:`无法预览二进制文件:{{path}}`,openBrowserSubtitleRoot:`工作区根目录`,openBrowserSubtitleDir:`{{relDir}}`,titleMemory:`记忆`,titleExit:`退出`,titleUpdate:`更新`,titleAborted:`已中止`,titleLanguage:`语言`,titlePermission:`权限`,titlePaused:`已暂停`,runAborted:`运行已中止`,runWillPauseAfterTurn:`将在当前回合结束后暂停`,noRunningTask:`当前没有正在运行的任务`,noRunningTaskToPause:`Agent 已完成当前回合,无需暂停`,notPaused:`当前没有暂停的运行`,runResumedByCommand:`已继续`,nothingToPause:`当前没有运行的任务`,pauseCancelled:`暂停请求已取消`,titlePauseRequested:`已请求暂停`,memoryDisabled:`记忆未启用(无存储)`,memorySaved:`✓ 已记忆「{{name}}」→ .otto/memory/(下回合起进上下文)`,dangerousBlocked:`危险命令已拦截:{{reason}}`,dangerousBlockedDetail:`已拦截危险命令({{reason}}):{{cmd}}
40
+ 如需特权操作,请经 agent 用 bash 工具。`,noModelConfigured:`尚未配置模型——输入 /setup 查看上手进度,或 /model 直接选择模型。`,todoGateContinuing:`续跑中 {{round}}/{{cap}}… {{left}} 项未完成`,budgetExtended:`工具预算已扩展(+{{maxTurns}} 轮)`,budgetProgressDenied:`预算窗口无进展(疑似循环)——已请求模型收尾`,budgetSteered:`工具预算耗尽(每窗口 {{maxTurns}} 轮)——已请求模型收尾`,progressStallDetected:`检测到停滞(同一工具调用反复 {{maxRepeat}} 次且无进展)——已请求模型更换策略`,toolCallMismatchRetry:`响应格式异常:模型声称要调用工具但未发出有效调用——已自动纠正并重试(第 {{retryCount}} 次)`,toolCallMismatchTerminated:`响应格式持续异常——已停止。请重新发送,或更换模型。`,pressCtrlCAgain:`再按一次 Ctrl+C 退出`,updateToast:`otto v{{latest}} 可用 — 输入 /upgrade 升级`,updateNotifAvailable:`otto v{{latest}} 可用(当前 v{{current}})`,updateNotifForced:`otto v{{latest}} 强制升级(当前 v{{current}})`,updateForcedBanner:`otto v{{latest}} 为必需更新。当前:v{{current}}。
41
+
42
+ 输入 /upgrade --force 立即安装并重启。`,titleMemoryPressure:`内存压力`,memoryPressureRestartNow:`立即重启`,memoryPressureRemindLater:`稍后提醒`,titleAutoCompact:`自动压缩`,autoCompactFailed:`自动上下文压缩失败:{{msg}}`,titleFleetBudget:`进程群`,fleetBudgetExceeded:"本机 {{processCount}} 个 otto 进程合计占用 {{totalRssMb}}MB,已超预算。运行 `otto ps` 查看并清扫孤儿进程。",restartChainDeep:`本会话已重启 {{generation}} 次——每次重启会在进程链上留下一个陪跑进程。建议完整退出并重开终端,一次性释放整条链。`,memoryPressureSuppress:`本次会话不再提醒`,memoryPressureResumeAbortedMessage:`重启后内存压力依然过高——已跳过自动续跑。未完成的消息仍保留在历史记录中,可稍后手动重发。`,memoryPressureResumeFailedMessage:`重启后自动续跑失败,请手动重新发送消息。`,titleStaleBuild:`检测到新构建`,staleBuildMessage:`当前运行 build {{current}},磁盘已有更新的 build {{latest}},建议 /exit 重启以获取最新修复`,titleContextPressure:`上下文占用`,contextPressureApproaching:`上下文占用已达 {{pct}}%,接近自动裁剪线`,contextPressureNearing:`上下文占用 {{pct}}%,已进入自动裁剪区间`,contextPressureCritical:`上下文占用 {{pct}}%,即将触发自动压缩`,titleError:`错误`,resumeNotFound:`未找到会话 "{{id}}",已新建会话。`,modelsRefreshed:`已刷新模型:{{summary}}(/model 查看,✓ = 账号可用)`,modelsRefreshedEmpty:`模型刷新:暂无可拉取的 provider(仍用缓存/内置)`,titleSetupRequired:`需要配置`,titleSetupReady:`就绪`,setupReadyMessage:`模型已就绪 — 直接输入消息开始对话!`,modelNotSupported:`该模型可能不被当前账号支持。输入 /model 选一个带 ✓(账号可用)的模型,或 /model refresh 刷新列表。`,rateLimitedRetriesExhausted:`当前模型触发了服务端流量限制(并非账号配额耗尽),自动重试已达上限。可稍后重试,或输入 /model 切换到其他可用模型。`,requestFailed:`请求失败:{{msg}}`,resumeContinueLabel:`续上本会话:`,titleEffort:`投入`,selectEffortTitle:`选择推理投入级别`,selectLanguageTitle:`语言`,titlePreference:`偏好设置`,preferenceUsage:`用法:/preference [general|lang|theme]`,prefOptionLang:`语言`,prefOptionTheme:`主题`,prefOptionGeneral:`常规`,prefDescGeneral:`通用行为、通知与个性化设置`,prefDescLang:`界面显示语言`,prefDescTheme:`配色外观(深色 / 浅色 / 跟随系统)`,selectGeneralTitle:`常规`,genNickname:`昵称`,genNicknameDesc:`会话与通知中个性化显示的称呼`,genNicknameInputTitle:`输入昵称`,genNicknamePlaceholder:`你的称呼…`,genCompletionNotice:`完成通知`,genCompletionNoticeDesc:`任务完成时推送系统通知`,genSound:`提示音`,genSoundDesc:`通知伴随提示音`,genUpdateCheck:`启动检查更新`,genUpdateCheckDesc:`启动时后台检查新版本(仅提示不自动安装)`,toggleOn:`开启`,toggleOff:`关闭`,genSaved:`已保存`,genSkillLoop:`技能回路`,genSkillLoopMissing:`未安装`,genSkillLoopMissingHint:`安装 plugin-skill-inductor 后可用`,genSkillLoopEntryDesc:`自动从对话中归纳可复用技能`,genSkillLoopOn:`开启`,genSkillLoopOff:`关闭`,genSkillLoopThresholdTitle:`触发阈值`,genSkillLoopThresholdDesc:`对话消息数达到此值时触发归纳`,genSkillLoopThreshold:`阈值`,genSkillLoopThr4:`4 条(激进)`,genSkillLoopThr4Desc:`极少对话即触发,适合频繁使用`,genSkillLoopThr6:`6 条(默认)`,genSkillLoopThr6Desc:`平衡触发频率与归纳质量`,genSkillLoopThr12:`12 条(保守)`,genSkillLoopThr12Desc:`较长对话才触发,归纳更稳定`,genSkillLoopThr20:`20 条(极保守)`,genSkillLoopThr20Desc:`仅长对话触发`,genSkillLoopCooldownTitle:`静默期`,genSkillLoopCooldownDesc:`归纳后多少天内不再重复触发`,genSkillLoopCooldown:`静默`,genSkillLoopCd3:`3 天`,genSkillLoopCd14:`14 天(默认)`,genSkillLoopCd30:`30 天`,genSkillLoopCd365:`365 天`,genSkillLoopCdDays:`{{n}} 天`,genSkillLoopStatus:`技能回路状态`,genSkillLoopStatusDesc:`查看归纳历史与候选技能`,skillLoopOnOff:`开/关`,skillLoopPanelTitle:`技能回路`,skillLoopStatusTitle:`技能回路状态`,skillLoopStatusNotInstalled:`插件未安装`,skillLoopStatusSuccess:`成功归纳`,skillLoopStatusPending:`待处理`,skillLoopStatusCandidates:`候选技能`,skillLoopStatusCooling:`静默中`,skillLoopStatusCount:`次数`,skillLoopStatusEpisodes:`回合`,skillLoopStatusTimes:`次`,skillLoopStatusGroupRecent:`最近`,skillLoopStatusGroupPending:`待处理`,compatTrusted:`已信任`,langDescZh:`使用简体中文界面`,langDescEn:`使用英文界面`,langDescAuto:`跟随系统环境(LANG)自动选择`,themeDescDark:`深色配色,适合暗光环境`,themeDescLight:`浅色配色,适合明亮环境`,themeDescSystem:`跟随终端 / 系统外观自动切换`,themeUsage:`未知主题。可用:dark|light|system。运行 /preference theme(不带参数)可选择配色方案。`,themeDarkPresetOption:`深色配色方案`,themeDarkPresetDesc:`深色外观使用的配色方案`,themeLightPresetOption:`浅色配色方案`,themeLightPresetDesc:`浅色外观使用的配色方案`,themePresetTitleDark:`深色配色方案`,themePresetTitleLight:`浅色配色方案`,themePresetBuiltin:`内置`,themePresetFromExtension:`来自 {{id}}`,themePresetReset:`恢复默认`,themePresetResetDesc:`使用该外观的内置配色方案`,themePresetSaved:`主题配色方案已保存:{{label}}`,selectCancelled:`已取消`,titleCompat:`信任`,titlePermissions:`权限`,titleUpgrade:`升级`,titleCommands:`命令`,effortUnknown:`未知: {{arg}}。可用: {{levels}}`,compatTrusting:`已信任本项目的 .claude 可执行配置,热重载中…`,compatReloadFailed:`重载失败:{{err}}`,compatUntrusted:`已撤销信任(下次启动起跳过 .claude 可执行面)`,compatNone:`本项目无 .claude 可执行配置(.mcp.json / .claude/commands)。`,compatTrustedLabel:`已信任`,compatUntrustedLabel:`未信任 — 这些面当前被跳过;输入 /compat trust 启用`,compatConfigGated:`.otto/config.json 高危键已忽略({{keys}})— 输入 /compat trust 启用`,compatConfigActive:`.otto/config.json 高危键已生效({{keys}})— 已信任`,listSep:`、`,permsCleared:`已清空「始终允许」——后续操作将重新弹窗确认`,upgradeChecking:`检查新版本中… (当前 v{{current}})`,upgradeNoNetwork:`无法连接 npm registry,请检查网络后重试。`,upgradeLatest:`已是最新版本 v{{current}}`,upgrading:`升级中…`,upgradeFailed:`升级失败: {{err}}`,unknownError:`未知错误`,permsSessionLabel:`本会话「始终允许」:`,permsProjectLabel:`项目级「始终允许」:`,permsClearHint:`清除本会话:/permissions clear`,permsManageHint:`管理项目级:/permissions add bash(git status) · /permissions remove <条目>`,permsInvalidEntry:`条目「{{entry}}」格式非法——用工具名如「read」或「bash(git status)」(空括号「bash()」不允许)`,permsAdded:`已加入项目级「始终允许」:{{entry}}`,permsRemoved:`已从项目级「始终允许」移除:{{entry}}`,permsNotFound:`不在项目级「始终允许」列表中:{{entry}}`,permsEmpty:`(空)`,helpGroupSession:`会话`,helpGroupModel:`模型与认证`,helpGroupAgent:`代理管理`,helpGroupDebug:`调试与诊断`,helpGroupUi:`界面`,helpGroupOther:`其它`,helpPrefixes:`前缀`,helpPrefixShell:`作为 shell 命令执行`,helpPrefixFile:`读取文件到上下文`,titleJob:`作业`,titleReverted:`已撤销`,titleDelegated:`已委派`,titlePlugin:`插件`,titleExtension:`扩展`,extCategoryLabel:`{{category}}`,extListTitle:`扩展 — 共 {{total}} 个,已启用 {{enabled}} 个`,extListEmptyTitle:`扩展 — 暂无可用`,extDiscoverHint:`可从 registry 搜索安装更多插件`,extDiscoverButton:`去发现`,extListEmptyOption:`暂无可插拔扩展(添加 MCP 服务器 / skills / agents / plugins)`,jobUsage:`用法:/job <要做的事> — 委派后台 agent 作业(worktree 隔离 + 全套工具)。/delegates 看进度,/job revert <id> 撤销。`,jobReverted:`作业 {{id}} 已撤销:{{msg}}`,jobRevertFailed:`✗ 撤销作业 {{id}} 未完成({{status}}):{{msg}}{{conflicts}}`,jobConflictFiles:`
43
+ 冲突文件:
44
+ {{joinedPaths}}`,delegated:`{{title}}
45
+ /delegates 面板查看进度`,delegateFailed:`委派失败:{{err}}`,extEnableLabel:`启用`,extDisableLabel:`禁用`,extReconnectLabel:`↻ 重新连接`,extReloadLabel:`重载`,extMcpTitle:`{{name}} — 状态 {{status}} · 选操作 · Esc 关`,extItemTitle:`{{name}} — 选操作 · Esc 关`,extPluginGroupTitle:`插件信息`,extPluginLabelDesc:`描述`,extPluginLabelScope:`作用域`,extPluginLabelTrust:`信任`,extPluginLabelSurfaces:`贡献面`,extPluginLabelContributions:`贡献轴`,extPluginLabelStatus:`状态`,extSkillGroupOverview:`概述`,extSkillLabelDesc:`描述`,extSkillLabelStatus:`状态`,extSkillLabelSource:`来源`,extSkillGroupTrigger:`触发方式`,extSkillLabelTriggerMode:`模式`,extSkillLabelPriority:`优先级`,extSkillGroupDependencies:`依赖`,extSkillLabelDependencies:`依赖 skill`,extSkillGroupTags:`标签`,extSkillLabelTags:`标签`,extSkillGroupError:`错误`,extSkillNoDependencies:`无依赖`,extSkillNoTags:`无标签`,extSkillTriggerAuto:`自动(按描述匹配)`,extSkillTriggerManual:`手动(显式调用)`,extViewFullTextLabel:`查看正文`,extSkillFullTextTitle:`{{name}} — SKILL.md 正文`,extSkillNoBody:`(无正文内容)`,extAgentGroupOverview:`概述`,extAgentLabelDesc:`描述`,extAgentLabelStatus:`状态`,extAgentGroupCapabilities:`任务与能力`,extAgentLabelTaskTypes:`任务类型`,extAgentLabelCapabilities:`能力标签`,extAgentGroupTools:`工具权限`,extAgentLabelDefaultTools:`默认工具白名单`,extAgentLabelDisallowedTools:`禁用工具黑名单`,extAgentGroupExecution:`执行配置`,extAgentLabelPromptMode:`提示词注入模式`,extAgentLabelModelTier:`偏好模型层级`,extAgentLabelAllowSubagents:`允许子代理委托`,extAgentNoTaskTypes:`未声明`,extAgentNoCapabilities:`未声明`,extAgentAllTools:`继承全部(未限制)`,extAgentNoDisallowedTools:`无`,extAgentFullTextTitle:`{{name}} — 系统提示词模板`,extPluginTrustLabel:`信任可执行面`,extPluginUntrustLabel:`撤销信任`,extPluginOpenPanelLabel:`{{title}}`,extPluginTrusted:`已信任`,extPluginUntrusted:`未信任(项目级——可执行面被门控)`,extPluginNoSurface:`无可执行面(永远受信任)`,extPluginCapabilityPending:`已信任 · 高危能力待授权({{caps}})`,extToggleFailed:`切换失败:{{err}}`,extToggleReloadFailed:`已{{verb}} {{name}},但刷新能力失败:{{err}}(状态已保存,可重试刷新)`,extReconnectUnavailable:`无法重连 {{id}}(未配置或 MCP 未就绪)`,extReconnected:`已重连 {{id}}`,extReconnectFailed:`重连 {{id}} 失败:{{err}}`,extLogSectionTitle:`最近日志`,extNoLogs:`暂无日志`,extRefreshHint:`r 刷新`,errorRetryPluginSource:`来自插件: {{pluginId}}`,pluginNotFound:`未找到插件 "{{id}}"(在 <.otto>/plugins/ 下)`,pluginTrusting:`已信任插件 {{id}} 的可执行面,热重载中…`,pluginUntrusted:`已撤销对 {{id}} 的信任(下次发现起跳过其可执行面)`,pluginTrustConfirmTitle:`信任插件 "{{id}}"?`,pluginTrustConfirmIntro:`信任将放行其可执行面——这会运行代码:`,pluginSurfaceMcp:`.mcp.json —— 启动 MCP server 二进制`,pluginSurfaceCommands:`commands/ —— !cmd 展开为 shell 命令`,pluginSurfaceScripts:`postinstall/setup —— 安装/首次加载时执行 shell`,pluginSurfacePanels:`panels —— 在 TUI 进程内运行代码`,pluginSurfaceSkills:`skills/ —— 注入模型可能照做的 prompt 内容`,pluginSurfaceAgents:`agents/ —— 注入 agent profile(默认继承全部工具)`,pluginCapabilityIntro:`该插件申请以下高危能力:`,pluginCapabilityProvider:`provider —— 注册 LLM provider,将处理你的凭据与请求流量`,pluginCapabilityTools:`tools —— 注册可被 agent 调用的工具`,pluginCapabilityTuiRenderer:`tui.renderer —— 在 TUI 进程内运行自定义渲染代码`,pluginCapabilityNetwork:`network —— 发起任意网络请求`,pluginCapabilityWireProtocol:`wire-protocol —— 截获全部 provider 请求/响应流量(含凭据)`,pluginCapabilityA2uiComponent:`a2ui.component —— 在 TUI 进程内运行自定义渲染组件代码`,pluginCapabilityPanelBackend:`panel.backend —— 面板可驱动有副作用的后端业务操作`,pluginCapabilityInputResolver:`input.resolver —— 在提交时展开 @ 引用,把内容注入 prompt`,pluginCapabilityA2uiRenderer:`a2ui.renderer —— 运行自定义代码,跨 TUI 与 web-ui 渲染消息`,pluginTrustConfirmHint:`仅信任你已审阅过源码的插件。`,pluginTrustConfirmAction:`信任`,scopeGlobal:`全局`,scopeProject:`项目`,scopeRepository:`仓库`,commonCancel:`取消`,commonClose:`关闭`,unknownLabel:`(未知)`,titleInstall:`安装`,titleDryRun:`预演`,titleUninstall:`卸载`,installUsage:`用法:/install [--global] [--here] [--force] [--dry-run] [--as plugin|skill|mcp] <source>
46
+ source 本地 .zip/.tar.gz 路径、HTTP URL、git 地址 或 npm 包名
47
+ --global 安装到用户级 ~/.otto/(默认项目级 .otto/)
48
+ --here 安装到当前目录 .otto/(绕过向上查找的工作区根;与 --global 互斥)
49
+ --force 覆盖已有同名扩展
50
+ --dry-run 预览安装计划后确认安装
51
+ --as <type> 强制指定内容类型:plugin / skill / mcp`,installMutuallyExclusive:`--global 与 --here 互斥,请只指定其一。`,installLoadingHint:`(探测中,请稍候)`,dryRunDetectFailed:`检测失败:{{err}}`,dryRunPreviewOk:`预览:{{name}} — 检测通过`,planSourcePrefix:`来源:`,installActionLabel:`安装`,installFailed:`安装失败:{{err}}`,capRefreshedInstall:`能力已刷新,新扩展将在下一轮对话生效`,installedRefreshErr:`已安装,但刷新时出错:{{err}}。请执行 /reload 手动刷新。`,pluginInstallConfirmTitle:`安装 {{name}}`,pluginInstallConfirmAction:`安装并授权`,pluginInstallInvalidName:`无效的插件名:{{name}}`,pluginInstallNotFound:`包 {{pkg}} 未安装,请先运行 pnpm install。使用 /install 可从本地文件安装。`,pluginInstallCancelled:`已取消安装`,pluginInstallFailed:`安装失败:{{err}}`,pluginInstallPendingCaps:`{{id}} 已安装,但部分能力需到 /extension 授权`,uninstallActionLabel:`卸载`,uninstalled:`{{type}} "{{name}}" 已从{{scope}}卸载`,uninstallRefreshed:`能力已刷新`,uninstalledRefreshErr:`已卸载,但刷新时出错:{{err}}`,uninstallConfirmTitle:`卸载 {{type}} "{{name}}"?`,uninstallConfirmScope:`范围:{{scopeLabel}} · 将删除以下内容(不可撤销):`,uninstallConfirmYes:`卸载`,uninstallFailed:`卸载失败:{{err}}`,titleModel:`模型`,titleModels:`模型`,titleLogin:`登录`,titleLogout:`登出`,commonNo:`否`,commonSelect:`选择`,modelRefreshLineOk:` ✓ {{provider}} +{{added}} 新增 · {{kept}} 已知 · {{total}} 可用`,modelRefreshLineErr:` ⚠ {{provider}} {{status}}({{reason}})`,modelRefreshLineMuted:` ○ {{provider}} {{reason}}`,modelRefreshLineWarning:` ⚠ {{provider}} {{reason}}`,modelRefreshReasonNotAuthenticated:`未认证(无需处理,可忽略)`,modelRefreshReasonPendingCapability:`能力待授权 — 需到 /extension 信任插件`,modelRefreshHint:`现在 /model 重新选择即可看到拉取后的列表(✓ = 账号可用)。`,modelDelegateProviderTitle:`无 "{{cand}}" provider — 委派一个后台作业来实现它?`,modelDelegateProviderYes:`是,委派后台 agent 作业实现 {{cand}} provider(worktree 隔离)`,modelProviderDelegated:`实现 {{cand}} provider — /delegates 查看进度`,modelNotFoundUse:`未找到:{{arg}}。用 /model 选择。`,modelSelectTitle:`选择模型`,modelSelectTitleAvail:`选择模型(订阅/key = 计费方式)`,modelRecentGroup:`最近使用`,loginNoProviders:`无可用 provider`,loginNotSet:`未设置`,loginPickProvider:`选择要认证的 provider`,loginAuthMethod:`{{name}} — 认证方式`,loginMethodOauth:`浏览器 OAuth(推荐)`,loginMethodKey:`粘贴 API key`,loginKeyTitle:`{{provider}} API key`,loginKeyPlaceholder:`粘贴 key(隐藏)`,loginCancelledNoKey:`已取消 — 未输入 key`,loginKeySaved:`✓ 已保存 {{provider}} 的 API key`,loginOauthCodeIntro:`打开此 URL 并输入下方显示的 code:`,loginOauthCode:`Code:{{code}}`,loginOauthTitle:`{{provider}} OAuth`,loginOauthUrlAuthorize:`打开此 URL 进行授权:`,loginOauthPasteCode:`{{provider}} OAuth — 授权后粘贴显示的 code`,loginOauthBrowserOpened:`已打开浏览器进行授权…`,loginOauthOpenBrowserButton:`打开浏览器`,loginSuccess:`✓ 已登录 {{provider}}`,loginFailed:`登录失败:{{msg}}`,logoutNoStored:`无已存凭据可清除`,logoutPickProvider:`选择要登出的 provider`,logoutSuccess:`✓ 已登出 {{provider}}`,serviceLoginUsage:`用法:/auth --service <url> --token <val>`,serviceLoginNeedValues:`--service 与 --token 都需要提供值`,serviceLoginFailed:`服务登录失败:{{err}}`,serviceLoginBadResponse:`服务登录失败:服务器返回无效响应`,serviceLoginSuccess:`✓ 已登录 {{url}}(用户:{{user}})`,serviceLogoutRemoved:`✓ 已移除服务身份`,serviceLogoutNotFound:`未找到服务身份`,serviceLogoutFailed:`失败:{{err}}`,titleCleared:`已重置`,titleResume:`恢复`,titleReload:`重载`,titleDiagnose:`诊断`,titleArchive:`归档`,titleUnarchive:`取消归档`,titlePin:`置顶`,titleUnpin:`取消置顶`,pinGroupDone:`{{idShort}} · {{title}} 已置顶到 {{group}}`,pinGroupMissingValue:`用法:/pin --group <分组名> [<会话id>...](--group 后缺少分组名)`,clearedDone:`对话已重置——上下文已释放(历史仍可时间旅行回溯)`,sessionNoMatch:`无匹配会话 "{{arg}}"`,resumeAlreadyOn:`已在当前会话`,resumeSessionNotFound:`会话 {{idShort}} 未找到`,resumeSwitched:`{{idShort}} · {{count}} 条消息`,resumeNoSaved:`无已存会话`,resumeFailed:`恢复失败:{{msg}}`,agoJustNow:`刚刚`,agoSeconds:`{{n}} 秒前`,agoMinutes:`{{n}} 分钟前`,agoHours:`{{n}} 小时前`,agoDays:`{{n}} 天前`,resumeSubtitle:`{{sessions}} 个会话 · {{msgs}} 条消息 · 最近 {{recent}}`,resumeSelectTitle:`恢复会话 — 共 {{n}} 个`,resumeArchivedSuffix:` 归档(archived)`,resumeReadOnlySuffix:` 只读(read-only)`,resumePinnedPrefix:`* `,resumeStatusBusy:`运行中`,resumeStatusNeedsInput:`需要输入`,resumeStatusIdle:`空闲`,resumeDefaultPinGroup:`置顶`,resumeRecentGroup:`最近`,reloadDone:`MCP 工具 {{mcpTools}} · 模型 {{models}} · agent {{agents}} · team {{teams}}`,reloadFailed:`热重载失败:{{msg}}`,diagnoseNone:`暂无可提案的复发硬失败`,diagnoseLine:`{{n}}. [{{signalKind}} ×{{count}}] {{directive}}
52
+ 起作业修复:/job {{directive}}`,diagnoseSummary:`诊断出 {{count}} 个改进提案(L1,需你审;起作业才执行)`,archiveCannot:`会话 {{idShort}} 不存在或不可归档`,archiveDone:`{{idShort}} · {{title}} 已归档(再次 /archive 可取消归档)`,unarchiveNotLoaded:`会话 {{idShort}} 未加载到内存`,unarchiveDone:`{{idShort}} · {{title}} 已取消归档`,pinNotLoaded:`会话 {{idShort}} 未加载到内存`,pinDone:`{{idShort}} · {{title}} 已置顶`,unpinDone:`{{idShort}} · {{title}} 已取消置顶`,titleSessionUnlock:`会话解锁`,unlockUsage:`用法:/session unlock <会话ID> [--force]`,unlockNotLocked:`会话 {{idShort}} 当前未被锁定,无需解锁`,unlockInspect:`{{idShort}} 当前被 pid={{pid}}(主机 {{hostname}})持有({{aliveLabel}},最后心跳 {{mtimeAgoSec}} 秒前)。
53
+ 执行 "/session unlock {{idShort}} --force" 可强制释放。`,unlockAliveConfirmed:`已确认存活`,unlockDeadConfirmed:`已确认死亡`,unlockUnknownAlive:`存活性未知(跨主机或旧格式锁)`,unlockRecentReleaseHint:`提示:该锁刚刚被释放(< 5 秒前)——可能只是正常的交接过程中(如另一个 otto 进程正在退出)。建议先重试,再考虑对会话 {{idShort}} 强制解锁。`,unlockHungWarning:`警告:会话 {{idShort}} 的锁持有进程已确认存活,但心跳已停止——这看起来像是 hung 进程,而非正常的活跃写者。`,unlockConfirmTitle:`强制解锁一个仍被存活进程持有的会话?`,unlockConfirmMessage:`会话 {{idShort}} 当前被一个存活进程持有(pid={{pid}},主机={{hostname}})。
54
+
55
+ 若该进程仍在写入时强制解锁,可能导致数据竞态——两个进程可能各自保存冲突的改动。
56
+
57
+ 仅在你确信该进程已卡死/无响应(而非只是较慢)时才应继续。`,unlockConfirmLabel:`仍然强制解锁`,unlockCancelLabel:`取消`,unlockForcedDone:`{{idShort}} 已强制解锁——下次存活进程的保存操作将成功`,unlockCancelled:`已取消强制解锁`,titleSessionCmd:`会话`,sessionUsage:`用法:/session <fork|unlock> [...]`,titleSessionFork:`会话分叉`,forkFailed:`分叉当前会话失败`,forkSuccess:`已分叉并切换到新会话 {{idShort}}`,forkNameTitle:`为分叉会话命名`,forkSuccessNamed:`已分叉并切换到「{{title}}」`,resumeArchivedOnlyTitle:`已归档会话 — 共 {{n}} 个`,titleInspector:`Inspector`,titleBreakpoints:`Breakpoints`,titleBreakpoint:`Breakpoint`,titleReplay:`Replay`,titleStatus:`状态`,inspectUnavailable:`调试不可用(Inspector 未启用)`,bpAllCleared:`已关闭所有断点`,inspectUnknownArg:`未知参数 "{{arg}}",/inspect sources 看全部`,replayNoTrace:`会话 "{{id}}" 无录制的 trace`,statusModelUnset:`(未设置)`,statusLineTitle:`标题:{{title}}`,statusLineSessionId:`会话 ID:{{idShort}}`,statusLineModel:`模型:{{model}}`,statusLineMsgs:`消息数:{{n}}`,statusLineCumOutput:`累计输出 tokens:{{n}}`,statusLineWriteLeaseReadOnly:`写权限:只读(另一进程持有租约)`,statusLineWriteLeaseOk:`写权限:正常`,statusLineRunPaused:`运行状态:已暂停(输入继续或 /continue)`,statusRowTitle:`标题`,statusRowSessionId:`会话 ID`,statusRowModel:`模型`,statusRowMsgs:`消息数`,statusRowOccupancy:`上下文占用`,statusRowCumOutput:`累计输出 tokens`,statusRowWriteAccess:`写权限`,statusValueOccupancy:`{{occ}} / {{window}}{{seg}}`,statusValueWriteLeaseReadOnly:`只读(另一进程持有租约)`,statusValueWriteLeaseOk:`正常`,titleUsage:`用量`,usageNotSubscription:`仅 Anthropic OAuth 订阅计划(Claude Pro/Max)可查看额度用量。API key / 其他供应商走标准分钟级限流,无此概念。`,usageNoSnapshotYet:`本会话尚无用量快照——先发一条消息,再运行 /usage。`,usageLineType:`额度类型:{{type}}`,usageLineStatus:`状态:{{status}}`,usageLineResetsAt:`重置时间:{{when}}`,usageLinePercent:`已用:{{pct}}%`,usageLineStandardLimits:`API 限流:{{reqR}}/{{reqL}} 请求,{{tokRk}}k/{{tokLk}}k token,{{reset}}s 后重置`,usageSubPoolNotInHeaders:`订阅池配额不通过 API 头显示——请去 chatgpt.com 用量面板查看。`,titleAbout:`关于 otto`,aboutVersion:`版本`,aboutBranch:`分支`,aboutCommit:`提交`,aboutRuntime:`运行时`,aboutCPU:`CPU`,aboutMemory:`内存`,aboutShell:`Shell`,aboutTerminal:`终端`,aboutModel:`当前模型`,aboutModelNotSet:`(未设置)`,aboutSession:`会话 ID`,aboutUpdateHint:`运行 /upgrade 检查更新。`,aboutGroupVersion:`版本信息`,aboutGroupRuntime:`运行环境`,aboutGroupSession:`会话状态`,titleCompact:`Compact`,memoryUserSaved:`✓ 已记忆「{{name}}」→ ~/.otto/memory(用户级,跨项目)`,memoryForgetUsage:`用法:/memory forget <名称>`,memoryDeleted:`✓ 已删除记忆「{{name}}」`,memoryNotFound:`未找到记忆「{{name}}」`,memoryDialogEmptyHint:"暂无记忆条目——输入 `#内容` 即可记一条跨会话记忆",memoryDialogDetailTitle:`{{name}}({{source}})`,memoryDialogDetailSourceProject:`项目记忆`,memoryDialogDetailSourceUser:`用户记忆`,memoryDialogDetailEmpty:`(无内容)`,memoryDialogConfirmForgetTitle:`删除记忆`,memoryDialogConfirmForgetMessage:`确认删除「{{name}}」?此操作不可撤销。`,memoryDialogHintView:`查看全文`,memoryDialogHintForget:`删除`,memoryDialogHintBack:`返回`,titleShortcuts:`快捷方式管理`,shortcutsPanelEmptyHint:`暂无快捷方式。按 n 新建第一个。`,shortcutsPanelListHint:`已定义`,shortcutsPanelNewTitle:`新建快捷方式`,shortcutsPanelEditTitle:`编辑快捷方式 "{{name}}"`,shortcutsPanelNameLabel:`名称(@ 后跟的名字,如 review):`,shortcutsPanelTextLabel:`展开文本(提交时替换 [@shortcut:名称]):`,shortcutsPanelNameInvalid:`名称只能包含字母、数字、下划线、连字符`,shortcutsPanelNameDuplicate:`该名称已被使用`,shortcutsPanelTextEmpty:`展开文本不能为空`,shortcutsPanelConfirmDeleteTitle:`删除快捷方式`,shortcutsPanelConfirmDeleteMessage:`确认删除 "{{name}}"?此操作不可撤销。`,shortcutsPanelHintNew:`新建`,shortcutsPanelHintEdit:`编辑`,shortcutsPanelHintDelete:`删除`,compactFailed:`压缩失败:{{msg}}`,titleUpgradeCheck:`Extension Upgrade Check`,upgradeCheckScanning:`检查扩展版本中…`,upgradeCheckNoVersioned:`未发现带版本号的已安装扩展(skill/plugin)。`,upgradeCheckLineUpdate:`{{tag}} {{name}} v{{installed}} → v{{latest}} *有更新*`,upgradeCheckLineLatest:`{{tag}} {{name}} v{{installed}} (最新)`,upgradeCheckSummary:`{{count}} 个扩展可更新,执行 /install --force 重新安装以升级。`,upgradeCheckFailed:`版本检查失败:{{err}}`,titleSessionResumed:`Session resumed`,titleSession:`Session`,resumeTodosAllDone:`此前的任务已全部完成。`,bgForbiddenZone:`
58
+ ⚠️ 此改动触及治理禁区({{count}} 个文件,高危自我修改):
59
+ {{files}}
60
+ 请格外审查;如有误,立即 /job revert {{id}}。`,bgJobApplied:`✓ 已应用作业 {{id}}:{{message}}(撤销:/job revert {{id}}){{zone}}`,bgConflictFiles:`
61
+ 冲突文件:
62
+ {{joined}}`,bgJobIncomplete:`✗ 应用作业 {{id}} 未完成({{status}}):{{message}}{{conflicts}}`,bgAutoReloadFailed:`自动热重载失败(可手动 /reload):{{msg}}`,modelCompactedFor:`已为 {{window}} 窗口压缩上下文`,grillRecommendation:`
63
+ 推荐:{{rec}}`,grillEvidence:`
64
+ 证据:
65
+ {{joined}}`,grillFreeformPlaceholder:`输入你自己的选项 / 补充信息…`,grillAnswerPlaceholder:`输入你的回答…`,titleBackgroundTask:`后台任务`,lifecycleCrossBoundaryDone:`"{{toolName}}" 已完成(在上一个任务中启动——结果未加入本次对话)`,lifecycleCrossBoundaryFailed:`"{{toolName}}" 执行失败(在上一个任务中启动——结果未加入本次对话)`,titleFeedback:`反馈`,feedbackStepTitle:`问题简短标题`,feedbackStepRepro:`复现步骤(可选)`,feedbackStepExpected:`期望行为(可选)`,feedbackStepActual:`实际行为(可选)`,feedbackConfirmTitle:`提交反馈?`,feedbackConfirmMessage:`标题:{{title}}
66
+
67
+ {{bodyPreview}}`,feedbackChannelSubmitting:`提交中…`,feedbackRepoUnresolved:`无法解析目标仓库——请在 .otto/config.json 中配置 "feedback_repo"`,feedbackCreated:`已打开:{{url}}`,feedbackUnavailable:`Feedback 插件不可用(已禁用或未安装)`,compatTrusted_other:`已信任 · MCP 工具 {{count}}`,resumeProbeHiddenHint_other:`(另有 {{count}} 个探针会话未显示,用 /resume --all 查看)`,resumeArchivedHiddenHint_other:`(另有 {{count}} 个已归档会话未显示,用 /resume --archived 查看)`,memoryDialogProjGroup_other:`项目记忆 (.otto/memory) · {{count}} 条`,memoryDialogUserGroup_other:`用户记忆 (~/.otto/memory) · {{count}} 条`,pluginTrusted_other:`已信任 {{id}} · MCP 工具 {{count}}`,resumeRestored_other:`↻ 已恢复会话 {{idShort}}({{count}} 条历史对话进上下文,本轮起接着聊)`,"imageDegradationNotice_image-constraint_other":`已丢弃 {{count}} 张较旧图片(超出供应商图片数量限制)`,imageDegradationNotice_other_other:`已丢弃 {{count}} 张较旧图片以适配上下文窗口`,promptBudgetExceeded_tokens:`输出 token 预算超额({{used}}/{{budget}})——已请求模型收尾`,promptBudgetExceeded_other:`时间预算超额({{used}}/{{budget}})——已请求模型收尾`,sessionCostBudgetExceeded:"会话成本超出预算(${{used}}/${{budget}})——不阻断,详情见 /cost",memoryPressureMessage:`otto 内存占用过高(已达堆上限的 {{usedPct}}%)。立即重启可保存当前全部进度并安全续接,避免不可预期的崩溃。`,authFailed:`认证失败——当前模型{{ps}}的 API Key 无效或已过期。输入 /auth{{ls}} 重新配置凭证后再重试。`,authRefreshFailed:`登录态刷新失败{{ps}}——可能是网络问题或多进程同时登录刷新冲突,请稍后重试;若持续失败请 /auth{{ls}} 重新认证。`,extToggled:`{{verb}} {{name}}{{seg}}`,pluginUsage:`用法:/trust plugin {{seg}}<id>`,installedTo:`{{name}} 已安装到{{scope}}{{seg}}`,statusLineOccupancy:`上下文占用:{{occ}} / {{window}}{{seg}}`,extPluginTitle:`{{name}} — {{state}} · 选操作 · Esc 关`,extSkillTitle:`{{name}} — {{state}} · 选操作 · Esc 关`,extAgentTitle:`{{name}} — {{state}} · 选操作 · Esc 关`,bpToggled:`{{point}} {{state}}`,pluginInstalled:`{{seg}}`,pinBatchSummary:`{{seg}}`,extSkillSourceLabel:`{{seg}}`,upgradeAvailableLines:[`当前版本: v{{current}}`,`最新版本: v{{latest}}`,``,`热升级流程:npm install -g @x-otto/cli@latest → 自动重启`,``,`⚠ 升级期间当前会话将中断。`,`输入 /upgrade --force 确认升级。`],extHealthSummary:`健康度 挂起 {{hookTimeouts}} 次 · 工具超时 {{toolTimeouts}} 次`,extHealthSummary_err:`健康度 挂起 {{hookTimeouts}} 次 · 工具超时 {{toolTimeouts}} 次 · 最近错误 {{lastError}}`,keybindTitle:`快捷键`,keybindSavedRestartHint:`已保存。新键位需重启会话后生效。`},permission:{allowTool:`允许工具:`,bashCommand:`Bash 命令`,approve:`批准`,deny:`拒绝`,alwaysAllow:`始终允许`,riskLabel_low:`低风险`,riskLabel_medium:`中风险`,riskLabel_high:`高风险`},hint:{select:`选择`,confirm:`确认`,execute:`执行`,cancel:`取消`,delOne:`删一条`,choose:`选定`,option:`选项`,question:`问题`,shortcut:`快捷`,toInterrupt:`中断`,pausedContinue:`输入继续或 /continue`,steer:`引导`,queue:`排队`,history:`历史`,autosuggestAccept:`接受建议`,autosuggestMenu:`补全菜单`,submit:`提交`,kill:`终止`,output:`输出`,apply:`应用`,switch:`切换`,delete:`删除`,close:`关闭`,collapse:`收起`,retry:`重试`,view:`查看`,load:`加载`,check:`勾选`,grab:`抓取`,drop:`放下`,move:`移动位置`,edit:`编辑`,exit:`退出`,dismiss:`消除`,quick:`快捷`,refresh:`刷新`,subagents:`子代理`,tasks:`任务`,viewDetail:`↵ 查看详情`,back:`返回`,scroll:`滚动`,find:`查找`,tabSwitchOutput:`切换视图`,tabFocus:`切换面板`,tabZone:`切换区域`,toggle:`开/关`,add:`添加`,run:`运行`,runNow:`立即运行`,detail:`详情`,logs:`日志`,switchField:`切换字段`,discard:`放弃`,confirmCancel:`确认取消`,confirmRemove:`确认删除`,abort:`取消`},history:{label:`历史`,capped_other:`最早的 {{count}} 条消息已从内存视图中移除(会话消息已达条数上限,存储中仍完整保留)`,cappedBytes_other:`最早的 {{count}} 条消息已从内存视图中移除(会话消息内存驻留超出字节预算,存储中仍完整保留)`,cappedMemoryPressure_other:`最早的 {{count}} 条消息已从内存视图中移除(内存压力收紧会话驻留,存储中仍完整保留)`,cappedLossy_other:`⚠ 最早的 {{count}} 条消息已从模型上下文中移除,且**未能生成摘要**——这部分内容模型将不再可见(自动压缩连续失败后的兜底裁剪)。原始记录仍完整保留在存储中,可用 /history 回看。`},common:{more:`更多`,disabled:`不可用`,wordOr:`或`,moreLinesLabel:`… 还有 {{n}} 行`,thoughtLines:`思考({{n}} 行)`,noContentAvailable:`(无内容)`,contentUnavailable:`(内容不可用——会话已恢复,原始文件内容未持久化)`,cancelButton:`取消`,upgradeButton:`升级`,escClose:`Esc 关闭`,noMatches:`无匹配`,confirmButton:`确认`,genericCancelButton:`取消`,dontRemind:`不再提醒`,okButton:`确定`,abortButton:`中止`,pauseButton:`暂停`,abortAndExitButton:`终止并退出`,abortAndRestartButton:`终止并重启`},model:{noneAvailable:`当前没有可用模型 — 请先`,goLogin:`登录`,setKey:`配置凭证`,pendingCapabilities:`{{count}} 个 provider 插件待授权`,goGrantCapability:`去授权`,noProviderPlugin:`当前没有可用的模型。安装 provider 插件后开始使用。`,goInstallPlugin:`安装 provider 插件`,switchedTo:`已切换到 {{label}}`,title:`配置的模型不可用`,reasonNotFound:`原因:未找到该模型 id(可能已下线或拼写有误)`,reasonUnauthenticated:`原因:{{provider}} 尚未认证`,hint:`/auth 认证该 provider · /model 切换`,permanent:`切换到此模型`,login:`去登录`,dismiss:`退出`,goToLoginButton:`去登录`,goToExtensionButton:`去授权`,forcedUpgradeTitle:`强制升级`,noRegistry:`无可用的模型注册表。`,notFound:`未找到模型: {{name}}。用 /model 列出可用模型。`,listFooter:` /model <id> 切换。* = 当前`,visionDelegateToast_other:`{{count}} 张图已由 vision 模型代述(当前模型不支持视觉输入)`,fallbackLoginToast:`去登录提供者 {{provider}}…`},welcome:{providerDesc:{"anthropic-provider":`Anthropic Claude,OAuth 登录(推荐)`,"deepseek-provider":`DeepSeek,需 DEEPSEEK_API_KEY`,"openai-codex-provider":`OpenAI Codex,需凭据`},version:`版本`,workspace:`工作目录`,extensions:`扩展`,msgCountLabel_other:`{{count}} 条消息`,itemCountLabel_other:`{{count}} 项`,greeting_late:`夜深了{{who}},周{{wday}}——万籁俱寂,正好深思。`,greeting_earlyMorning:`早安{{who}}!周{{wday}}清晨——新灵感正等着你。`,greeting_morning:`周{{wday}}上午好{{who}}——一起创造些了不起的东西吧。`,greeting_afternoon:`周{{wday}}下午好{{who}}——保持势头,继续推进。`,greeting_evening:`周{{wday}}晚上好{{who}}——收尾复盘的好时光。`,greeting_night:`深夜了{{who}},周{{wday}}——最好的灵感往往在夜深人静时迸发。`,tipLabel:`OTTO 小贴士`,shadowBadge:`影子`,shadowChip:`影子模式 — 不写入磁盘`,shadowBannerTitle:`影子会话 — 零磁盘落痕`,shadowGuarantee:`保证:otto 自有状态(凭据、会话、记忆、教训、配置、trace、日志)本次会话只在内存中,不写入磁盘。`,shadowNotGuaranteedTitle:`不保证(仍可能留痕):`,shadowNg1:`你让 otto 用 write/edit 工具改的项目文件(你的意图产物)`,shadowNg2:`shell 命令、git、MCP server、第三方插件的自主写盘`,shadowNg3:`provider 服务端的日志、遥测与账单记录`,shadowNg4:`OS 层痕迹:你的 shell 历史、进程列表、网络连接`},onboarding:{title:`开始使用`,nameQuestion:`怎么称呼你?`,langQuestion:`选择语言`,namePlaceholder:`例如:小明`,nameDesc:`昵称用于会话和通知中的个性化称呼。`,langFootnote:`之后可用 /preference lang 切换。`,langOptions:{en:`English (en)`,zh:`中文 (zh)`,auto:`跟随系统自动检测`},skip:`跳过`,done:`完成`,stepName:`昵称`,stepLang:`语言`,stepTheme:`主题`,stepCounter:`第 {{current}}/{{total}} 步`,langAuto:`跟随系统`,themeQuestion:`配色主题`,themeFootnote:`移动高亮即实时预览;跟随终端会探测你的终端背景色`,themeDark:`深色`,themeLight:`浅色`,themeSystem:`跟随终端`,hintNext:`下一步`,hintDone:`完成`,hintSkip:`跳过`,hintBack:`上一步`,hintQuick:`直选`},prompt:{ready:`就绪`,streaming:`生成中`,default:`输入消息,或 /help 查看命令…`,working:`Agent 处理中 — 输入引导当前回合…`,setup:`尚未配置完成——输入 /setup 从上次的进度继续`,fallback:`输入消息…`,unfocused:`输入保留中,随时继续…`,submit:`提交`,readySuffix:`{{n}} 个就绪`,upgradeRequired:`需要更新 — 输入 /upgrade 继续`,submitButton:`提交`,defaultTitle:`输入`,reviewingPlaceholder:`回看中 · Esc 回最新`},questions:{readyToSubmit:`可以提交答案了。`,someUnanswered:`还有问题未作答 — 仍要提交?`},freeform:{tab:`补充`,filled:`*`,empty:`-`,label:`输入补充说明(可选):`,placeholder:`在此输入补充信息…`,advance:`完成(前进至提交)`},panelTitle:{memory:`memory`,editedFilesTitle:`已编辑文件`},inspText:{thinking:`思考`,thinkingLabel:`思考中…`},update:{forcedBanner:`⚡ 强制升级至 v{{latest}} — 输入 /upgrade 现在升级`,availableBanner:`🆕 v{{latest}} 可用 — 输入 /upgrade 查看详情`},status:{failed:`失败`,interrupted:`已中断`,done:`完成`,stopped:`暂停`},task:{leftLabel:`{{done}}/{{total}} · 剩 {{left}} 项`,title:`任务`,collapsedHint:`已折叠`,detailTitle:`任务详情`,turnInfo:`(回合 #{{turn}}, {{shown}}/{{total}} 条消息)`,turnTag:`(回合 #{{turn}})`,truncated:`… 还有 {{n}} 条消息已截断`,statusLabel_pending:`待办`,statusLabel_in_progress:`进行中`,statusLabel_done:`完成`,statusLabel_skipped:`已跳过`,statusLabel_failed:`失败`},tool:{edit:`编辑`,write:`写入`,read:`读取`,tasks:`任务`,subagent:`子代理`,unknown:`未知`,fallback:`工具`,compact:`压缩`,prune:`裁剪`,history:`历史`,session:`会话`,run:`运行`,model:`模型`,effort:`投入档`,budgetLabel:`{{used}}/{{max}} 工具`,countLabel_other:`{{count}} 个工具`,chainSummary_other:`[{{count}} 个工具: {{names}}]`},diff:{modeLabel:`对比 HEAD`,loading:`整个文件 diff 加载中…`,error:`整个文件 diff 不可用:{{message}}`,linesTotalLabel_other:`{{count}} 行`,fileCountLabel_other:`{{count}} 个文件`,fileOpLabel_edit:`已修改`,fileOpLabel_write:`已创建`,fileOpLabel_other:`已删除`},compact:{ed:`更早的消息已压缩`,pruned:`工具输出已裁剪以适应上下文`,ing:`正在压缩上下文…`,edResult:`✓ 上下文已压缩:{{before}} → {{after}} 条消息(完整转录已保留)`,noop:`无需压缩——当前上下文已经很小。`,unavailable:`压缩不可用:当前会话未启用记忆/压缩。`,logTitle:`压缩/裁剪日志`,logEmpty:`本会话暂无压缩或裁剪事件。`,logCompactRow:`{{before}} → {{after}}(保留 {{pct}}%)`,logDetailTitle:`{{kind}} · {{time}}`,logNoSummary:`该事件无可用摘要。`,logViewSummary:`查看摘要`,ingVerb:`压缩中`,logHistoryCappedRow_other:`{{count}} 条消息已从内存移除(存储中仍保留)`,ionStageLabel_analyze:`分析上下文中`,ionStageLabel_summarize:`生成摘要中`,ionStageLabel_finalize:`整理结果中`,logPruneRow:`节省约 {{tokensSaved}} tokens`,logPruneRow_pruned_other:`节省约 {{tokensSaved}} tokens({{count}} 条工具输出)`},lease:{denied:`本轮改动未保存——另一 otto 进程持有此会话写权`,restored:`写权已恢复,此后改动正常保存`,deniedToastTitle:`会话只读(改动不会保存)`,deniedToastBody:`原因:另一个 otto 进程正在写这个会话(如另一个终端窗口,或 /exit -r 重启未完全交接)。
68
+ 本窗口仍可正常对话,但改动不会保存。
69
+ 解决:① 关闭另一个 otto 进程后,本会话会在下次保存成功时自动恢复可写;② 或退出本窗口,/resume 换一个会话继续工作。`,restoredToastTitle:`会话已恢复可写`,restoredToastBody:`此后的改动会正常保存。`},pause:{titleRequested:`等待暂停`,bodyRequested:`将在当前回合结束后自动暂停`,titleActive:`已暂停`,bodyActive:`Agent 运行已暂停,排队消息不会自动执行`,btnCancel:`取消暂停`,btnResume:`继续运行`,footerDismiss:`Esc 关闭浮层,暂停请求仍在后台生效`,footerActive:`Enter 接受 · Esc 关闭`,toolCount:`{{n}} 工具 · {{s}}s`,toolTotal:`本回合执行了 {{n}} 个工具`},run:{messageFooter:`输入任意消息或 /continue 继续`,resumedMessageBody:`Agent 已恢复运行`,pauseCancelledMessageBody:`暂停请求已取消,Agent 继续运行`,messageBody:`Agent 运行已暂停,排队消息不会自动执行`,messageBody_n:`Agent 运行已暂停(本回合 {{n}} 个工具),排队消息不会自动执行`},shell:{running:`运行中`,terminated:`已终止`,errored:`错误`,exit:`退出码 {{code}}`,copyHint:`复制输出`,copiedTitle:`Shell`,copiedBody:`已复制到剪贴板`,hint:`问 AI`,exitCode:`退出码 {{code}}`,askAiTerminated:`被信号终止`,unknownError:`未知错误`,prompt:"命令 `{{command}}` 执行失败({{errorLabel}}),输出如下,请帮忙排查:\n\n```\n{{output}}\n```",truncated:`...(已截断,完整输出请用 c 键复制到剪贴板查看)`,viewAll_other:`查看全部输出(共 {{count}} 行)`,moreLines_other:`... 还有 {{count}} 行 ...`},spinner:{verbs:[`处理中`,`思考中`,`计算中`,`运行中`],outputPercent:`{{pct}}% 上限`,estimatedPercent:`~{{pct}}%`},bg:{runningVerb:`运行 {{tool}}`,tasksTitle:`委派`,empty:`(无后台任务)`,noOutput:`(暂无输出)`,live:`实时`,following:`跟随中…`,jobsLabel:`{{n}} 个委派`,runningSuffix:`{{n}} 个运行中`,doneSuffix:`{{n}} 个完成`,needInputSuffix:`{{n}} 个待输入`,metaReady:`就绪`,metaNeedsInput:`待输入`,agentStatusLabel:`{{st}}`,procStatusLabel:`{{s}}`,categoryLabel_job:`委派作业`,categoryLabel_bash:`Bash 命令`,categoryLabel_other:`子代理`,metaExited:`已退出`,metaExited_code:`已退出 {{code}}`},subagent:{sTitle:`子代理`,sRunning:`{{n}} 个运行中`,header:`子代理 @{{title}} · {{status}}`,contextEarlierLines:`↑ {{n}} 行更早 · ↵ 看完整可滚动转录`,sWorking_other:`子代理运行中({{count}} 个子代理)`},agent:{interruptTitle:`中断 agent?`,interruptMessage:`当前 agent 回合仍在运行。确认中断会停止本轮并标记为已中断。`,interruptConfirm:`中断`},queue:{label:`队列`,empty:`队列为空`,editTitle:`编辑队列项 {{index}}/{{total}}`,editSendNowButton:`直接发送`,editConfirmButton:`确定`,editSendNowHintBusy:`将作为补充说明注入当前回合`,editSendNowHintIdle:`将立即发送为新消息`,exitTitle:`退出排队命令面板`,exitConfirm:`清除并退出`,exitMessage:`面板中有 %d 条排队命令将被清除。`,popTitle:`移除排队消息?`,popMessage:`当前有一条追问消息排队中。是否移除最新排队消息,而不是中断正在运行的回合?`,popConfirm:`移除排队消息`,dFollowUpToast:`模型还在跑——已加入追问队列,完成后自动发送`},retry:{reason:`{{reason}}`,defaultTitle:`错误详情`,attempt:`重试 {{attempt}}/{{max}}`,countdown:`{{s}} 秒后重试…`,progressSep:`,`,nowButton:`立即重试`,hint:`↵/r`,stopButton:`停止`,hintWithStop:`↵/r 重试 · Esc 停止`},error:{typeLabel:`{{type}} 限额已达上限`,retryNow:`立即重试`,switchModel:`切换模型`,title:`请求失败:{{reason}}`,defaultTitle:`请求失败`,exhaustedTitle:`多次重试后仍失败`,autoCountdown:`第 {{attempt}}/{{max}} 次重试,{{seconds}} 秒后自动重试`,manualBody:`第 {{attempt}}/{{max}} 次重试,需先完成操作才能重试`,exhaustedBody:`已重试 {{max}} 次仍失败`,resetsIn:`配额将在 {{hms}} 后重置`,unknownReset:`重置时间未知`,hint:`←/→ 选择 · ↵ 确认 · r 立即重试 · Esc 取消`},pulse:{title:`这次体验如何?`,ratingGood:`好评`,ratingNeutral:`一般`,ratingBad:`待改进`,commentTitle:`{{ratingLabel}} · 想补充点什么吗?(可选)`,commentPlaceholder:`说点什么…`,hintRating:`←/→/Tab 切换 · ↵ 选择 · Esc 关闭`,hintComment:`↵ 提交 · Esc 关闭(评分仍会保存)`},find:{inputLabel:`查找:`,matchCount:`{{current}}/{{total}}`,tabPrompt:`提示词`,tabConversation:`对话`,tabDiff:`Diff`,tabDiagnostics:`诊断`,searchNoMatches:`无匹配`},schedule:{sLabel:`定时任务`,sEmpty:`暂无定时任务。用 /schedule add 创建`,oneShot:`单次`,next:`下次: `,panel:{noTasks:`暂无定时任务。`,pressToAdd:`按 {{key}} 创建第一个定时任务。`,examples:`示例: {{c1}} 每天 09:00 · {{c2}} 每 30 分钟`,running:`运行中`,failedCanceled:`失败/已取消`,readonlyNet:`{{cross}} 网络错误 — 无法连接调度服务`,readonlyLease:`{{cross}} 只读 — 另一个终端持有 fire-ownership 租约`,moreAbove:`... 上方 {{n}} 条`,moreBelow:`... 下方 {{n}} 条`,failedErr:`(失败: {{err}})`,detail:{id:`ID`,status:`状态`,type:`类型`,cron:`Cron`,prompt:`提示词`,nextFire:`下次触发`,lastFire:`上次触发`,never:`从未`,jobRunning:`{{cross}} 任务运行中 — {{id}}`,recent:`最近 ({{n}} 条)`,loadingLogs:`加载日志...`,noLogs:`暂无日志`},logsTitle:`日志: {{id}}`,form:{newTitle:`新建定时任务`,editTitle:`编辑: {{id}}`,name:`名称`,cron:`Cron`,type:`类型`,status:`状态`,prompt:`提示词`,preview:`预览`,auto:`(自动)`,cronPlaceholder:`________________`,recurring:`循环`,enabled:`已启用`,disabled:`已禁用`,toggleHint:`(←/→ 切换)`,templatesHint:`按 ←/→ 选择模板`,templates:`模板`,previewNext:`下次触发: {{time}}`,previewJitter:`下次触发: {{time}} + 0-30分钟抖动`,previewJitterOnce:`下次触发: {{time}} + ~90秒抖动`,previewCron:`cron: {{cron}} (循环)`,previewCronOnce:`cron: {{cron}} (单次)`,previewEmpty:`输入有效的 cron 表达式`,invalidCron:`无效 cron`,required:`Cron 和提示词为必填项`,saving:`保存中...`,createFailed:`创建失败`,saveFailed:`保存失败`},confirmCancelTitle:`取消任务?`,confirmCancelBody:`这将取消 {{name}} 当前正在运行的任务。`,confirmCancelNote:`定时任务定义不受影响。`,confirmRemoveTitle:`删除定时任务?`,confirmRemoveBody:`这将永久删除 {{name}} ({{id}})。`,confirmRemoveWarn:`此操作不可撤销。`}},draft:{sLabel:`草稿`,sEmpty:`暂无草稿。用 Ctrl+S 保存一条`,saved:`已保存到草稿`,saveEmpty:`输入为空,无内容可保存`},prompts:{label:`Prompt 记录`,empty:`暂无 Prompt 记录`},scroll:{above:`↑ 上方 {{n}} 行`,below:`↓ 下方 {{n}} 行`,viewportLinesAbove:`上方行`,viewportLinesBelow:`下方行`},service:{sTitle:`服务`,sEmpty:`(无运行中的服务)`,countLabel_other:`服务`},insp:{live:`实时 · {{n}} 行`,row:`第 {{cur}}/{{total}} 行`,replay:`回放`,paused:`⏸ 已暂停`,pausedBig:`⏸ 已暂停`,inspect:`检查`,hintPause:`c 继续 · s 单步 · n 下一步 · o 步出 · x 停止`,hintFocus:`Ctrl+G 聚焦`,hintBp:`↑↓ 选择 · Tab 切换 · space 开关 · Esc 退出`,bpIdle:`▶ ⤼ ⤓ ⤴ ⏹ 空闲 — 运行一次以在启用的断点处暂停`,variablesIdle:`变量在暂停时显示 — 去 Sources 启用一个点位再运行`,breakpoints:`断点`,noneInteractive:`— 无(需交互式 inspector)—`,noTools:`— 暂无工具调用 —`,noEvents:`— 暂无追踪事件(运行一次)—`,noUsage:`— 暂无用量(运行一次)—`,noLineage:`— 无血缘 —`,toolbar:`▶ 继续(c) ⤼ 跨过(n) ⤓ 单步(s) ⤴ 步出(o) ⏹ 停止(x)`,variables:`变量`,editKeys:` Enter=保存 Esc=取消`,injectMsg:`注入消息`,changeData:`改数据: t 思考 · [ ]温度 · i 注入 · e 系统提示`,budgetOverhead:`开销`,budgetMessages:`消息`,budgetFree:`可用`,budgetLastTotal:`上轮 {{lastIn}}→{{lastOut}} · 累计 {{totalIn}}→{{totalOut}}`,liveTag:`▸ 实时`,userPrefix:`用户: `,thinkingFull:`思考(全文):`,toolRunning:`{{tool}}(运行中)`,toolCall:`{{tool}}(调用)`,assistantFallback:`助手文本`,emptyPrompt:`(提示)`,endTurn:`· 回合结束`,treeThinking:`思考 ⟨{{n}} · {{chars}} 字符⟩`,bpCatAgentWorkLoop:`Agent 工作循环`,bpCatWorkLoopInjection:`工作循环注入`,bpCatToolExecutor:`工具执行器`,bpCatSessionPrompt:`会话提示生命周期`,bpCatLifecycleHook:`生命周期钩子`,bpCatTurnObservable:`回合可观测`,bpCatCustom:`自定义`,debugCall:`调用`,debugLlmParams:`LLM 参数`,debugSystemPrompt:`系统提示`,debugMessages:`消息 ({{n}})`,debugTokens:`Token 入 {{inTokens}} · 出 {{outTokens}}`,debugEmpty:`(空)`,debugEditsPending:`编辑: {{parts}}(恢复时应用)`,debugEditSysPrompt:`系统提示`,asstPrefix:`助手: `,thinkingPrefix:`思考… `,noTurnData:`暂无回合数据。`,treeAssistantDeltas_other:`助手 ⟨{{count}} 增量 · {{chars}} 字符⟩`,hintTree:`↑↓ 移动 · Tab 切换 · w 血缘{{whySeg}} · z 展开{{expandSeg}} · space 折叠 · Esc 退出`},budget:{exhaustedTitle:`已达本回合工具步数预算——任务可能还没干完,要我接着干完吗?`,continue:`接着跑`,stop:`先停下`,stoppedNote:`⏸ 已停在工具步数预算上限——任务可能还没全干完。需要的话直接继续指示我即可接着干(每次对话都会重置本回合工具预算)。`,tokensLabel_other:`{{count}} token`,tokenBudgetLabel:`{{used}}/{{budget}} tok`},cmdDesc:{help:`显示可用命令`,exit:`退出 TUI;/exit --restart 重启到同一会话`,clear:`清屏并重置会话`,abort:`中止当前 agent 运行`,copy:`复制上一条助手回复`,model:`列出模型或用 /model <id> 切换`,setup:`查看上手进度(provider → 登录 → 模型),带下一步直达按钮`,status:`显示会话状态`,inspect:`打开 inspector(Events/Tools/Sources/Budget);/inspect sources|<point>|off`,replay:`回放会话追踪(/replay [<id>|off])`,delegates:`开关 Delegates 面板(↑↓ 选择 · k 终止 · o 输出 · a 应用)。别名:/jobs /bg`,job:`委派后台 agent 作业:/job <指令>(worktree 隔离 + 全套工具含 MCP)。改了代码→产 diff 待 apply;整理/调研类→产文字结果(按 o 看)。`,extension:`管理可插拔扩展(MCP / 技能 / agent):↑↓ 选择 · Enter 切换 · Esc 关闭`,compact:`立即压缩对话上下文(摘要更早的消息以释放 token)`,memory:`项目+用户记忆:/memory [user|project|<名称>|forget <名称>];/memory user <内容> 记跨项目笔记(# 写项目级)`,login:`登录 provider(OAuth 或 API Key);/auth [<provider>]`,logout:`移除某 provider 的已存凭证;/logout [<provider>]`,effort:`切换推理投入档(/effort low|medium|high|xhigh|max)`,preference:`偏好设置:/preference [lang|theme]`,permissions:`查看/清空始终允许列表(/permissions [clear])`,context:`显示上下文用量分解(system/tools/messages/cache/free 分段条)`,attach:"连接到 `otto serve` 上运行的会话:/attach <sessionId>(本期只读预览)",history:`打开输入历史搜索面板。别名:/hist`,prompts:`查看 Prompt 记录(本会话已提交的 prompt 列表)`,notification:`开关通知中心面板(≡ Ctrl+N)。别名:/notif`,pin:`置顶当前会话(/resume 列表排序权重);批量/分组:/pin [<会话id>...] [--group <名称>]`,unpin:`取消置顶当前会话`},pref:{permModeSwitched:`权限模式 → {{label}}`,languageUsage:`用法:/preference lang <en|zh>`,languageName_zh:`中文`,languageName_other:`English`,permModeLabel_confirm:`批准`,permModeLabel_auto:`自动`,permModeLabel_bypass:`全自动`,permModeLabel:`{{context}}`,authModeLabel_oauth:`订阅`,authModeLabel_api_key:`密钥`,authModeLabel_env:`密钥`,authModeLabel:`{{context}}`,languageSwitched:`语言 → {{name}}({{l}})`},time:{justNow:`刚刚`,minAgo:`{{min}} 分钟前`,hourAgo:`{{hr}} 小时前`,dayAgo:`{{day}} 天前`},paste:{confirmTitle:`粘贴大段文本?`,collapseLabel:`折叠为 `,confirm:`确认`,cancel:`取消`,view:`查看`,viewTitle:`复制内容`,titlePasteExpired:`粘贴已失效`,expiredToast_other:`{{count}} 处粘贴内容已失效,请重新粘贴`,previewSummary_body:`─── 共 {{lines}} 行, {{chars}} 字符 ───`},select:{filterPlaceholder:`输入过滤…`,noMatches:`无匹配`,clearHint:`清除 / `,matchCount_other:`{{count}} 个匹配`},sigil:{filterPlaceholder:`输入过滤…`,noMatches:`无匹配`,searching:`搜索中…`,catAgent:`代理`,catRecent:`最近使用`,catResource:`自定义资源`,catShortcut:`快捷方式`,catExtension:`扩展`,catPerson:`成员`,catHashtag:`模板`,catPlugin:`插件`,catFile:`文件`,catModel:`模型`,loadingFile:`加载文件…`,readFullFile:`查看全文`,catSkill:`技能`,titleMention:`提及`,titleHashtag:`标签`},toast:{editorError:`编辑器错误`},context:{tokensLabel:`{{formatted}} token`,title:`上下文`,noData:`暂无上下文数据 — 等待首次 API 响应。`,viewDetails:`Enter 详情`,systemHeading:`系统上下文`,systemMeta:`{{tokens}}t · {{stable}} 稳定 + {{volatile}} 易变`,laneVolatile:`易变`,laneCache:`缓存`,conversationHeading:`对话`,conversationMeta:`{{tokens}}t · {{turns}} 轮`,earlierTurns:`更早 {{count}} 轮({{tokens}}t)`,turnRow:`第 {{index}} 轮 · {{messages}} 条 · {{tokens}}t`,totalLine:`合计 {{used}} / {{window}}({{percent}}%)· 空闲 {{free}}t`,tagPruned:`已裁剪`,tagCompacted:`已压缩`,tagTruncated:`已截断`},transcript:{frozenNew:`条新消息`,escToLive:`Esc 回最新`,you:`你`,assistant:`助手`,loadingEarlier:`加载更早历史…`,emptyEarlier:`— 已到最早消息 —(PgUp/↑ 滚动 · Esc 回最新)`,findBar:`/{{query}} · {{count}}`},trust:{title:`信任此文件夹?`,body:`访问工作区:
70
+ {{path}}
71
+
72
+ 这是你创建或信任的项目吗(你自己的代码、知名开源项目、或团队的工作)?
73
+ otto 将在此读取、编辑、执行文件。不确定就先查看此目录,或以只读方式打开。`,optTrust:`信任 — 完整访问(读 / 改 / 执行 + 应用其配置)`,optReadonly:`只读这一会话 — 安全查看,禁写 / 执行 / 联网`,optExit:`否,退出`},parent:{title:`检测到父级 workspace`,body:`当前目录 {{currentRoot}} 没有 workspace 身份,
74
+ 但上级目录 {{parentRoot}} 已有 workspace。`,optUseParent:`使用上级 workspace — 共享会话与记忆`,optCreateNew:`在当前目录创建新 workspace — 独立身份`,optExit:`退出`},notif:{title:`通知`,readDivider:`──── 已读 ────`},confirm:{reset:`确认重置`,replace:`确认替换`,abortConfirmTitle:`中止 Agent?`,abortConfirmMessage:`Agent 正在运行中。中止后当前回合将丢失,未完成的写入操作可能不完整。`,exitConfirmTitle:`终止并退出 otto?`,exitConfirmMessage:`Agent 正在运行中。退出将中止当前回合,未完成的写入操作可能不完整。`,exitRestartConfirmTitle:`终止并重启 otto?`},cache:{sessionLabel:`会话`,lastTurnLabel:`最近一轮`},recovery:{titleProvider:`尚未安装 AI provider`,hintProvider:`otto 需要一个 provider 才能连接模型。`,ctaProvider:`运行 /setup 安装`,titleAuth:`已安装 provider,尚未连接`,hintAuth:`登录或粘贴 API key 即可继续。`,ctaAuth:`运行 /setup 连接`,titleModel:`尚无可用模型`,hintModel:`凭据可能缺失或已过期。`,ctaModel:`运行 /setup 选择模型`},setup:{wizardApiKeyPlaceholder:`输入或粘贴密钥,按 Enter 确认`,title:`设置向导`,welcomeTitle:`欢迎使用 otto,你的 AI 伙伴`,welcomeGreeting:``,welcomeDescription:`本向导将通过 4 个步骤帮你完成初始设置:选择 AI 服务商、登录、选择模型,然后开始对话。`,welcomeDontShowAgain:`不再显示此向导`,welcomeStart:`开始`,welcomeCancel:`取消`,step1Subtitle:`otto 需要至少一个 AI provider 才能工作。选择一个安装——稍后可以通过 /extension 添加更多。`,step3Subtitle:`选择 provider 的认证方式。`,step4Subtitle:`选择一个模型开始对话。`,step5Done:`一切就绪!输入消息即可开始。`,installing:`安装中…`,installed:`已安装!`,installFailed:`安装失败:{{reason}}`,loginOAuth:`通过 OAuth 登录(推荐)`,loginApiKey:`粘贴 API key`,loggingIn:`登录中…`,loginFailed:`登录失败:{{reason}}`,exitTitle:`退出向导`,exitConfirm:`退出设置向导?进度将被保存 — 稍后可用 /setup 继续。`,errorTitle:`设置出错`,errorMessage:`设置步骤 {{step}} 失败:{{msg}}
75
+ 已记录崩溃报告。`,stepNameProvider:`LLM 服务商`,stepNameLogin:`登录`,stepNameModel:`模型`,stepNameStart:`开始`,actionInstall:`安装`,actionLogin:`登录`,installPendingCapabilities:`已安装,但部分能力尚未授权——请运行 /extension 授予,否则该 provider 不会提供任何模型。`,modelRecommendedTag:`推荐`,modelRecommendedHint:`已把推荐项排在最前——随时可用 /model 更换。`,modelUnusableUnauthenticated:`需要先登录`,modelUnusableOauthRisk:`订阅方案可能被限流`,authFailedNetwork:`无法连接授权服务,可能是网络或代理问题。`,authFailedRejected:`授权未完成。`,actionOpenProxySettings:`打开代理设置`,actionRetryAuth:`重新登录`,oauthWaiting:`等待浏览器中完成授权…`,actionOpenAgain:`重新打开授权页`,actionUseApiKeyInstead:`改用 API key`,apiKeyStorageNote:`保存在本机凭据文件中——不会写入当前项目,也不会进入聊天记录。`,installFailedRecovery:`{{provider}} 安装失败。选择下一步:`,actionRetryInstall:`重试安装`,actionChooseAnotherProvider:`换一个 provider`,capabilityGranted:`已授予能力:{{caps}}`,capabilityRevokeHint:`可随时在 /extension 中撤销。`},install:{title:`正在安装 {{source}}`,phaseResolving:`解析来源…`,phaseDetecting:`检测内容…`,phaseInstalling:`安装中…`,phaseRefreshing:`刷新能力…`,reloadingDetail:`正在刷新能力…`,done:`已安装`,summaryFailed:`安装失败`,summaryPartial:`部分安装成功`,nextStepForce:`提示:加 --force 可覆盖已存在的内容`,nextStepReload:`提示:执行 /reload 手动刷新能力`,failureOverflow:`(完整列表见下方消息)`,partialCounts:`{{ok}} 个成功,{{fail}} 个失败:`},proxy:{title:`Proxy`,groupConfig:`配置`,groupAbout:`说明`,fieldUrl:`代理地址`,fieldEnabled:`启用状态`,dialogSetUrl:`设置代理地址`,dialogEditUrl:`编辑代理地址`,urlPlaceholder:`http://127.0.0.1:7890`,urlEmpty:`尚未设置 — 例如 http://127.0.0.1:7890`,stateEnabled:`已启用`,stateDisabled:`已停用`,actionClear:`清除配置`,clearTitle:`清除代理配置`,clearMessage:`确认清除代理配置?({{url}})`,clearConfirm:`清除`,aboutScope:`作用于所有出站 HTTP:模型 API、登录、网页抓取、版本检查。`,aboutLoopback:`本机地址(localhost / 127.0.0.1)始终直连。`,aboutStorage:`配置存储在 {{path}}`,aboutCommand:`命令行等效:/proxy [<url>|on|off|status|clear]`,actionTest:`测试连接`,actionAdoptEnv:`采用系统代理 {{value}}(来自 {{source}})`,probeProbing:`测试中…`,probeOk:`代理可达 — {{latency}}ms({{target}})`,probeFailedProxy:`代理不可达 — {{reason}}`,probeFailedTarget:`代理正常,但目标不可达 — {{reason}}`,probeNoModel:`请先配置模型,再测试连接`,effectiveMismatch:`当前生效:{{effective}} — 需重启会话使变更生效`,effectiveNotApplied:`尚未生效 — 需重启会话使变更生效`,envDetectedToast:`检测到 {{source}}={{value}} — 运行 /proxy 可一键采用`},crashGap:{toastTitle:`检测到上次异常退出丢失了部分对话`,toastBody:`上次进程异常终止(如内存耗尽或被强制结束)时,约 {{lostTurns}} 个回合的消息未能保存,已无法恢复。较早的对话已完整保留。`},signalBar:{tabHint:`Tab 切换`,clipboard:`剪贴板`,clipboardFailed:`复制受限 — 按住 {{modifier}} 拖拽用终端原生复制`},clipboard:{paneTitle:`剪贴板`,viewerTitle:`剪贴板内容`,charsLabel:`{{count}} 个字符`,empty:`暂无复制内容`,openHint:`查看`},mouse:{toggleTitle:`鼠标`,enabledBody:`已开启 — 拖拽即选择并复制;按住 {{modifier}} 可用终端原生选择;滚轮可滚动`,disabledBody:`已关闭 — 恢复终端原生选择,滚轮失效(可用 Alt+↑/↓ 回看)`}}}};function r(r){return e.isInitialized?e.changeLanguage(r):e.use(t).init({lng:r,fallbackLng:`en`,resources:n,defaultNS:`translation`,interpolation:{escapeValue:!1},returnNull:!1,returnEmptyString:!1}),e}r(`en`);const i=e.t.bind(e);function a(){let e=process.env.LC_ALL||process.env.LC_MESSAGES||process.env.LANG||``;return/zh/i.test(e)?`zh`:`en`}export{i,e as n,r,a as t};
76
+ //# sourceMappingURL=i18n-CznO8p1Y.js.map