mocode-ai 1.3.9 → 1.4.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.
- package/README.md +78 -70
- package/README.zh-CN.md +81 -73
- package/bin/mocode-agent-host.js +1 -1
- package/dist/agent/core.js +226 -293
- package/dist/agent/index.js +14 -10
- package/dist/agent/mode.js +3 -3
- package/dist/agent/runtime-context.js +45 -0
- package/dist/agent/spawn.js +101 -86
- package/dist/agent/tool-helpers.js +134 -0
- package/dist/agent/trace-state.js +118 -0
- package/dist/agents/coordinator.js +6 -1
- package/dist/changeset/index.js +9 -8
- package/dist/config/index.js +109 -77
- package/dist/config/presets.js +3 -1
- package/dist/config/profiles.js +125 -0
- package/dist/context/age-aware.js +2 -4
- package/dist/context/artifacts.js +6 -13
- package/dist/context/budget.js +6 -8
- package/dist/context/classifier.js +1 -2
- package/dist/context/encoders/code.js +2 -6
- package/dist/context/encoders/command.js +1 -3
- package/dist/context/encoders/search.js +1 -3
- package/dist/context/index.js +1 -1
- package/dist/context/lifecycle.js +5 -3
- package/dist/context/pipeline.js +1 -1
- package/dist/context/relevance.js +2 -4
- package/dist/context/token-calibration.js +13 -18
- package/dist/host/stdio.js +73 -12
- package/dist/i18n/index.js +96 -44
- package/dist/index.js +1 -1
- package/dist/llm/index.js +39 -23
- package/dist/llm/provider.js +23 -0
- package/dist/llm/providers/anthropic.js +12 -18
- package/dist/llm/tool-schema.js +48 -0
- package/dist/mcp/client.js +70 -25
- package/dist/mcp/config.js +1 -3
- package/dist/mcp/index.js +3 -1
- package/dist/memory/reflect.js +3 -6
- package/dist/memory/store.js +10 -12
- package/dist/permissions/index.js +66 -22
- package/dist/pet/bridge.js +2 -2
- package/dist/repl/commands/appearance.js +72 -0
- package/dist/repl/commands/compact.js +114 -0
- package/dist/repl/commands/context.js +17 -0
- package/dist/repl/commands/image.js +71 -0
- package/dist/repl/commands/memory.js +51 -0
- package/dist/repl/commands/mode.js +47 -0
- package/dist/repl/commands/model.js +435 -0
- package/dist/repl/commands/pet.js +70 -0
- package/dist/repl/commands/registry.js +46 -0
- package/dist/repl/commands/session.js +102 -0
- package/dist/repl/commands/skill.js +95 -0
- package/dist/repl/commands/system.js +202 -0
- package/dist/repl/commands/tool-group.js +233 -0
- package/dist/repl/commands/types.js +4 -0
- package/dist/repl/commands.js +324 -0
- package/dist/repl/index.js +5 -2577
- package/dist/repl/message-format.js +151 -0
- package/dist/repl/running-input.js +147 -0
- package/dist/repl/runtime.js +816 -0
- package/dist/repl/status-bar.js +161 -0
- package/dist/rollback/index.js +44 -14
- package/dist/runtime/browser-manager.js +1 -1
- package/dist/runtime/dev-server-manager.js +1 -1
- package/dist/runtime/input-injector.js +313 -0
- package/dist/runtime/screen-capture.js +89 -0
- package/dist/runtime/screen-pipeline.js +223 -0
- package/dist/sandbox/index.js +1 -1
- package/dist/sandbox/policy.js +8 -2
- package/dist/session/compact.js +22 -34
- package/dist/session/index.js +2 -2
- package/dist/session/notes.js +39 -5
- package/dist/session/persist.js +14 -8
- package/dist/session/scheduler.js +3 -4
- package/dist/session/trace-metrics.js +6 -3
- package/dist/skills/activation.js +10 -5
- package/dist/skills/discover.js +5 -17
- package/dist/skills/index.js +1 -1
- package/dist/skills/runner.js +28 -44
- package/dist/skills/toolmap.js +5 -2
- package/dist/tools/builtins/browser.js +17 -3
- package/dist/tools/builtins/computer.js +322 -0
- package/dist/tools/builtins/dev-server.js +1 -3
- package/dist/tools/builtins/edit-file.js +21 -7
- package/dist/tools/builtins/grep.js +1 -1
- package/dist/tools/builtins/index.js +28 -25
- package/dist/tools/builtins/memory-forget.js +1 -1
- package/dist/tools/builtins/memory-graph.js +4 -7
- package/dist/tools/builtins/memory-list.js +2 -6
- package/dist/tools/builtins/memory-save.js +8 -2
- package/dist/tools/builtins/memory-search.js +4 -4
- package/dist/tools/builtins/note-append.js +14 -3
- package/dist/tools/builtins/plan-update.js +40 -9
- package/dist/tools/builtins/run-command.js +8 -8
- package/dist/tools/builtins/screenshot.js +11 -87
- package/dist/tools/builtins/task.js +29 -40
- package/dist/tools/builtins/use-skill.js +1 -1
- package/dist/tools/builtins/view-image.js +5 -3
- package/dist/tools/builtins/web-fetch.js +1 -3
- package/dist/tools/builtins/web-search.js +3 -7
- package/dist/tools/builtins/write-file.js +4 -2
- package/dist/tools/constants.js +50 -37
- package/dist/tools/policy.js +221 -0
- package/dist/tools/registry.js +40 -19
- package/dist/tools/resource-lock.js +4 -2
- package/dist/tools/router.js +143 -0
- package/dist/tools/validation.js +6 -5
- package/dist/ui/batch.js +63 -23
- package/dist/ui/clipboard.js +17 -5
- package/dist/ui/content.js +166 -13
- package/dist/ui/diff.js +61 -19
- package/dist/ui/fuzzy.js +35 -2
- package/dist/ui/intervention.js +2 -4
- package/dist/ui/layout-internal/content-write.js +587 -0
- package/dist/ui/layout-internal/core.js +590 -0
- package/dist/ui/layout-internal/input-paint.js +365 -0
- package/dist/ui/layout-internal/screen.js +128 -0
- package/dist/ui/layout-internal/scroll.js +152 -0
- package/dist/ui/layout-internal/selection.js +229 -0
- package/dist/ui/layout-internal/state.js +82 -0
- package/dist/ui/layout-internal/statusbar.js +351 -0
- package/dist/ui/layout-types.js +1 -0
- package/dist/ui/layout.js +3 -2288
- package/dist/ui/markdown.js +10 -2
- package/dist/ui/prompt-internal/editor.js +945 -0
- package/dist/ui/prompt-internal/paste.js +52 -0
- package/dist/ui/prompt-internal/pickers.js +519 -0
- package/dist/ui/prompt-internal/types.js +1 -0
- package/dist/ui/prompt.js +4 -1506
- package/dist/ui/render.js +87 -2
- package/dist/verification/affected.js +11 -5
- package/dist/verification/discovery.js +1 -3
- package/dist/verification/profile.js +11 -3
- package/package.json +11 -2
package/dist/i18n/index.js
CHANGED
|
@@ -19,14 +19,18 @@ const zhCN = {
|
|
|
19
19
|
'commands.memoryStatus': '查看当前开关与原理',
|
|
20
20
|
'commands.memoryReflect': '手动触发后台记忆反思',
|
|
21
21
|
'commands.memoryInit': '扫描项目生成 AGENTS.md 项目记忆',
|
|
22
|
-
'commands.subagent': '子 Agent
|
|
23
|
-
'commands.subagentOn': '
|
|
24
|
-
'commands.subagentOff': '
|
|
25
|
-
'commands.subagentStatus': '
|
|
26
|
-
'commands.fe': '
|
|
27
|
-
'commands.feOn': '
|
|
28
|
-
'commands.feOff': '
|
|
29
|
-
'commands.feStatus': '
|
|
22
|
+
'commands.subagent': '子 Agent 自动路由 gate',
|
|
23
|
+
'commands.subagentOn': '允许按需路由 orchestration',
|
|
24
|
+
'commands.subagentOff': '禁止 orchestration',
|
|
25
|
+
'commands.subagentStatus': '查看 orchestration gate',
|
|
26
|
+
'commands.fe': '浏览器调试/桌面观察自动路由 gate',
|
|
27
|
+
'commands.feOn': '允许按需路由 browser/dev_server/screenshot',
|
|
28
|
+
'commands.feOff': '禁止 browser-debug/desktop-observe',
|
|
29
|
+
'commands.feStatus': '查看前端能力 gate',
|
|
30
|
+
'commands.cu': 'Computer Use 自动路由 gate(高危)',
|
|
31
|
+
'commands.cuOn': '允许按需路由 computer-control',
|
|
32
|
+
'commands.cuOff': '禁止 computer-control',
|
|
33
|
+
'commands.cuStatus': '查看 Computer Use gate',
|
|
30
34
|
'commands.mcp': 'MCP 服务开关(重启后生效)',
|
|
31
35
|
'commands.mcpOn': '开启 MCP 服务',
|
|
32
36
|
'commands.mcpOff': '关闭 MCP 服务',
|
|
@@ -41,7 +45,7 @@ const zhCN = {
|
|
|
41
45
|
'commands.modelDelete': '删除指定预设',
|
|
42
46
|
'commands.mode': '切换 Agent 工作模式',
|
|
43
47
|
'commands.modePlan': '只读探查并产出计划',
|
|
44
|
-
'commands.modeAuto': '
|
|
48
|
+
'commands.modeAuto': '自动执行(工具按任务动态路由)',
|
|
45
49
|
'commands.pet': '桌宠控制',
|
|
46
50
|
'commands.petToggle': '显示或隐藏桌宠',
|
|
47
51
|
'commands.petSkin': '选择桌宠皮肤',
|
|
@@ -140,14 +144,14 @@ const zhCN = {
|
|
|
140
144
|
'repl.planAlready': '(已在 plan 模式)',
|
|
141
145
|
'repl.planChanged': '(已切到 plan 模式:只读探查 + 产出计划,审批后切 auto 执行。/auto 或 Shift+Tab 切回)',
|
|
142
146
|
'repl.autoAlready': '(已在 auto 模式)',
|
|
143
|
-
'repl.autoChanged': '(已切回 auto
|
|
147
|
+
'repl.autoChanged': '(已切回 auto 模式:工具按任务自动路由)',
|
|
144
148
|
'repl.noImages': '(无待发送图片)',
|
|
145
149
|
'repl.imagesCleared': '(已清空待发送图片)',
|
|
146
150
|
'repl.imageUsage': '用法:/image <path>',
|
|
147
151
|
'repl.themeList': '可用主题:',
|
|
148
152
|
'repl.themeCurrent': '(当前:{theme};用 /theme <名称> 切换)',
|
|
149
153
|
'repl.themeChanged': '(已切换主题 {theme})',
|
|
150
|
-
'repl.modeCurrent': '当前模式:{mode};/plan
|
|
154
|
+
'repl.modeCurrent': '当前模式:{mode};/plan 切到只读规划,/auto 按任务自动路由工具并执行',
|
|
151
155
|
'repl.unknownCommand': '未知命令:{value}',
|
|
152
156
|
'repl.didYouMean': '你是不是想输入 {value}?',
|
|
153
157
|
'repl.unknownCommandHint': '输入 /help 查看全部命令(普通文本直接打字发送,不必加 /)',
|
|
@@ -228,6 +232,8 @@ const zhCN = {
|
|
|
228
232
|
'permission.dangerTitle': '⚠ 高风险操作: {tool}',
|
|
229
233
|
'permission.confirmTitle': '确认执行: {tool}',
|
|
230
234
|
'permission.dangerWarning': '⚠ 此操作可能产生不可逆副作用,请谨慎确认。',
|
|
235
|
+
'permission.computerSensitiveReview': '⚠ 待输入内容含 URL / 密码形态 / 支付关键词,已强制要求逐次确认(不可授权整个会话)。',
|
|
236
|
+
'permission.computerAction': '桌面动作: {value}',
|
|
231
237
|
'permission.firstTimeHint': '说明:面板按工具风险等级弹出。「允许」仅放行本次操作;选择会话级/项目级选项后,同类命令不再重复询问。',
|
|
232
238
|
'permission.confirmExecute': '确认执行',
|
|
233
239
|
'permission.allowForever': '以后不再询问此工具',
|
|
@@ -240,29 +246,35 @@ const zhCN = {
|
|
|
240
246
|
'askHuman.submitted': '用户回答:{value}',
|
|
241
247
|
'askHuman.selected': '用户选择:{value}',
|
|
242
248
|
'task.missingPrompt': '错误:缺少 prompt(子任务指令)。',
|
|
243
|
-
'task.disabled': '
|
|
249
|
+
'task.disabled': '错误:orchestration capability gate 已关闭。需要时请运行 /subagent on。',
|
|
244
250
|
'task.interrupted': '子 agent 被中断,未完成。',
|
|
245
251
|
'task.noSummary': '子 agent 完成但未返回文本摘要(可能只调了工具或达到步数上限)。',
|
|
246
252
|
'task.summaryTruncated': '…(子 agent 摘要已截断 {count} 字符)',
|
|
247
253
|
'subagent.running': '子 Agent 运行中',
|
|
248
254
|
'subagent.complete': '子 Agent 完成',
|
|
249
255
|
'subagent.failed': '子 Agent 失败',
|
|
250
|
-
'subagent.status': '
|
|
251
|
-
'subagent.stateOn': '
|
|
252
|
-
'subagent.stateOff': '
|
|
253
|
-
'subagent.changedOn': '
|
|
254
|
-
'subagent.changedOff': '
|
|
256
|
+
'subagent.status': 'Orchestration 自动路由:{state}',
|
|
257
|
+
'subagent.stateOn': '允许',
|
|
258
|
+
'subagent.stateOff': '禁止',
|
|
259
|
+
'subagent.changedOn': '已允许自动路由按需选择 orchestration(sub-agent / run_skill);不会常驻工具表。',
|
|
260
|
+
'subagent.changedOff': '已禁止 orchestration;路由器和运行时都会拦截后续调用。',
|
|
255
261
|
'skill.executing': '执行 skill: {name}…',
|
|
256
262
|
'skill.complete': 'Skill 执行完成',
|
|
257
263
|
'skill.aborted': 'Skill 执行已中断',
|
|
258
264
|
'skill.maxSteps': 'Skill 达到最大步数({max})',
|
|
259
265
|
'subagent.usage': '用法:/subagent on|off|status',
|
|
260
|
-
'fe.status': '
|
|
261
|
-
'fe.stateOn': '
|
|
262
|
-
'fe.stateOff': '
|
|
263
|
-
'fe.changedOn': '
|
|
264
|
-
'fe.changedOff': '
|
|
266
|
+
'fe.status': 'Browser/desktop 自动路由:{state}',
|
|
267
|
+
'fe.stateOn': '允许',
|
|
268
|
+
'fe.stateOff': '禁止',
|
|
269
|
+
'fe.changedOn': '已允许按需路由 browser-debug / desktop-observe;view_image 始终属于公共工具。',
|
|
270
|
+
'fe.changedOff': '已禁止 browser-debug / desktop-observe;后续路由不会暴露 browser / dev_server / screenshot。',
|
|
265
271
|
'fe.usage': '用法:/fe on|off|status',
|
|
272
|
+
'cu.status': 'Computer-control 自动路由:{state}',
|
|
273
|
+
'cu.stateOn': '允许',
|
|
274
|
+
'cu.stateOff': '禁止',
|
|
275
|
+
'cu.changedOn': '已允许按需路由 computer-control;只有明确 GUI 操作意图才会选择,且每个动作仍需权限确认。',
|
|
276
|
+
'cu.changedOff': '已禁止 computer-control;路由器和运行时都会拦截后续 computer 调用。',
|
|
277
|
+
'cu.usage': '用法:/cu on|off|status',
|
|
266
278
|
'mcp.status': 'MCP 服务:{state}',
|
|
267
279
|
'mcp.stateOn': '开启',
|
|
268
280
|
'mcp.stateOff': '关闭',
|
|
@@ -271,6 +283,20 @@ const zhCN = {
|
|
|
271
283
|
'mcp.usage': '用法:/mcp on|off|status',
|
|
272
284
|
'mcp.unchanged': 'MCP 已是{state},未变更。',
|
|
273
285
|
'mcp.restartHint': '该设置已写入配置文件;下次启动将按此状态决定是否连接 MCP。',
|
|
286
|
+
'memory.routeStatus': 'Memory 自动路由:{state}',
|
|
287
|
+
'memory.indexStatus': 'Memory Index / 后台反思:{state}',
|
|
288
|
+
'memory.stateAllowed': '允许',
|
|
289
|
+
'memory.stateBlocked': '禁止',
|
|
290
|
+
'memory.stateEnabled': '开启',
|
|
291
|
+
'memory.stateDisabled': '关闭',
|
|
292
|
+
'memory.source': 'MEMORY_ENABLED={value} · {path}',
|
|
293
|
+
'memory.statusHint': '路由 gate 决定 memory-read / memory-write 是否可选;Index 状态决定紧凑索引和后台反思是否启用。每个真实用户轮都会重新路由。',
|
|
294
|
+
'memory.usage': '用法:/memory_switch [on|off|status](/memory_status 仅查看状态)',
|
|
295
|
+
'memory.unchanged': 'Memory 已是{state},未变更。',
|
|
296
|
+
'memory.changedOn': '已允许按需路由 memory-read / memory-write,并开启 Memory Index。',
|
|
297
|
+
'memory.changedOff': '已禁止 memory-read / memory-write,并关闭 Memory Index。',
|
|
298
|
+
'memory.saved': '已写入 {path}: MEMORY_ENABLED={value};下一真实用户轮起生效。',
|
|
299
|
+
'memory.failed': '/memory_switch 失败:{error}',
|
|
274
300
|
'plan.ready': '计划已就绪',
|
|
275
301
|
'plan.approvalDetail': '切换到 auto 模式按上述计划执行?(plan 模式只读探查,执行需切 auto)',
|
|
276
302
|
'plan.execute': '切 auto 执行',
|
|
@@ -321,14 +347,18 @@ const en = {
|
|
|
321
347
|
'commands.memoryStatus': 'Show current state and behavior',
|
|
322
348
|
'commands.memoryReflect': 'Run background memory reflection',
|
|
323
349
|
'commands.memoryInit': 'Scan project and generate AGENTS.md',
|
|
324
|
-
'commands.subagent': 'Sub-agent
|
|
325
|
-
'commands.subagentOn': '
|
|
326
|
-
'commands.subagentOff': '
|
|
327
|
-
'commands.subagentStatus': 'Show
|
|
328
|
-
'commands.fe': '
|
|
329
|
-
'commands.feOn': '
|
|
330
|
-
'commands.feOff': '
|
|
331
|
-
'commands.feStatus': 'Show frontend
|
|
350
|
+
'commands.subagent': 'Sub-agent automatic-routing gate',
|
|
351
|
+
'commands.subagentOn': 'Allow orchestration to be routed when needed',
|
|
352
|
+
'commands.subagentOff': 'Block orchestration',
|
|
353
|
+
'commands.subagentStatus': 'Show orchestration gate',
|
|
354
|
+
'commands.fe': 'Browser-debug and desktop-observe routing gate',
|
|
355
|
+
'commands.feOn': 'Allow browser/dev_server/screenshot routing',
|
|
356
|
+
'commands.feOff': 'Block browser-debug and desktop-observe',
|
|
357
|
+
'commands.feStatus': 'Show frontend capability gate',
|
|
358
|
+
'commands.cu': 'Computer Use automatic-routing gate (high-risk)',
|
|
359
|
+
'commands.cuOn': 'Allow computer-control routing when needed',
|
|
360
|
+
'commands.cuOff': 'Block computer-control',
|
|
361
|
+
'commands.cuStatus': 'Show Computer Use gate',
|
|
332
362
|
'commands.mcp': 'MCP service controls (applies immediately)',
|
|
333
363
|
'commands.mcpOn': 'Enable MCP services',
|
|
334
364
|
'commands.mcpOff': 'Disable MCP services',
|
|
@@ -343,7 +373,7 @@ const en = {
|
|
|
343
373
|
'commands.modelDelete': 'Delete a preset',
|
|
344
374
|
'commands.mode': 'Switch Agent mode',
|
|
345
375
|
'commands.modePlan': 'Read-only research and planning',
|
|
346
|
-
'commands.modeAuto': 'Execute automatically with
|
|
376
|
+
'commands.modeAuto': 'Execute automatically with task-routed tools',
|
|
347
377
|
'commands.pet': 'Desktop pet controls',
|
|
348
378
|
'commands.petToggle': 'Show or hide the desktop pet',
|
|
349
379
|
'commands.petSkin': 'Choose a pet skin',
|
|
@@ -442,14 +472,14 @@ const en = {
|
|
|
442
472
|
'repl.planAlready': '(already in plan mode)',
|
|
443
473
|
'repl.planChanged': '(switched to plan mode: read-only research and planning; approval returns to auto. Use /auto or Shift+Tab to switch back)',
|
|
444
474
|
'repl.autoAlready': '(already in auto mode)',
|
|
445
|
-
'repl.autoChanged': '(switched to auto mode:
|
|
475
|
+
'repl.autoChanged': '(switched to auto mode: tools are routed per task)',
|
|
446
476
|
'repl.noImages': '(no pending images)',
|
|
447
477
|
'repl.imagesCleared': '(pending images cleared)',
|
|
448
478
|
'repl.imageUsage': 'Usage: /image <path>',
|
|
449
479
|
'repl.themeList': 'Available themes:',
|
|
450
480
|
'repl.themeCurrent': '(current: {theme}; use /theme <name> to switch)',
|
|
451
481
|
'repl.themeChanged': '(switched theme to {theme})',
|
|
452
|
-
'repl.modeCurrent': 'Current mode: {mode}; /plan for read-only planning, /auto for
|
|
482
|
+
'repl.modeCurrent': 'Current mode: {mode}; /plan for read-only planning, /auto for task-routed execution',
|
|
453
483
|
'repl.unknownCommand': 'Unknown command: {value}',
|
|
454
484
|
'repl.didYouMean': 'Did you mean {value}?',
|
|
455
485
|
'repl.unknownCommandHint': 'Run /help for all commands (plain text is sent as-is, no slash needed)',
|
|
@@ -530,6 +560,8 @@ const en = {
|
|
|
530
560
|
'permission.dangerTitle': '⚠ High-risk operation: {tool}',
|
|
531
561
|
'permission.confirmTitle': 'Confirm execution: {tool}',
|
|
532
562
|
'permission.dangerWarning': '⚠ This operation may have irreversible side effects. Confirm carefully.',
|
|
563
|
+
'permission.computerSensitiveReview': '⚠ The text to type contains a URL / password pattern / payment keyword; per-action approval is enforced (no session-wide grant).',
|
|
564
|
+
'permission.computerAction': 'Desktop action: {value}',
|
|
533
565
|
'permission.firstTimeHint': "Note: this panel appears based on each tool's risk level. 'Allow' approves only this action; session/project options stop repeated prompts for the same command.",
|
|
534
566
|
'permission.confirmExecute': 'Confirm and run',
|
|
535
567
|
'permission.allowForever': 'Always allow this tool',
|
|
@@ -542,29 +574,35 @@ const en = {
|
|
|
542
574
|
'askHuman.submitted': 'User response: {value}',
|
|
543
575
|
'askHuman.selected': 'User selected: {value}',
|
|
544
576
|
'task.missingPrompt': 'Error: missing prompt (sub-task instruction).',
|
|
545
|
-
'task.disabled': 'Error:
|
|
577
|
+
'task.disabled': 'Error: the orchestration capability gate is blocked. Run /subagent on if needed.',
|
|
546
578
|
'task.interrupted': 'The sub-agent was interrupted before completion.',
|
|
547
579
|
'task.noSummary': 'The sub-agent completed without a text summary (it may only have used tools or reached its step limit).',
|
|
548
580
|
'task.summaryTruncated': '…(sub-agent summary truncated by {count} characters)',
|
|
549
581
|
'subagent.running': 'Sub-agent running',
|
|
550
582
|
'subagent.complete': 'Sub-agent complete',
|
|
551
583
|
'subagent.failed': 'Sub-agent failed',
|
|
552
|
-
'subagent.status': '
|
|
553
|
-
'subagent.stateOn': '
|
|
554
|
-
'subagent.stateOff': '
|
|
555
|
-
'subagent.changedOn': '
|
|
556
|
-
'subagent.changedOff': '
|
|
584
|
+
'subagent.status': 'Orchestration automatic routing: {state}',
|
|
585
|
+
'subagent.stateOn': 'allowed',
|
|
586
|
+
'subagent.stateOff': 'blocked',
|
|
587
|
+
'subagent.changedOn': 'Automatic routing may now select orchestration (sub-agent / run_skill) when needed; it is not always exposed.',
|
|
588
|
+
'subagent.changedOff': 'Orchestration is blocked; both the router and runtime reject subsequent calls.',
|
|
557
589
|
'skill.executing': 'Executing skill: {name}…',
|
|
558
590
|
'skill.complete': 'Skill complete',
|
|
559
591
|
'skill.aborted': 'Skill aborted',
|
|
560
592
|
'skill.maxSteps': 'Skill reached max steps ({max})',
|
|
561
593
|
'subagent.usage': 'Usage: /subagent on|off|status',
|
|
562
|
-
'fe.status': '
|
|
563
|
-
'fe.stateOn': '
|
|
564
|
-
'fe.stateOff': '
|
|
565
|
-
'fe.changedOn': '
|
|
566
|
-
'fe.changedOff': '
|
|
594
|
+
'fe.status': 'Browser/desktop automatic routing: {state}',
|
|
595
|
+
'fe.stateOn': 'allowed',
|
|
596
|
+
'fe.stateOff': 'blocked',
|
|
597
|
+
'fe.changedOn': 'Automatic routing may now select browser-debug / desktop-observe; view_image remains a common tool.',
|
|
598
|
+
'fe.changedOff': 'Browser-debug / desktop-observe are blocked; browser / dev_server / screenshot will not be exposed.',
|
|
567
599
|
'fe.usage': 'Usage: /fe on|off|status',
|
|
600
|
+
'cu.status': 'Computer-control automatic routing: {state}',
|
|
601
|
+
'cu.stateOn': 'allowed',
|
|
602
|
+
'cu.stateOff': 'blocked',
|
|
603
|
+
'cu.changedOn': 'Automatic routing may now select computer-control for explicit GUI intent; every action still requires permission approval.',
|
|
604
|
+
'cu.changedOff': 'Computer-control is blocked; both the router and runtime reject subsequent computer calls.',
|
|
605
|
+
'cu.usage': 'Usage: /cu on|off|status',
|
|
568
606
|
'mcp.status': 'MCP services: {state}',
|
|
569
607
|
'mcp.stateOn': 'enabled',
|
|
570
608
|
'mcp.stateOff': 'disabled',
|
|
@@ -573,6 +611,20 @@ const en = {
|
|
|
573
611
|
'mcp.usage': 'Usage: /mcp on|off|status',
|
|
574
612
|
'mcp.unchanged': 'MCP is already {state}; no change made.',
|
|
575
613
|
'mcp.restartHint': 'This setting is saved to the configuration file; future startups use it to decide whether to connect MCP.',
|
|
614
|
+
'memory.routeStatus': 'Memory automatic routing: {state}',
|
|
615
|
+
'memory.indexStatus': 'Memory Index / background reflection: {state}',
|
|
616
|
+
'memory.stateAllowed': 'allowed',
|
|
617
|
+
'memory.stateBlocked': 'blocked',
|
|
618
|
+
'memory.stateEnabled': 'enabled',
|
|
619
|
+
'memory.stateDisabled': 'disabled',
|
|
620
|
+
'memory.source': 'MEMORY_ENABLED={value} · {path}',
|
|
621
|
+
'memory.statusHint': 'The route gate controls whether memory-read / memory-write may be selected; the Index state controls prompt injection and background reflection. Every real user turn is routed again.',
|
|
622
|
+
'memory.usage': 'Usage: /memory_switch [on|off|status] (/memory_status only reports state)',
|
|
623
|
+
'memory.unchanged': 'Memory is already {state}; no change made.',
|
|
624
|
+
'memory.changedOn': 'Memory-read / memory-write may now be routed on demand, and the Memory Index is enabled.',
|
|
625
|
+
'memory.changedOff': 'Memory-read / memory-write are now blocked, and the Memory Index is disabled.',
|
|
626
|
+
'memory.saved': 'Saved {path}: MEMORY_ENABLED={value}; effective from the next real user turn.',
|
|
627
|
+
'memory.failed': '/memory_switch failed: {error}',
|
|
576
628
|
'plan.ready': 'Plan ready',
|
|
577
629
|
'plan.approvalDetail': 'Switch to auto mode and execute the plan above? (Plan mode is read-only; execution requires auto mode.)',
|
|
578
630
|
'plan.execute': 'Switch to auto and execute',
|
package/dist/index.js
CHANGED
|
@@ -87,7 +87,7 @@ async function main() {
|
|
|
87
87
|
process.exit(1);
|
|
88
88
|
}
|
|
89
89
|
const { startRepl } = await import('./repl/index.js');
|
|
90
|
-
await startRepl(loaded.history, loaded.id, sandboxRootOverride, loaded.queryHistory);
|
|
90
|
+
await startRepl(loaded.history, loaded.id, sandboxRootOverride, loaded.queryHistory, loaded.lastToolGroups);
|
|
91
91
|
}
|
|
92
92
|
else {
|
|
93
93
|
const { startRepl } = await import('./repl/index.js');
|
package/dist/llm/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
|
-
import { config, getActiveModel
|
|
2
|
+
import { config, getActiveModel } from '../config/index.js';
|
|
3
3
|
import { tools } from '../tools/registry.js';
|
|
4
|
-
import { getPlanDisabledTools,
|
|
4
|
+
import { getPlanDisabledTools, getProfileDisabledTools } from '../tools/constants.js';
|
|
5
5
|
import { ThinkTagFilter } from './think-filter.js';
|
|
6
|
+
import { sanitizeToolSchemas } from './tool-schema.js';
|
|
6
7
|
import { anthropicChatOnce } from './providers/anthropic.js';
|
|
8
|
+
import { registerModelProvider, getModelProvider, listModelProviders } from './provider.js';
|
|
7
9
|
// 强制关闭第三方调试日志泄漏:openai SDK 在 process.env.DEBUG === 'true' 时用裸
|
|
8
10
|
// console.log 把请求/响应直写 stdout,会污染 TUI 输入框(并泄露 headers/URL)。
|
|
9
11
|
// 仅拦截 'true' 这一开关值——保留 namespace 形式的 DEBUG(如 DEBUG=express:*) 调试能力。
|
|
@@ -57,13 +59,13 @@ function sleep(ms, signal) {
|
|
|
57
59
|
reject(new DOMException('This operation was aborted', 'AbortError'));
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
|
-
let onAbort;
|
|
61
62
|
const t = setTimeout(() => {
|
|
62
|
-
|
|
63
|
-
signal?.removeEventListener('abort', onAbort);
|
|
63
|
+
signal?.removeEventListener('abort', onAbort);
|
|
64
64
|
resolve();
|
|
65
65
|
}, ms);
|
|
66
|
-
onAbort
|
|
66
|
+
// onAbort 用 const:声明点即唯一赋值点。setTimeout 回调里的前向引用只在异步触发时求值,
|
|
67
|
+
// 那时 onAbort 已初始化,不存在 TDZ。
|
|
68
|
+
const onAbort = () => {
|
|
67
69
|
clearTimeout(t);
|
|
68
70
|
reject(new DOMException('This operation was aborted', 'AbortError'));
|
|
69
71
|
};
|
|
@@ -219,14 +221,11 @@ export function __setChatCreateImpl(impl) {
|
|
|
219
221
|
export const chatTools = [];
|
|
220
222
|
export const planChatTools = [];
|
|
221
223
|
export function refreshChatTools() {
|
|
222
|
-
//
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
return isFrontendToolsEnabled();
|
|
228
|
-
return true;
|
|
229
|
-
});
|
|
224
|
+
// Legacy fallback for callers that do not pass a per-turn ToolPolicy. Official TUI/stdio requests
|
|
225
|
+
// build schemas from ToolPolicy snapshots instead; keep this stable array for old embeddings and budgets.
|
|
226
|
+
// MCP extensions are not part of the static profile map and remain visible on this compatibility path.
|
|
227
|
+
const profileDisabled = getProfileDisabledTools();
|
|
228
|
+
const visibleTools = tools.filter((tool) => !profileDisabled.has(tool.name));
|
|
230
229
|
const next = visibleTools.map((t) => ({
|
|
231
230
|
type: 'function',
|
|
232
231
|
function: {
|
|
@@ -240,6 +239,22 @@ export function refreshChatTools() {
|
|
|
240
239
|
// MCP 协议没有可靠的副作用注解;plan 模式绝不暴露外部工具,保留只读探查保证。
|
|
241
240
|
planChatTools.splice(0, planChatTools.length, ...next.filter((t) => !t.function.name.startsWith('mcp__') && !getPlanDisabledTools().has(t.function.name)));
|
|
242
241
|
}
|
|
242
|
+
// 不在模块顶层调用 refreshChatTools():llm → registry 的 import 在部分加载顺序下会
|
|
243
|
+
// 形成循环(registry → builtins → … → llm),顶层执行时 tools 尚未初始化(TDZ ReferenceError)。
|
|
244
|
+
// chatTools 初始为空数组;两个真实入口(repl 启动、stdio host 启动)都会显式刷新,
|
|
245
|
+
// 所有消费方(budget/compact/scheduler 默认参数、agent 装配)均在运行时求值,不受影响。
|
|
246
|
+
// ── 默认 provider 注册(2.0 步骤3)──────────────────────────────────────────────
|
|
247
|
+
// 把 chat() 原本的 config.provider if-else 分流变成注册表查找:openai 走 chatOnce,
|
|
248
|
+
// anthropic 走 anthropicChatOnce。chatOnce 是 hoisted 函数声明,模块顶层引用安全。
|
|
249
|
+
// 新增 provider 只需 registerModelProvider,不必改 chat()。
|
|
250
|
+
registerModelProvider({
|
|
251
|
+
name: 'openai',
|
|
252
|
+
chatOnce: (messages, handlers, signal, tools) => chatOnce(messages, handlers, signal, tools),
|
|
253
|
+
});
|
|
254
|
+
registerModelProvider({
|
|
255
|
+
name: 'anthropic',
|
|
256
|
+
chatOnce: (messages, handlers, signal, tools) => anthropicChatOnce(messages, handlers, signal, tools ?? chatTools),
|
|
257
|
+
});
|
|
243
258
|
/**
|
|
244
259
|
* 多 provider 兼容的 cache / reasoning 字段提取。
|
|
245
260
|
* 不同后端报 cached 字段名差异巨大,这里按"最常见的几种"顺序 probe,
|
|
@@ -327,10 +342,12 @@ toolsOverride) {
|
|
|
327
342
|
throw new DOMException('This operation was aborted', 'AbortError');
|
|
328
343
|
}
|
|
329
344
|
try {
|
|
330
|
-
|
|
331
|
-
|
|
345
|
+
const provider = getModelProvider(config.provider);
|
|
346
|
+
if (!provider) {
|
|
347
|
+
// 未注册的 provider:给出可用名单,避免悄悄落到错误实现。
|
|
348
|
+
throw new Error(`未知的 LLM provider "${config.provider}";已注册:${listModelProviders().join(', ') || '(空)'}`);
|
|
332
349
|
}
|
|
333
|
-
return await chatOnce(messages, handlers, signal, toolsOverride);
|
|
350
|
+
return await provider.chatOnce(messages, handlers, signal, toolsOverride);
|
|
334
351
|
}
|
|
335
352
|
catch (err) {
|
|
336
353
|
lastErr = err;
|
|
@@ -416,7 +433,9 @@ async function chatOnce(messages, handlers, signal, toolsOverride) {
|
|
|
416
433
|
const create = createImplOverride
|
|
417
434
|
? createImplOverride
|
|
418
435
|
: (body, opts) => client.chat.completions.create(body, opts);
|
|
419
|
-
|
|
436
|
+
// transport 边界消毒:剔除部分后端(kimi-k3@dashscope 实测)整请求 400 拒绝的
|
|
437
|
+
// uniqueItems 关键字。无需改写时返回原引用,前缀缓存逐字节稳定不受影响。
|
|
438
|
+
const activeTools = sanitizeToolSchemas(toolsOverride ?? chatTools);
|
|
420
439
|
const stream = await create({
|
|
421
440
|
model: getActiveModel(),
|
|
422
441
|
messages: normalizeImageDetail(messages),
|
|
@@ -613,8 +632,7 @@ export function messageTokens(m) {
|
|
|
613
632
|
else if (role === 'tool')
|
|
614
633
|
structural = 6;
|
|
615
634
|
let body = contentTokens(m.content);
|
|
616
|
-
const tcs = m
|
|
617
|
-
.tool_calls;
|
|
635
|
+
const tcs = m.tool_calls;
|
|
618
636
|
if (tcs) {
|
|
619
637
|
for (const tc of tcs)
|
|
620
638
|
body += estimateTokens(tc?.function?.arguments ?? '');
|
|
@@ -643,9 +661,7 @@ export function estimateToolSchemaTokens(activeTools = chatTools) {
|
|
|
643
661
|
}
|
|
644
662
|
/** 把模型级校正系数统一应用到原始估算。 */
|
|
645
663
|
export function correctTokenEstimate(estimate, correction = 1) {
|
|
646
|
-
const safeCorrection = Number.isFinite(correction)
|
|
647
|
-
? Math.max(0.5, Math.min(2, correction))
|
|
648
|
-
: 1;
|
|
664
|
+
const safeCorrection = Number.isFinite(correction) ? Math.max(0.5, Math.min(2, correction)) : 1;
|
|
649
665
|
return estimate > 0 ? Math.max(1, Math.ceil(estimate * safeCorrection)) : 0;
|
|
650
666
|
}
|
|
651
667
|
/** 估算一次完整请求的 prompt token(messages + 本次实际工具 schema)。 */
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ModelProvider 抽象(2.0 步骤3):把「某种模型后端怎么做一次流式 chat」从 chat() 的
|
|
3
|
+
* 硬编码 if-else 分流(config.provider === 'anthropic' ? … : …)变成注册表查找。
|
|
4
|
+
* 新增 provider(Responses API / 本地模型 / 事件式模型)只需 registerModelProvider,
|
|
5
|
+
* 不再需要改 chat() 本体。
|
|
6
|
+
*
|
|
7
|
+
* 本模块只对 index.ts 做 type-only import(运行期零依赖,不构成循环引用);
|
|
8
|
+
* 不读 config、不持会话状态,注册表是显式的进程级插件点。默认 provider(openai /
|
|
9
|
+
* anthropic)由 index.ts 在模块初始化时注册,与既有 config.provider 行为完全一致。
|
|
10
|
+
*/
|
|
11
|
+
const providers = new Map();
|
|
12
|
+
/** 注册一个 provider;同名覆盖(与 registerToolsExtension 的按源替换语义一致)。 */
|
|
13
|
+
export function registerModelProvider(provider) {
|
|
14
|
+
providers.set(provider.name, provider);
|
|
15
|
+
}
|
|
16
|
+
/** 按名取 provider;未注册返 undefined(chat() 据此报清晰错误)。 */
|
|
17
|
+
export function getModelProvider(name) {
|
|
18
|
+
return providers.get(name);
|
|
19
|
+
}
|
|
20
|
+
/** 列出已注册 provider 名(错误提示/诊断用)。 */
|
|
21
|
+
export function listModelProviders() {
|
|
22
|
+
return [...providers.keys()];
|
|
23
|
+
}
|
|
@@ -9,9 +9,7 @@ function parseJsonObject(value) {
|
|
|
9
9
|
return {};
|
|
10
10
|
try {
|
|
11
11
|
const parsed = JSON.parse(value);
|
|
12
|
-
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
13
|
-
? parsed
|
|
14
|
-
: {};
|
|
12
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
|
|
15
13
|
}
|
|
16
14
|
catch {
|
|
17
15
|
return {};
|
|
@@ -102,13 +100,13 @@ export function encodeAnthropicMessages(input, promptCache = config.anthropicPro
|
|
|
102
100
|
continue;
|
|
103
101
|
}
|
|
104
102
|
if (message.role === 'tool') {
|
|
105
|
-
appendMessage(messages, 'user', [
|
|
103
|
+
appendMessage(messages, 'user', [
|
|
104
|
+
{
|
|
106
105
|
type: 'tool_result',
|
|
107
106
|
tool_use_id: message.tool_call_id ?? '',
|
|
108
|
-
content: typeof message.content === 'string'
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}], cacheCandidates);
|
|
107
|
+
content: typeof message.content === 'string' ? message.content : JSON.stringify(message.content ?? ''),
|
|
108
|
+
},
|
|
109
|
+
], cacheCandidates);
|
|
112
110
|
}
|
|
113
111
|
}
|
|
114
112
|
if (promptCache) {
|
|
@@ -241,10 +239,10 @@ function usageFromAnthropic(raw) {
|
|
|
241
239
|
function addLiveCount(text, state) {
|
|
242
240
|
for (const ch of text) {
|
|
243
241
|
const cp = ch.codePointAt(0) ?? 0;
|
|
244
|
-
if ((cp >= 0x4e00 && cp <= 0x9fff)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
242
|
+
if ((cp >= 0x4e00 && cp <= 0x9fff) ||
|
|
243
|
+
(cp >= 0x3400 && cp <= 0x4dbf) ||
|
|
244
|
+
(cp >= 0x3040 && cp <= 0x30ff) ||
|
|
245
|
+
(cp >= 0xac00 && cp <= 0xd7a3))
|
|
248
246
|
state.cjk++;
|
|
249
247
|
else
|
|
250
248
|
state.other++;
|
|
@@ -306,17 +304,13 @@ export async function anthropicChatOnce(messages, handlers, signal, tools) {
|
|
|
306
304
|
reportLive();
|
|
307
305
|
}
|
|
308
306
|
else if (block?.type === 'tool_use') {
|
|
309
|
-
const initialInput = block.input && typeof block.input === 'object'
|
|
310
|
-
? block.input
|
|
311
|
-
: undefined;
|
|
307
|
+
const initialInput = block.input && typeof block.input === 'object' ? block.input : undefined;
|
|
312
308
|
const call = {
|
|
313
309
|
id: typeof block.id === 'string' ? block.id : '',
|
|
314
310
|
name: typeof block.name === 'string' ? block.name : '',
|
|
315
311
|
// 流式 tool_use 通常以 input:{} 开始,真正 JSON 紧随 input_json_delta;
|
|
316
312
|
// 只有非空 input 才直接采用,避免累加成 `{}{...}`。
|
|
317
|
-
arguments: initialInput && Object.keys(initialInput).length > 0
|
|
318
|
-
? JSON.stringify(initialInput)
|
|
319
|
-
: '',
|
|
313
|
+
arguments: initialInput && Object.keys(initialInput).length > 0 ? JSON.stringify(initialInput) : '',
|
|
320
314
|
};
|
|
321
315
|
toolAcc.set(index, call);
|
|
322
316
|
if (call.name)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 递归剔除工具参数 schema 里的 `uniqueItems` 关键字。
|
|
3
|
+
*
|
|
4
|
+
* 背景:`uniqueItems` 是合法的 JSON Schema 关键字,OpenAI / qwen / 多数兼容后端都接受;
|
|
5
|
+
* 但 kimi-k3 经 dashscope compatible-mode 的模型服务层**不接受**它,收到即整请求 400:
|
|
6
|
+
* `<400> InternalError.Algo: An error occurred in model serving,
|
|
7
|
+
* error message is: [Invalid request parameters.]`
|
|
8
|
+
* 实测确定性 6/6:同一请求含 uniqueItems 必拒、去掉必过;而 format / const /
|
|
9
|
+
* patternProperties / $defs / minProperties / minItems 等关键字均被接受。
|
|
10
|
+
*
|
|
11
|
+
* 在 agent 侧的表现极具迷惑性——"干着干着突然每一步都 400、一把就结束":
|
|
12
|
+
* 工具路由(add_tool_groups / select_tool_groups)的 schema 一旦带上 uniqueItems,
|
|
13
|
+
* 该 turn 路由出的工具子集每步都会重发同一份毒 schema,于是每步都被拒;
|
|
14
|
+
* 换成 qwen3.8-max 等容忍 uniqueItems 的模型又立刻恢复正常。与 history 内容、
|
|
15
|
+
* 上下文长度、tool_call 配对**全部无关**(仅 system+user 两条消息 + 这一个工具即必拒)。
|
|
16
|
+
*
|
|
17
|
+
* 放在 transport 边界而非只修构造点:MCP / 外部注册工具、续接会话里可能已存着带
|
|
18
|
+
* uniqueItems 的 schema,只修构造点无法自愈。无需改写时返回**原数组引用**——
|
|
19
|
+
* 工具 schema 计入前缀缓存,逐字节稳定才能命中;每次新建对象会击穿缓存。
|
|
20
|
+
*/
|
|
21
|
+
export function sanitizeToolSchemas(tools) {
|
|
22
|
+
let sawUnsupported = false;
|
|
23
|
+
const strip = (value) => {
|
|
24
|
+
if (Array.isArray(value))
|
|
25
|
+
return value.map(strip);
|
|
26
|
+
if (value && typeof value === 'object') {
|
|
27
|
+
const src = value;
|
|
28
|
+
const out = {};
|
|
29
|
+
for (const [key, child] of Object.entries(src)) {
|
|
30
|
+
if (key === 'uniqueItems') {
|
|
31
|
+
sawUnsupported = true;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
out[key] = strip(child);
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
return value;
|
|
39
|
+
};
|
|
40
|
+
const next = tools.map((tool) => ({
|
|
41
|
+
...tool,
|
|
42
|
+
function: {
|
|
43
|
+
...tool.function,
|
|
44
|
+
parameters: strip(tool.function.parameters),
|
|
45
|
+
},
|
|
46
|
+
}));
|
|
47
|
+
return sawUnsupported ? next : tools;
|
|
48
|
+
}
|