mocode-ai 0.6.7 → 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/README.zh-CN.md +5 -0
- package/dist/agent/core.js +5 -5
- package/dist/agent/index.js +10 -8
- package/dist/agent/spawn.js +1 -5
- package/dist/commands/config.js +9 -7
- package/dist/config/index.js +49 -41
- package/dist/context/budget.js +2 -3
- package/dist/i18n/index.js +450 -0
- package/dist/index.js +8 -4
- package/dist/llm/index.js +19 -16
- package/dist/mcp/client.js +389 -0
- package/dist/mcp/config.js +128 -0
- package/dist/mcp/index.js +105 -0
- package/dist/mcp/registry.js +5 -0
- package/dist/mcp/types.js +1 -0
- package/dist/permissions/index.js +16 -12
- package/dist/pet/state.js +2 -1
- package/dist/repl/index.js +210 -102
- package/dist/rollback/index.js +311 -119
- package/dist/session/persist.js +11 -5
- package/dist/tools/builtins/ask-human.js +4 -3
- package/dist/tools/builtins/run-command.js +6 -5
- package/dist/tools/builtins/task.js +5 -4
- package/dist/tools/registry.js +58 -22
- package/dist/tools/result.js +7 -0
- package/dist/ui/intervention.js +12 -7
- package/dist/ui/layout.js +4 -3
- package/dist/ui/prompt.js +83 -28
- package/dist/ui/render.js +15 -12
- package/package.json +1 -1
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
const zhCN = {
|
|
2
|
+
'common.none': '(无)',
|
|
3
|
+
'common.current': '当前',
|
|
4
|
+
'commands.help': '查看所有命令',
|
|
5
|
+
'commands.exit': '退出 mocode(同 /quit)',
|
|
6
|
+
'commands.clear': '清空历史(保留系统提示)',
|
|
7
|
+
'commands.context': '显示上下文用量条',
|
|
8
|
+
'commands.skills': '列出已发现的 skill',
|
|
9
|
+
'commands.compact': '压缩历史(可带焦点 /compact …)',
|
|
10
|
+
'commands.session': '会话恢复与回滚',
|
|
11
|
+
'commands.sessionResume': '续接最近 10 个已保存会话(快速)',
|
|
12
|
+
'commands.sessionBrowse': '浏览全部已保存会话',
|
|
13
|
+
'commands.sessionRollback': '菜单选轮次回滚(↑↓·Enter)',
|
|
14
|
+
'commands.memory': '记忆库、开关与反思',
|
|
15
|
+
'commands.memoryOverview': '条目计数与近期索引',
|
|
16
|
+
'commands.memoryToggle': '切换记忆子系统开关',
|
|
17
|
+
'commands.memoryOn': '开启记忆子系统',
|
|
18
|
+
'commands.memoryOff': '关闭记忆子系统',
|
|
19
|
+
'commands.memoryStatus': '查看当前开关与原理',
|
|
20
|
+
'commands.memoryReflect': '手动触发后台记忆反思',
|
|
21
|
+
'commands.memoryInit': '扫描项目生成 MOCODE.md 项目记忆',
|
|
22
|
+
'commands.skill': '项目专属 Skill 管理',
|
|
23
|
+
'commands.toggle': '切换开关',
|
|
24
|
+
'commands.skillOn': '开启项目 Skill',
|
|
25
|
+
'commands.skillOff': '关闭项目 Skill',
|
|
26
|
+
'commands.skillView': '查看当前内容',
|
|
27
|
+
'commands.skillInit': '扫描项目生成或优化 Skill',
|
|
28
|
+
'commands.snapshot': '项目快照管理',
|
|
29
|
+
'commands.snapshotToggle': '切换快照开关',
|
|
30
|
+
'commands.snapshotOn': '开启项目快照',
|
|
31
|
+
'commands.snapshotOff': '关闭项目快照',
|
|
32
|
+
'commands.snapshotStatus': '查看当前状态',
|
|
33
|
+
'commands.snapshotRefresh': '重新扫描并生成快照摘要',
|
|
34
|
+
'commands.theme': '切换颜色主题(↑↓·Enter)',
|
|
35
|
+
'commands.model': '模型配置与预设管理',
|
|
36
|
+
'commands.modelConfigure': '配置新模型(向导)',
|
|
37
|
+
'commands.modelSwitch': '切换已配置预设',
|
|
38
|
+
'commands.modelList': '列出已配置模型',
|
|
39
|
+
'commands.modelShow': '显示当前模型配置',
|
|
40
|
+
'commands.modelUse': '按名称应用预设',
|
|
41
|
+
'commands.modelDelete': '删除指定预设',
|
|
42
|
+
'commands.mode': '切换 Agent 工作模式',
|
|
43
|
+
'commands.modePlan': '只读探查并产出计划',
|
|
44
|
+
'commands.modeAuto': '全工具自动执行',
|
|
45
|
+
'commands.pet': '桌宠控制',
|
|
46
|
+
'commands.petToggle': '显示或隐藏桌宠',
|
|
47
|
+
'commands.petSkin': '选择桌宠皮肤',
|
|
48
|
+
'commands.petQuit': '完全关闭桌宠进程',
|
|
49
|
+
'commands.image': '管理下一条消息的图片',
|
|
50
|
+
'commands.imageAttach': '附加本地图片',
|
|
51
|
+
'commands.imageList': '列出待发送图片',
|
|
52
|
+
'commands.imageClear': '清空待发送图片',
|
|
53
|
+
'commands.language': '切换界面与回复语言',
|
|
54
|
+
'commands.languageZh': '切换到中文',
|
|
55
|
+
'commands.languageEn': 'Switch to English',
|
|
56
|
+
'help.title': '可用斜杠命令',
|
|
57
|
+
'help.hint': '(› 表示可进入子菜单;→ 后为实际执行命令)',
|
|
58
|
+
'language.current': '当前语言:{language}',
|
|
59
|
+
'language.changed': '语言已切换为中文。',
|
|
60
|
+
'language.usage': '用法:/language zh-CN|en',
|
|
61
|
+
'language.invalid': '不支持的语言“{value}”。支持:zh-CN、en。',
|
|
62
|
+
'language.shellOverride': 'shell 环境变量 MOCODE_LANGUAGE 已设置,文件值下次启动会被覆盖。',
|
|
63
|
+
'language.zh': '简体中文',
|
|
64
|
+
'language.en': 'English',
|
|
65
|
+
'running.compact': '压缩',
|
|
66
|
+
'running.compacting': '压缩中…',
|
|
67
|
+
'running.resume': '续接',
|
|
68
|
+
'running.chooseSession': '选择会话…',
|
|
69
|
+
'running.rollback': '回滚',
|
|
70
|
+
'running.chooseTurn': '选择轮次…',
|
|
71
|
+
'running.init': '初始化',
|
|
72
|
+
'running.generateMemory': '生成 MOCODE.md…',
|
|
73
|
+
'running.snapshot': '刷新快照',
|
|
74
|
+
'running.scanning': '扫描项目文件中…',
|
|
75
|
+
'running.plan': '切 plan',
|
|
76
|
+
'running.auto': '切 auto',
|
|
77
|
+
'running.clear': '清空',
|
|
78
|
+
'running.theme': '切主题',
|
|
79
|
+
'running.chooseTheme': '选择主题…',
|
|
80
|
+
'running.model': '配模型',
|
|
81
|
+
'running.configuring': '配置中…',
|
|
82
|
+
'running.pet': '桌宠',
|
|
83
|
+
'running.processing': '处理中…',
|
|
84
|
+
'running.memory': '切记忆开关',
|
|
85
|
+
'running.switching': '切换中…',
|
|
86
|
+
'running.memoryStatus': '查记忆状态',
|
|
87
|
+
'running.skill': '项目 Skill',
|
|
88
|
+
'running.language': '切语言',
|
|
89
|
+
'running.chooseLanguage': '选择语言…',
|
|
90
|
+
'prompt.lines': '{count} 行',
|
|
91
|
+
'prompt.chars': '{count} 字符',
|
|
92
|
+
'prompt.chooseRollback': '↑↓ 选择 · Enter 回滚到该轮 · Esc 取消',
|
|
93
|
+
'prompt.chooseResume': '↑↓ 选择 · Enter 续接 · Esc 取消',
|
|
94
|
+
'prompt.recent': '↑↓ 选择 · Enter 续接 · a 仅最近{count} · Esc 取消',
|
|
95
|
+
'prompt.all': '↑↓ 选择 · Enter 续接 · a 全部({count}) · Esc 取消',
|
|
96
|
+
'prompt.chooseSwitch': '↑↓ 选择 · Enter 切换 · Esc 取消',
|
|
97
|
+
'prompt.chooseConfirm': '↑↓ 选择 · Enter 确认 · 数字键直选 · Esc 取消',
|
|
98
|
+
'prompt.submit': 'Enter 提交 · Esc {escape} · Ctrl+C 取消',
|
|
99
|
+
'prompt.back': '返回选项',
|
|
100
|
+
'prompt.cancel': '取消',
|
|
101
|
+
'prompt.keepFiles': '↑↓ 选择 · Enter 确认 · Esc 保留文件',
|
|
102
|
+
'prompt.revertFiles': '撤销文件改动{detail}',
|
|
103
|
+
'prompt.revertDetail': '({count} 个文件恢复到回滚前)',
|
|
104
|
+
'prompt.messagesOnly': '只撤销消息,保留文件改动',
|
|
105
|
+
'intervention.custom': '其他(自定义输入)',
|
|
106
|
+
'intervention.defaultChoice': '自动选择默认项',
|
|
107
|
+
'intervention.emptyInput': '自动返回空输入',
|
|
108
|
+
'intervention.nonInteractive': '[介入] {title}(非交互环境,{kind})',
|
|
109
|
+
'repl.idle': '空闲',
|
|
110
|
+
'repl.loadFailed': '(加载失败)',
|
|
111
|
+
'repl.resumed': '(已续接会话 {id})',
|
|
112
|
+
'repl.noSessions': '(没有已保存的会话)',
|
|
113
|
+
'repl.noValue': '(无)',
|
|
114
|
+
'repl.historyCleared': '(历史已清空,保留系统提示)',
|
|
115
|
+
'repl.planAlready': '(已在 plan 模式)',
|
|
116
|
+
'repl.planChanged': '(已切到 plan 模式:只读探查 + 产出计划,审批后切 auto 执行。/auto 或 Shift+Tab 切回)',
|
|
117
|
+
'repl.autoAlready': '(已在 auto 模式)',
|
|
118
|
+
'repl.autoChanged': '(已切回 auto 模式:全工具执行)',
|
|
119
|
+
'repl.noImages': '(无待发送图片)',
|
|
120
|
+
'repl.imagesCleared': '(已清空待发送图片)',
|
|
121
|
+
'repl.imageUsage': '用法:/image <path>',
|
|
122
|
+
'repl.themeList': '可用主题:',
|
|
123
|
+
'repl.themeCurrent': '(当前:{theme};用 /theme <名称> 切换)',
|
|
124
|
+
'repl.themeChanged': '(已切换主题 {theme})',
|
|
125
|
+
'theme.default': '16 色原版(深底)',
|
|
126
|
+
'theme.light': '浅底终端',
|
|
127
|
+
'theme.solarized': 'Solarized 强调色',
|
|
128
|
+
'theme.gruvbox': 'Gruvbox 暖色',
|
|
129
|
+
'theme.nord': 'Nord 冷色',
|
|
130
|
+
'theme.orange': '南瓜橙(暖)',
|
|
131
|
+
'theme.rose': '玫红(暖紫)',
|
|
132
|
+
'theme.emerald': '翡翠绿(冷)',
|
|
133
|
+
'theme.amber': '琥珀金黄(暖)',
|
|
134
|
+
'theme.lavender': '薰衣草淡紫(冷)',
|
|
135
|
+
'theme.sunset': '日落珊瑚红(暖)',
|
|
136
|
+
'config.title': 'mocode 配置向导 — 写入 {path}(Ctrl+C 取消)',
|
|
137
|
+
'config.example': '(如 https://open.bigmodel.cn/api/v3)',
|
|
138
|
+
'config.keySet': ' [已设置,回车保留]',
|
|
139
|
+
'config.modelDefault': '(回车默认 gpt-4o-mini)',
|
|
140
|
+
'config.required': '\n[config] {key} 不能为空,已取消。',
|
|
141
|
+
'config.done': '\n已写入 {path}。现在运行 `mocode` 即可启动(任意目录、任意终端)。',
|
|
142
|
+
'cli.sandboxPath': '[cli] --sandbox-root 需要一个路径参数',
|
|
143
|
+
'cli.noSessions': '(没有已保存的会话)',
|
|
144
|
+
'cli.noValue': '(无)',
|
|
145
|
+
'cli.sessionMissing': '[session] 找不到会话 {id}(用 --resume 查看列表)',
|
|
146
|
+
'banner.model': '模型',
|
|
147
|
+
'banner.directory': '目录',
|
|
148
|
+
'banner.memory': '记忆',
|
|
149
|
+
'banner.enabled': '开启',
|
|
150
|
+
'banner.disabled': '关闭',
|
|
151
|
+
'status.modeSwitch': 'Shift+Tab 切换',
|
|
152
|
+
'status.history': '历史 ↑{count}(PgDn 回底)',
|
|
153
|
+
'status.measured': '实测',
|
|
154
|
+
'status.estimated': '估算',
|
|
155
|
+
'status.messages': '{count} 条消息',
|
|
156
|
+
'agent.sending': '发送中… (Esc / Ctrl+C 撤回)',
|
|
157
|
+
'agent.thinking': '思考中',
|
|
158
|
+
'agent.generating': '生成 {tool}',
|
|
159
|
+
'agent.executing': '执行 {tool}',
|
|
160
|
+
'agent.noReply': '(无回复)',
|
|
161
|
+
'agent.maxSteps': '达到最大步数({count}),本轮停止。',
|
|
162
|
+
'agent.aborted': '(已中断)',
|
|
163
|
+
'agent.workedFor': '耗时 {elapsed}',
|
|
164
|
+
'toolSummary.lines': '{count} 行',
|
|
165
|
+
'toolSummary.files': '{count} 个文件',
|
|
166
|
+
'toolSummary.matches': '{count} 处匹配',
|
|
167
|
+
'toolSummary.emptyFile': '(空文件)',
|
|
168
|
+
'toolSummary.noMatches': '(无匹配)',
|
|
169
|
+
'toolSummary.noOutput': '(无输出)',
|
|
170
|
+
'toolError.unknown': '错误:未知工具 "{name}"',
|
|
171
|
+
'toolError.invalidJson': '错误:工具 {name} 的 arguments 不是合法 JSON: {arguments}',
|
|
172
|
+
'toolError.execution': '错误:工具 {name} 执行失败: {message}',
|
|
173
|
+
'command.outputTruncated': '...(输出已截断 {count} 字符,保留开头与结尾)...',
|
|
174
|
+
'command.interrupted': '[已中断]',
|
|
175
|
+
'command.executionFailed': '执行失败: {message}',
|
|
176
|
+
'command.exitCode': '[退出码 {code}]',
|
|
177
|
+
'command.timedOut': '[超时,已终止]',
|
|
178
|
+
'repl.errorLabel': '[错误]',
|
|
179
|
+
'repl.visionUnsupported': '当前模型 {model} 不支持视觉输入。',
|
|
180
|
+
'repl.originalError': '原始:{message}',
|
|
181
|
+
'repl.visionHint': '提示:运行 /model 切换到支持视觉的模型(如 gpt-4o / claude-3.5-sonnet / gemini-1.5-pro)。',
|
|
182
|
+
'permission.path': '路径: {value}',
|
|
183
|
+
'permission.command': '命令: {value}',
|
|
184
|
+
'permission.task': '任务: {value}',
|
|
185
|
+
'permission.noArgs': '(无参数)',
|
|
186
|
+
'permission.dangerTitle': '⚠ 高风险操作: {tool}',
|
|
187
|
+
'permission.confirmTitle': '确认执行: {tool}',
|
|
188
|
+
'permission.dangerWarning': '⚠ 此操作可能产生不可逆副作用,请谨慎确认。',
|
|
189
|
+
'permission.confirmExecute': '确认执行',
|
|
190
|
+
'permission.allowForever': '以后不再询问此工具',
|
|
191
|
+
'permission.deny': '拒绝',
|
|
192
|
+
'permission.allow': '允许',
|
|
193
|
+
'permission.allowSession': '本次会话始终允许此工具',
|
|
194
|
+
'askHuman.cancelled': '用户取消了选择。请考虑是否有不依赖用户输入的替代方案,或换个角度重新提问。',
|
|
195
|
+
'askHuman.submitted': '用户回答:{value}',
|
|
196
|
+
'askHuman.selected': '用户选择:{value}',
|
|
197
|
+
'task.missingPrompt': '错误:缺少 prompt(子任务指令)。',
|
|
198
|
+
'task.interrupted': '子 agent 被中断,未完成。',
|
|
199
|
+
'task.noSummary': '子 agent 完成但未返回文本摘要(可能只调了工具或达到步数上限)。',
|
|
200
|
+
'task.summaryTruncated': '…(子 agent 摘要已截断 {count} 字符)',
|
|
201
|
+
'plan.ready': '计划已就绪',
|
|
202
|
+
'plan.approvalDetail': '切换到 auto 模式按上述计划执行?(plan 模式只读探查,执行需切 auto)',
|
|
203
|
+
'plan.execute': '切 auto 执行',
|
|
204
|
+
'plan.refine': '留 plan 细化',
|
|
205
|
+
'plan.running': '执行',
|
|
206
|
+
'plan.executing': '按计划执行…',
|
|
207
|
+
'plan.executePrompt': '请按上述计划执行。',
|
|
208
|
+
'assistant.languageInstruction': 'Reply to the user in Chinese.',
|
|
209
|
+
};
|
|
210
|
+
const en = {
|
|
211
|
+
'common.none': '(none)',
|
|
212
|
+
'common.current': 'Current',
|
|
213
|
+
'commands.help': 'Show all commands',
|
|
214
|
+
'commands.exit': 'Exit mocode (same as /quit)',
|
|
215
|
+
'commands.clear': 'Clear history (keep system prompt)',
|
|
216
|
+
'commands.context': 'Show context usage',
|
|
217
|
+
'commands.skills': 'List discovered skills',
|
|
218
|
+
'commands.compact': 'Compact history (optional focus: /compact …)',
|
|
219
|
+
'commands.session': 'Resume sessions and roll back turns',
|
|
220
|
+
'commands.sessionResume': 'Resume one of the 10 latest saved sessions',
|
|
221
|
+
'commands.sessionBrowse': 'Browse all saved sessions',
|
|
222
|
+
'commands.sessionRollback': 'Choose a turn to roll back (↑↓·Enter)',
|
|
223
|
+
'commands.memory': 'Memory store, controls, and reflection',
|
|
224
|
+
'commands.memoryOverview': 'Show counts and recent entries',
|
|
225
|
+
'commands.memoryToggle': 'Toggle the memory subsystem',
|
|
226
|
+
'commands.memoryOn': 'Enable the memory subsystem',
|
|
227
|
+
'commands.memoryOff': 'Disable the memory subsystem',
|
|
228
|
+
'commands.memoryStatus': 'Show current state and behavior',
|
|
229
|
+
'commands.memoryReflect': 'Run background memory reflection',
|
|
230
|
+
'commands.memoryInit': 'Scan project and generate MOCODE.md',
|
|
231
|
+
'commands.skill': 'Manage the project-specific Skill',
|
|
232
|
+
'commands.toggle': 'Toggle the feature',
|
|
233
|
+
'commands.skillOn': 'Enable the project Skill',
|
|
234
|
+
'commands.skillOff': 'Disable the project Skill',
|
|
235
|
+
'commands.skillView': 'View current content',
|
|
236
|
+
'commands.skillInit': 'Generate or improve the project Skill',
|
|
237
|
+
'commands.snapshot': 'Manage project snapshots',
|
|
238
|
+
'commands.snapshotToggle': 'Toggle project snapshots',
|
|
239
|
+
'commands.snapshotOn': 'Enable project snapshots',
|
|
240
|
+
'commands.snapshotOff': 'Disable project snapshots',
|
|
241
|
+
'commands.snapshotStatus': 'Show current status',
|
|
242
|
+
'commands.snapshotRefresh': 'Rescan and regenerate the snapshot summary',
|
|
243
|
+
'commands.theme': 'Switch color theme (↑↓·Enter)',
|
|
244
|
+
'commands.model': 'Model configuration and presets',
|
|
245
|
+
'commands.modelConfigure': 'Configure a new model (wizard)',
|
|
246
|
+
'commands.modelSwitch': 'Switch configured preset',
|
|
247
|
+
'commands.modelList': 'List configured models',
|
|
248
|
+
'commands.modelShow': 'Show current model configuration',
|
|
249
|
+
'commands.modelUse': 'Apply a preset by name',
|
|
250
|
+
'commands.modelDelete': 'Delete a preset',
|
|
251
|
+
'commands.mode': 'Switch Agent mode',
|
|
252
|
+
'commands.modePlan': 'Read-only research and planning',
|
|
253
|
+
'commands.modeAuto': 'Execute automatically with all tools',
|
|
254
|
+
'commands.pet': 'Desktop pet controls',
|
|
255
|
+
'commands.petToggle': 'Show or hide the desktop pet',
|
|
256
|
+
'commands.petSkin': 'Choose a pet skin',
|
|
257
|
+
'commands.petQuit': 'Terminate the desktop pet process',
|
|
258
|
+
'commands.image': 'Manage images for the next message',
|
|
259
|
+
'commands.imageAttach': 'Attach a local image',
|
|
260
|
+
'commands.imageList': 'List pending images',
|
|
261
|
+
'commands.imageClear': 'Clear pending images',
|
|
262
|
+
'commands.language': 'Switch interface and reply language',
|
|
263
|
+
'commands.languageZh': '切换到中文',
|
|
264
|
+
'commands.languageEn': 'Switch to English',
|
|
265
|
+
'help.title': 'Available slash commands',
|
|
266
|
+
'help.hint': '(› opens a submenu; → shows the command that will run)',
|
|
267
|
+
'language.current': 'Current language: {language}',
|
|
268
|
+
'language.changed': 'Language switched to English.',
|
|
269
|
+
'language.usage': 'Usage: /language zh-CN|en',
|
|
270
|
+
'language.invalid': 'Unsupported language “{value}”. Supported: zh-CN, en.',
|
|
271
|
+
'language.shellOverride': 'MOCODE_LANGUAGE is set in the shell; it will override the saved value on next launch.',
|
|
272
|
+
'language.zh': '简体中文',
|
|
273
|
+
'language.en': 'English',
|
|
274
|
+
'running.compact': 'Compact',
|
|
275
|
+
'running.compacting': 'Compacting…',
|
|
276
|
+
'running.resume': 'Resume',
|
|
277
|
+
'running.chooseSession': 'Choose a session…',
|
|
278
|
+
'running.rollback': 'Rollback',
|
|
279
|
+
'running.chooseTurn': 'Choose a turn…',
|
|
280
|
+
'running.init': 'Initialize',
|
|
281
|
+
'running.generateMemory': 'Generating MOCODE.md…',
|
|
282
|
+
'running.snapshot': 'Refresh snapshot',
|
|
283
|
+
'running.scanning': 'Scanning project files…',
|
|
284
|
+
'running.plan': 'Plan mode',
|
|
285
|
+
'running.auto': 'Auto mode',
|
|
286
|
+
'running.clear': 'Clear',
|
|
287
|
+
'running.theme': 'Theme',
|
|
288
|
+
'running.chooseTheme': 'Choose a theme…',
|
|
289
|
+
'running.model': 'Model',
|
|
290
|
+
'running.configuring': 'Configuring…',
|
|
291
|
+
'running.pet': 'Pet',
|
|
292
|
+
'running.processing': 'Processing…',
|
|
293
|
+
'running.memory': 'Memory',
|
|
294
|
+
'running.switching': 'Switching…',
|
|
295
|
+
'running.memoryStatus': 'Memory status',
|
|
296
|
+
'running.skill': 'Project Skill',
|
|
297
|
+
'running.language': 'Language',
|
|
298
|
+
'running.chooseLanguage': 'Choose a language…',
|
|
299
|
+
'prompt.lines': '{count} lines',
|
|
300
|
+
'prompt.chars': '{count} characters',
|
|
301
|
+
'prompt.chooseRollback': '↑↓ Select · Enter Roll back to turn · Esc Cancel',
|
|
302
|
+
'prompt.chooseResume': '↑↓ Select · Enter Resume · Esc Cancel',
|
|
303
|
+
'prompt.recent': '↑↓ Select · Enter Resume · a Latest {count} · Esc Cancel',
|
|
304
|
+
'prompt.all': '↑↓ Select · Enter Resume · a All ({count}) · Esc Cancel',
|
|
305
|
+
'prompt.chooseSwitch': '↑↓ Select · Enter Switch · Esc Cancel',
|
|
306
|
+
'prompt.chooseConfirm': '↑↓ Select · Enter Confirm · Number Quick select · Esc Cancel',
|
|
307
|
+
'prompt.submit': 'Enter Submit · Esc {escape} · Ctrl+C Cancel',
|
|
308
|
+
'prompt.back': 'Back to choices',
|
|
309
|
+
'prompt.cancel': 'Cancel',
|
|
310
|
+
'prompt.keepFiles': '↑↓ Select · Enter Confirm · Esc Keep files',
|
|
311
|
+
'prompt.revertFiles': 'Revert file changes{detail}',
|
|
312
|
+
'prompt.revertDetail': ' ({count} files restored to before the rollback)',
|
|
313
|
+
'prompt.messagesOnly': 'Roll back messages only; keep file changes',
|
|
314
|
+
'intervention.custom': 'Other (custom input)',
|
|
315
|
+
'intervention.defaultChoice': 'automatically selected the default',
|
|
316
|
+
'intervention.emptyInput': 'automatically returned empty input',
|
|
317
|
+
'intervention.nonInteractive': '[intervention] {title} (non-interactive; {kind})',
|
|
318
|
+
'repl.idle': 'Idle',
|
|
319
|
+
'repl.loadFailed': '(load failed)',
|
|
320
|
+
'repl.resumed': '(resumed session {id})',
|
|
321
|
+
'repl.noSessions': '(no saved sessions)',
|
|
322
|
+
'repl.noValue': '(none)',
|
|
323
|
+
'repl.historyCleared': '(history cleared; system prompt kept)',
|
|
324
|
+
'repl.planAlready': '(already in plan mode)',
|
|
325
|
+
'repl.planChanged': '(switched to plan mode: read-only research and planning; approval returns to auto. Use /auto or Shift+Tab to switch back)',
|
|
326
|
+
'repl.autoAlready': '(already in auto mode)',
|
|
327
|
+
'repl.autoChanged': '(switched to auto mode: all tools enabled)',
|
|
328
|
+
'repl.noImages': '(no pending images)',
|
|
329
|
+
'repl.imagesCleared': '(pending images cleared)',
|
|
330
|
+
'repl.imageUsage': 'Usage: /image <path>',
|
|
331
|
+
'repl.themeList': 'Available themes:',
|
|
332
|
+
'repl.themeCurrent': '(current: {theme}; use /theme <name> to switch)',
|
|
333
|
+
'repl.themeChanged': '(switched theme to {theme})',
|
|
334
|
+
'theme.default': 'Original 16-color theme (dark)',
|
|
335
|
+
'theme.light': 'Light terminal',
|
|
336
|
+
'theme.solarized': 'Solarized accents',
|
|
337
|
+
'theme.gruvbox': 'Warm Gruvbox colors',
|
|
338
|
+
'theme.nord': 'Cool Nord colors',
|
|
339
|
+
'theme.orange': 'Warm pumpkin orange',
|
|
340
|
+
'theme.rose': 'Warm rose purple',
|
|
341
|
+
'theme.emerald': 'Cool emerald green',
|
|
342
|
+
'theme.amber': 'Warm amber gold',
|
|
343
|
+
'theme.lavender': 'Cool pale lavender',
|
|
344
|
+
'theme.sunset': 'Warm sunset coral',
|
|
345
|
+
'config.title': 'mocode configuration wizard — writing {path} (Ctrl+C to cancel)',
|
|
346
|
+
'config.example': ' (for example, https://open.bigmodel.cn/api/v3)',
|
|
347
|
+
'config.keySet': ' [set; press Enter to keep]',
|
|
348
|
+
'config.modelDefault': ' (press Enter for gpt-4o-mini)',
|
|
349
|
+
'config.required': '\n[config] {key} is required; cancelled.',
|
|
350
|
+
'config.done': '\nSaved to {path}. Run `mocode` to start from any directory or terminal.',
|
|
351
|
+
'cli.sandboxPath': '[cli] --sandbox-root requires a path',
|
|
352
|
+
'cli.noSessions': '(no saved sessions)',
|
|
353
|
+
'cli.noValue': '(none)',
|
|
354
|
+
'cli.sessionMissing': '[session] Session {id} was not found (use --resume to list sessions)',
|
|
355
|
+
'banner.model': 'Model',
|
|
356
|
+
'banner.directory': 'Directory',
|
|
357
|
+
'banner.memory': 'Memory',
|
|
358
|
+
'banner.enabled': 'Enabled',
|
|
359
|
+
'banner.disabled': 'Disabled',
|
|
360
|
+
'status.modeSwitch': 'Shift+Tab Switch',
|
|
361
|
+
'status.history': 'History ↑{count} (PgDn to bottom)',
|
|
362
|
+
'status.measured': 'measured',
|
|
363
|
+
'status.estimated': 'estimated',
|
|
364
|
+
'status.messages': '{count} messages',
|
|
365
|
+
'agent.sending': 'Sending… (Esc / Ctrl+C to recall)',
|
|
366
|
+
'agent.thinking': 'Thinking',
|
|
367
|
+
'agent.generating': 'Generating {tool}',
|
|
368
|
+
'agent.executing': 'Running {tool}',
|
|
369
|
+
'agent.noReply': '(no reply)',
|
|
370
|
+
'agent.maxSteps': 'Maximum steps reached ({count}); this turn has stopped.',
|
|
371
|
+
'agent.aborted': '(aborted)',
|
|
372
|
+
'agent.workedFor': 'Worked for {elapsed}',
|
|
373
|
+
'toolSummary.lines': '{count} lines',
|
|
374
|
+
'toolSummary.files': '{count} files',
|
|
375
|
+
'toolSummary.matches': '{count} matches',
|
|
376
|
+
'toolSummary.emptyFile': '(empty file)',
|
|
377
|
+
'toolSummary.noMatches': '(no matches)',
|
|
378
|
+
'toolSummary.noOutput': '(no output)',
|
|
379
|
+
'toolError.unknown': 'Error: unknown tool "{name}"',
|
|
380
|
+
'toolError.invalidJson': 'Error: arguments for tool {name} are not valid JSON: {arguments}',
|
|
381
|
+
'toolError.execution': 'Error: tool {name} failed: {message}',
|
|
382
|
+
'command.outputTruncated': '...(output truncated by {count} characters; keeping the beginning and end)...',
|
|
383
|
+
'command.interrupted': '[interrupted]',
|
|
384
|
+
'command.executionFailed': 'Execution failed: {message}',
|
|
385
|
+
'command.exitCode': '[exit code {code}]',
|
|
386
|
+
'command.timedOut': '[timed out and terminated]',
|
|
387
|
+
'repl.errorLabel': '[Error]',
|
|
388
|
+
'repl.visionUnsupported': 'The current model, {model}, does not support vision input.',
|
|
389
|
+
'repl.originalError': 'Original: {message}',
|
|
390
|
+
'repl.visionHint': 'Tip: run /model and switch to a vision-capable model (for example, gpt-4o, claude-3.5-sonnet, or gemini-1.5-pro).',
|
|
391
|
+
'permission.path': 'Path: {value}',
|
|
392
|
+
'permission.command': 'Command: {value}',
|
|
393
|
+
'permission.task': 'Task: {value}',
|
|
394
|
+
'permission.noArgs': '(no arguments)',
|
|
395
|
+
'permission.dangerTitle': '⚠ High-risk operation: {tool}',
|
|
396
|
+
'permission.confirmTitle': 'Confirm execution: {tool}',
|
|
397
|
+
'permission.dangerWarning': '⚠ This operation may have irreversible side effects. Confirm carefully.',
|
|
398
|
+
'permission.confirmExecute': 'Confirm and run',
|
|
399
|
+
'permission.allowForever': 'Always allow this tool',
|
|
400
|
+
'permission.deny': 'Deny',
|
|
401
|
+
'permission.allow': 'Allow',
|
|
402
|
+
'permission.allowSession': 'Always allow this tool for this session',
|
|
403
|
+
'askHuman.cancelled': 'The user cancelled the choice. Consider an alternative that does not require user input, or ask from a different angle.',
|
|
404
|
+
'askHuman.submitted': 'User response: {value}',
|
|
405
|
+
'askHuman.selected': 'User selected: {value}',
|
|
406
|
+
'task.missingPrompt': 'Error: missing prompt (sub-task instruction).',
|
|
407
|
+
'task.interrupted': 'The sub-agent was interrupted before completion.',
|
|
408
|
+
'task.noSummary': 'The sub-agent completed without a text summary (it may only have used tools or reached its step limit).',
|
|
409
|
+
'task.summaryTruncated': '…(sub-agent summary truncated by {count} characters)',
|
|
410
|
+
'plan.ready': 'Plan ready',
|
|
411
|
+
'plan.approvalDetail': 'Switch to auto mode and execute the plan above? (Plan mode is read-only; execution requires auto mode.)',
|
|
412
|
+
'plan.execute': 'Switch to auto and execute',
|
|
413
|
+
'plan.refine': 'Stay in plan and refine',
|
|
414
|
+
'plan.running': 'Execute',
|
|
415
|
+
'plan.executing': 'Executing the plan…',
|
|
416
|
+
'plan.executePrompt': 'Execute the plan above.',
|
|
417
|
+
'assistant.languageInstruction': 'Reply to the user in English.',
|
|
418
|
+
};
|
|
419
|
+
const resources = {
|
|
420
|
+
'zh-CN': zhCN,
|
|
421
|
+
en,
|
|
422
|
+
};
|
|
423
|
+
let currentLanguage = 'zh-CN';
|
|
424
|
+
export function normalizeLanguage(value) {
|
|
425
|
+
const normalized = value?.trim().toLowerCase().replace('_', '-');
|
|
426
|
+
if (!normalized)
|
|
427
|
+
return null;
|
|
428
|
+
if (normalized === 'zh' || normalized.startsWith('zh-'))
|
|
429
|
+
return 'zh-CN';
|
|
430
|
+
if (normalized === 'en' || normalized.startsWith('en-'))
|
|
431
|
+
return 'en';
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
export function detectLanguage(preferred) {
|
|
435
|
+
const explicit = normalizeLanguage(preferred);
|
|
436
|
+
if (explicit)
|
|
437
|
+
return explicit;
|
|
438
|
+
const system = normalizeLanguage(process.env.LC_ALL || process.env.LC_MESSAGES || process.env.LANG || Intl.DateTimeFormat().resolvedOptions().locale);
|
|
439
|
+
return system ?? 'zh-CN';
|
|
440
|
+
}
|
|
441
|
+
export function setLanguage(language) {
|
|
442
|
+
currentLanguage = language;
|
|
443
|
+
}
|
|
444
|
+
export function getLanguage() {
|
|
445
|
+
return currentLanguage;
|
|
446
|
+
}
|
|
447
|
+
export function t(key, params = {}) {
|
|
448
|
+
const template = resources[currentLanguage][key] ?? zhCN[key];
|
|
449
|
+
return template.replace(/\{(\w+)\}/g, (match, name) => Object.prototype.hasOwnProperty.call(params, name) ? String(params[name]) : match);
|
|
450
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { exitAltScreen } from './ui/layout.js';
|
|
2
2
|
import { checkAndMaybeUpdate } from './updater/index.js';
|
|
3
|
+
import { readConfigFile } from './config/file.js';
|
|
4
|
+
import { detectLanguage, setLanguage, t } from './i18n/index.js';
|
|
3
5
|
// 终端恢复兜底:任一退出 / 中断 / 未捕获异常路径都要恢复 alt screen,避免残留备用屏 + 滚动区域。
|
|
4
6
|
// exitAltScreen 幂等(未激活时空操作),故全局注册安全——进 alt screen 前的路径(如 --resume 列表、缺环境变量、`mocode config`)调用它无副作用。
|
|
5
7
|
// 仅 layout 是叶子(不依赖 config),故静态导入安全;repl / session 依赖 config(模块加载触发 loadEnvFiles + config 单例初始化),
|
|
@@ -36,6 +38,8 @@ process.on('unhandledRejection', (e) => {
|
|
|
36
38
|
* 显式 process.exit(0)——OpenAI 客户端的 keep-alive 会卡住事件循环。
|
|
37
39
|
*/
|
|
38
40
|
async function main() {
|
|
41
|
+
const savedLanguage = readConfigFile().MOCODE_LANGUAGE;
|
|
42
|
+
setLanguage(detectLanguage(process.env.MOCODE_LANGUAGE ?? savedLanguage));
|
|
39
43
|
const args = process.argv.slice(2);
|
|
40
44
|
// --sandbox-root <path>:覆盖沙箱根(文件操作边界)。缺值或以 -- 开头报错退出。
|
|
41
45
|
const sr = args.indexOf('--sandbox-root');
|
|
@@ -43,7 +47,7 @@ async function main() {
|
|
|
43
47
|
if (sr !== -1) {
|
|
44
48
|
sandboxRootOverride = args[sr + 1];
|
|
45
49
|
if (!sandboxRootOverride || sandboxRootOverride.startsWith('--')) {
|
|
46
|
-
console.error('
|
|
50
|
+
console.error(t('cli.sandboxPath'));
|
|
47
51
|
process.exit(1);
|
|
48
52
|
}
|
|
49
53
|
}
|
|
@@ -61,18 +65,18 @@ async function main() {
|
|
|
61
65
|
// 裸 --resume:列出会话后退出
|
|
62
66
|
const sessions = listSessions();
|
|
63
67
|
if (sessions.length === 0) {
|
|
64
|
-
console.log(
|
|
68
|
+
console.log(t('cli.noSessions'));
|
|
65
69
|
}
|
|
66
70
|
else {
|
|
67
71
|
for (const s of sessions) {
|
|
68
|
-
console.log(`${s.id} ${s.firstUser || '
|
|
72
|
+
console.log(`${s.id} ${s.firstUser || t('cli.noValue')} ${s.model}`);
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
process.exit(0);
|
|
72
76
|
}
|
|
73
77
|
const loaded = loadSession(id);
|
|
74
78
|
if (!loaded || !loaded.history.length) {
|
|
75
|
-
console.error(
|
|
79
|
+
console.error(t('cli.sessionMissing', { id }));
|
|
76
80
|
process.exit(1);
|
|
77
81
|
}
|
|
78
82
|
const updateNotice = checkAndMaybeUpdate();
|
package/dist/llm/index.js
CHANGED
|
@@ -142,24 +142,27 @@ let createImplOverride = null;
|
|
|
142
142
|
export function __setChatCreateImpl(impl) {
|
|
143
143
|
createImplOverride = impl;
|
|
144
144
|
}
|
|
145
|
-
/** 把内部工具定义转成 OpenAI 的 tool 格式 */
|
|
146
|
-
export const chatTools = tools.map((t) => ({
|
|
147
|
-
type: 'function',
|
|
148
|
-
function: {
|
|
149
|
-
name: t.name,
|
|
150
|
-
description: t.description,
|
|
151
|
-
// 不同版本 SDK 的 FunctionParameters 宽严不一,用 any 兜底
|
|
152
|
-
parameters: t.parameters,
|
|
153
|
-
},
|
|
154
|
-
}));
|
|
155
145
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* 注意:planChatTools 是顶层 const(模块初始化时一次性求值);若运行时 /memory_switch 关闭
|
|
160
|
-
* 记忆,这里仍是按当前 isMemoryEnabled() 算出的快照——重启 REPL 才完全生效。
|
|
146
|
+
* 工具 schema 保持稳定数组引用,再在 MCP 发现或扩展变动后原地刷新;
|
|
147
|
+
* 这样 chat()/预算模块的默认参数不会继续指向陈旧的顶层快照。
|
|
161
148
|
*/
|
|
162
|
-
export const
|
|
149
|
+
export const chatTools = [];
|
|
150
|
+
export const planChatTools = [];
|
|
151
|
+
export function refreshChatTools() {
|
|
152
|
+
const next = tools.map((t) => ({
|
|
153
|
+
type: 'function',
|
|
154
|
+
function: {
|
|
155
|
+
name: t.name,
|
|
156
|
+
description: t.description,
|
|
157
|
+
// 不同版本 SDK 的 FunctionParameters 宽严不一,用 any 兜底
|
|
158
|
+
parameters: t.parameters,
|
|
159
|
+
},
|
|
160
|
+
}));
|
|
161
|
+
chatTools.splice(0, chatTools.length, ...next);
|
|
162
|
+
// MCP 协议没有可靠的副作用注解;plan 模式绝不暴露外部工具,保留只读探查保证。
|
|
163
|
+
planChatTools.splice(0, planChatTools.length, ...next.filter((t) => !t.function.name.startsWith('mcp__') && !getPlanDisabledTools().has(t.function.name)));
|
|
164
|
+
}
|
|
165
|
+
refreshChatTools();
|
|
163
166
|
/**
|
|
164
167
|
* 多 provider 兼容的 cache / reasoning 字段提取。
|
|
165
168
|
* 不同后端报 cached 字段名差异巨大,这里按"最常见的几种"顺序 probe,
|