micro-models-agent 0.63.3 → 1.5.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/CHANGELOG.md +258 -1
- package/dist/cli/cache-line.js +30 -0
- package/dist/cli/command-suggest.js +38 -0
- package/dist/cli/commands.js +285 -60
- package/dist/cli/completer.js +16 -16
- package/dist/cli/json-payload.js +32 -0
- package/dist/cli/main.js +165 -77
- package/dist/cli/plugin-commands.js +5 -4
- package/dist/cli/relaunch.js +37 -0
- package/dist/cli/repl-commands.js +441 -307
- package/dist/cli/repl.js +360 -83
- package/dist/cli/run-result.js +12 -6
- package/dist/cli/security-commands.js +64 -60
- package/dist/cli/setup-order.js +57 -0
- package/dist/cli/setup-prompt.js +49 -0
- package/dist/cli/setup.js +52 -48
- package/dist/config/budget.js +48 -0
- package/dist/config/config.js +132 -70
- package/dist/config/defaults.js +37 -11
- package/dist/config/domains.js +9 -50
- package/dist/config/utils.js +56 -0
- package/dist/core/agent/audit-gate.js +49 -0
- package/dist/core/agent/compaction.js +89 -0
- package/dist/core/agent/constants.js +61 -0
- package/dist/core/agent/context-renderer.js +40 -0
- package/dist/core/agent/hallucination-gate.js +87 -0
- package/dist/core/agent/loop-state.js +53 -0
- package/dist/core/agent/prefix-monitor.js +101 -0
- package/dist/core/agent/reasoning-resolver.js +56 -0
- package/dist/core/agent/token-tracker.js +96 -0
- package/dist/core/agent/tool-batch.js +237 -0
- package/dist/core/agent/tool-output.js +62 -0
- package/dist/core/agent-moe.js +214 -69
- package/dist/core/agent.js +506 -546
- package/dist/core/bootstrap.js +297 -98
- package/dist/core/crash-handler.js +2 -1
- package/dist/core/prompt-builder.js +3 -0
- package/dist/core/prompt-overflow.js +307 -0
- package/dist/core/session-logger.js +34 -2
- package/dist/i18n/en.json +40 -5
- package/dist/i18n/ru.json +40 -5
- package/dist/index.js +5 -1
- package/dist/llm/cache-usage.js +76 -0
- package/dist/llm/image-utils.js +20 -16
- package/dist/llm/llm-errors.js +41 -0
- package/dist/llm/model-loader.js +30 -0
- package/dist/llm/openai-compat.js +287 -101
- package/dist/llm/orchestrator.js +140 -68
- package/dist/llm/provider-budget.js +68 -0
- package/dist/llm/provider.js +0 -1
- package/dist/llm/stream-state.js +26 -0
- package/dist/llm/token-counter.js +28 -0
- package/dist/logger/app-logger.js +12 -15
- package/dist/main.js +3311 -1192
- package/dist/migration/detect.js +3 -1
- package/dist/modules/browser/actions.js +0 -3
- package/dist/modules/browser/bridge-client.js +2 -0
- package/dist/modules/browser/driver.js +46 -4
- package/dist/modules/certification/cli.js +85 -42
- package/dist/modules/certification/loader.js +15 -1
- package/dist/modules/certification/manifest.js +126 -15
- package/dist/modules/certification/runner.js +4 -26
- package/dist/modules/certification/scenarios.js +184 -5
- package/dist/modules/certification/syntax-scenarios.js +51 -0
- package/dist/modules/context/chunk-query.js +25 -5
- package/dist/modules/context/fact-extractor.js +6 -2
- package/dist/modules/context/manager.js +23 -7
- package/dist/modules/execution/audit-runners.js +7 -1
- package/dist/modules/execution/auditor.js +3 -3
- package/dist/modules/execution/execution-plugin.js +22 -15
- package/dist/modules/execution/input-from.js +46 -0
- package/dist/modules/execution/module.js +107 -18
- package/dist/modules/execution/moe-executor.js +166 -54
- package/dist/modules/execution/plan-actions.js +524 -0
- package/dist/modules/execution/plan-steps.js +23 -0
- package/dist/modules/execution/plan-store.js +15 -3
- package/dist/modules/execution/plan-tool.js +6 -488
- package/dist/modules/execution/plan-validator.js +24 -0
- package/dist/modules/execution/stuck-detector.js +3 -18
- package/dist/modules/execution/tracker.js +14 -5
- package/dist/modules/execution/transient-error.js +30 -0
- package/dist/modules/execution/verifier.js +94 -7
- package/dist/modules/execution/windows-commands.js +11 -0
- package/dist/modules/hallucination/confidence.js +36 -23
- package/dist/modules/hallucination/consistency.js +3 -0
- package/dist/modules/hallucination/detector.js +8 -3
- package/dist/modules/hallucination/factual.js +26 -7
- package/dist/modules/hallucination/llm-judge.js +12 -2
- package/dist/modules/indexer/map-command.js +35 -0
- package/dist/modules/indexer/map-select.js +87 -0
- package/dist/modules/indexer/module.js +34 -22
- package/dist/modules/indexer/symbols.js +189 -0
- package/dist/modules/indexer/walker.js +96 -42
- package/dist/modules/lsp/check-tool.js +2 -1
- package/dist/modules/lsp/client.js +49 -32
- package/dist/modules/lsp/config.js +55 -2
- package/dist/modules/lsp/module.js +38 -5
- package/dist/modules/lsp/probe.js +4 -3
- package/dist/modules/lsp/project-root.js +41 -1
- package/dist/modules/lsp/startup-check.js +12 -4
- package/dist/modules/mcp/client.js +153 -104
- package/dist/modules/mcp/module.js +165 -41
- package/dist/modules/memory/module.js +4 -3
- package/dist/modules/plugins/builtin/lint-on-write.js +36 -6
- package/dist/modules/plugins/manager.js +47 -84
- package/dist/modules/pricing/index.js +17 -7
- package/dist/modules/pricing/prices.js +30 -12
- package/dist/modules/processes/index.js +1 -0
- package/dist/modules/processes/kill-tree.js +56 -0
- package/dist/modules/processes/registry.js +2 -54
- package/dist/modules/providers/cache.js +23 -0
- package/dist/modules/providers/factory.js +28 -0
- package/dist/modules/providers/fallback.js +7 -5
- package/dist/modules/providers/health.js +2 -1
- package/dist/modules/providers/index.js +1 -0
- package/dist/modules/providers/manager.js +17 -2
- package/dist/modules/providers/presets.js +79 -6
- package/dist/modules/reasoning/policy.js +40 -0
- package/dist/modules/reasoning/probe.js +111 -0
- package/dist/modules/security/audit-notifier.js +42 -27
- package/dist/modules/security/command-validator.js +25 -20
- package/dist/modules/security/encryption.js +6 -12
- package/dist/modules/security/network-validator.js +76 -5
- package/dist/modules/security/path-validator.js +77 -34
- package/dist/modules/security/rate-limiter.js +11 -0
- package/dist/modules/security/security-policies.js +1 -1
- package/dist/modules/security/session-encryption.js +13 -2
- package/dist/modules/security/session-isolation.js +2 -9
- package/dist/modules/session/manager.js +11 -0
- package/dist/modules/session/module.js +11 -3
- package/dist/modules/session/store.js +41 -5
- package/dist/modules/skills/loader.js +7 -1
- package/dist/modules/skills/module.js +2 -1
- package/dist/modules/updater/changelog-reader.js +94 -0
- package/dist/modules/updater/dev-detect.js +17 -0
- package/dist/modules/updater/index.js +1 -0
- package/dist/modules/updater/module.js +14 -3
- package/dist/output/bus.js +32 -0
- package/dist/output/channel.js +233 -0
- package/dist/output/format.js +14 -0
- package/dist/output/index.js +7 -0
- package/dist/output/json-sink.js +22 -0
- package/dist/output/machine.js +8 -0
- package/dist/output/session-sink.js +27 -0
- package/dist/output/types.js +1 -0
- package/dist/tools/approve.js +6 -2
- package/dist/tools/attach-image.js +11 -11
- package/dist/tools/auto-fixer.js +198 -0
- package/dist/tools/bash.js +142 -89
- package/dist/tools/chunk-query.js +10 -6
- package/dist/tools/download-file.js +1 -1
- package/dist/tools/edit-file.js +20 -2
- package/dist/tools/executor.js +54 -9
- package/dist/tools/glob-tool.js +7 -0
- package/dist/tools/grep-tool.js +15 -1
- package/dist/tools/index.js +3 -1
- package/dist/tools/list-dir.js +3 -1
- package/dist/tools/load-skill.js +2 -1
- package/dist/tools/mcp-call.js +1 -1
- package/dist/tools/move-file.js +5 -4
- package/dist/tools/path-utils.js +7 -0
- package/dist/tools/pipeline-run.js +1 -1
- package/dist/tools/prompt-io.js +28 -0
- package/dist/tools/question.js +12 -12
- package/dist/tools/scope-request.js +91 -0
- package/dist/tools/session-info.js +44 -0
- package/dist/tools/set-thinking.js +71 -0
- package/dist/tools/subagent.js +50 -9
- package/dist/tools/syntax-validator.js +177 -0
- package/dist/tools/user-input.js +16 -9
- package/dist/tools/write-file.js +17 -1
- package/dist/ui/diff.js +10 -0
- package/dist/ui/line-editor.js +179 -26
- package/dist/ui/line-math.js +20 -3
- package/dist/ui/md-formatter.js +100 -10
- package/dist/ui/output.js +5 -4
- package/dist/ui/plan-view.js +2 -7
- package/dist/ui/renderer.js +89 -85
- package/dist/ui/spinner.js +14 -4
- package/dist/utils/error.js +4 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/retry.js +17 -0
- package/dist/utils/sleep.js +23 -0
- package/dist/utils/truncate.js +9 -0
- package/package.json +1 -1
package/dist/i18n/ru.json
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
"file.is_directory": "Это каталог, используйте rmdir: {path}",
|
|
12
12
|
"file.replaced_in": "Заменено в {path}",
|
|
13
13
|
"file.string_not_found": "Строка не найдена в файле:\n{str}\n\nИспользуй read_file для {path}, чтобы увидеть текущее содержимое файла перед редактированием — искомая строка может отличаться (пробелы, переводы строк) или уже была заменена.",
|
|
14
|
+
"file.edit_args_invalid": "edit_file требует строковые аргументы \"old\" и \"new\". Получено: old={oldType}, new={newType}.",
|
|
15
|
+
"file.read_failed": "Не удалось прочитать {path}: {error}",
|
|
16
|
+
"file.write_failed": "Не удалось записать {path}: {error}",
|
|
17
|
+
"file.protected_path_ask": "Защищённый путь \"{path}\" (совпадает с {pattern}). НЕ изменяй его. Спроси у пользователя явного подтверждения и дождись ответа — не обходи это ограничение.",
|
|
14
18
|
"file.moved": "Перемещён {from} → {to}",
|
|
15
19
|
"file.not_found_short": "Не найдено: {path}",
|
|
16
20
|
"file.empty": "(пусто)",
|
|
@@ -46,6 +50,8 @@
|
|
|
46
50
|
"error.llm_output_truncated": "Ответ упёрся в лимит токенов генерации ({tokens}) и был обрезан — этот ответ неполный. Увеличьте \"maxCompletionTokens\" в конфиге, чтобы разрешить длинные ответы",
|
|
47
51
|
"error.llm_provider_stream_error": "Провайдер вернул ошибку посреди стрима: {error}",
|
|
48
52
|
"error.llm_timeout": "Время запроса LLM истекло ({timeout}мс)",
|
|
53
|
+
"error.context_log_init": "Context log включён, но не удалось инициализировать: {error}. Diff контекста писаться не будет.",
|
|
54
|
+
"error.provider_build": "Не удалось собрать провайдера \"{name}\": {error}",
|
|
49
55
|
"env.runtime_node": "Запущено под Node (v{version}) — вставка изображений из буфера и LSP на Windows работают урезанно. Установите Bun (https://bun.sh) для полного функционала.",
|
|
50
56
|
"env.runtime_old": "Версия рантайма {version} ниже требуемой engines {engine}.",
|
|
51
57
|
"env.tool_missing": "Инструмент не найден в PATH: {tool}",
|
|
@@ -91,6 +97,8 @@
|
|
|
91
97
|
"tool.failed": "Инструмент {name} упал: {error}",
|
|
92
98
|
"tool.unknown": "Неизвестный инструмент: {name}",
|
|
93
99
|
"tool.blocked": "Заблокировано плагином: {plugin}",
|
|
100
|
+
"tool.ui.security_blocked": "Заблокировано политикой безопасности",
|
|
101
|
+
"tool.ui.protected_path": "Защищённый путь — нужно подтверждение",
|
|
94
102
|
"tool.blocked_reason": "Заблокировано плагином: {plugin}. Причина: {reason}",
|
|
95
103
|
"tool.using": "[{label}]",
|
|
96
104
|
"tool.friendly.write_file": "Запись файла",
|
|
@@ -334,6 +342,7 @@
|
|
|
334
342
|
"cli.show_details": "Показать детали сессии",
|
|
335
343
|
"cli.delete_session": "Удалить сессию",
|
|
336
344
|
"cli.first_run": "Первый запуск. Запускаем мастер настройки...",
|
|
345
|
+
"cli.setup_saved_restart": "Настройки сохранены. Перезапуск с новой конфигурацией...",
|
|
337
346
|
"cli.unknown_cmd": "Неизвестная команда: {name}.",
|
|
338
347
|
"cli.unknown_command": "Неизвестная команда \"{input}\". Возможно, вы имели в виду \"{suggestion}\"?",
|
|
339
348
|
"cli.help_hint": "Введите /help для списка команд.",
|
|
@@ -344,6 +353,8 @@
|
|
|
344
353
|
"cli.exit_on_complete": "Завершить сразу после выполнения задачи; интерактивные тулзы (question/approve) не блокируют stdin, а возвращают ошибку",
|
|
345
354
|
"cli.reasoning_level": "Установить уровень рассуждений (auto|none|low|medium|high|max)",
|
|
346
355
|
"cli.json": "Вывести результат в формате JSON (режим однократного запуска)",
|
|
356
|
+
"cli.context_log": "Писать весь контекст LLM в <session>/context.diff в git-подобном diff-формате (первый снимок — полный, далее изменения +/-)",
|
|
357
|
+
"cli.verbose": "Показывать полный вывод чата (тела тулов, списки); по умолчанию — кратко",
|
|
347
358
|
"cli.security.description": "Управление настройками безопасности",
|
|
348
359
|
"cli.security.status": "Показать текущую конфигурацию безопасности",
|
|
349
360
|
"cli.security.policies": "Список доступных политик безопасности",
|
|
@@ -404,6 +415,11 @@
|
|
|
404
415
|
"repl.reasoning_usage": "Использование: /reasoning [auto|none|low|medium|high|max]",
|
|
405
416
|
"repl.reasoning_level_set": "Уровень рассуждений установлен: {level}",
|
|
406
417
|
"repl.reasoning_invalid_level": "Неверный уровень '{level}'. Допустимые: {valid}",
|
|
418
|
+
"repl.verbose": "Подробность вывода: quiet, normal или verbose",
|
|
419
|
+
"repl.verbose_usage": "Использование: /verbose [quiet|normal|verbose]",
|
|
420
|
+
"repl.verbose_set": "Подробность вывода: {level}",
|
|
421
|
+
"repl.verbose_invalid_level": "Неверный уровень '{level}'. Допустимые: {valid}",
|
|
422
|
+
"repl.last_action_none": "Нет недавнего действия для показа.",
|
|
407
423
|
"repl.status": "Показать статус агента",
|
|
408
424
|
"repl.status_usage": "Использование: /status",
|
|
409
425
|
"repl.plugins": "Список загруженных плагинов",
|
|
@@ -435,6 +451,8 @@
|
|
|
435
451
|
"repl.skill_usage": "Использование: /skill [list|loaded|load|unload|search]",
|
|
436
452
|
"repl.agent": "Агент: ",
|
|
437
453
|
"repl.you": "Вы: ",
|
|
454
|
+
"repl.you_reasoning": "Вы [{level}]: ",
|
|
455
|
+
"repl.you_reasoning_cont": "Вы [{level}]… ",
|
|
438
456
|
"repl.interrupt": "Прервано (Esc)",
|
|
439
457
|
"repl.title": "MMA REPL v{version}",
|
|
440
458
|
"repl.model": "Модель:",
|
|
@@ -507,6 +525,7 @@
|
|
|
507
525
|
"setup.title": "\n Мастер настройки MMA v2\n",
|
|
508
526
|
"setup.select_provider": "\n Выберите тип провайдера:",
|
|
509
527
|
"setup.select_provider_num": "\n Выберите провайдер (1-{max})",
|
|
528
|
+
"setup.select_language_num": "\n Выберите язык (1-{max})",
|
|
510
529
|
"setup.scanning": " Сканирование локальных LLM-серверов...",
|
|
511
530
|
"setup.found_servers": " Найдено серверов: {count}",
|
|
512
531
|
"setup.no_servers": " Локальные серверы не найдены. Введите URL вручную.",
|
|
@@ -531,8 +550,6 @@
|
|
|
531
550
|
"setup.scanning_spinner": "Сканирование локальных LLM-серверов…",
|
|
532
551
|
"setup.fetching_spinner": "Загрузка списка моделей…",
|
|
533
552
|
"setup.testing_spinner": "Проверка чата с \"{model}\"…",
|
|
534
|
-
"setup.summary_setting": "Параметр",
|
|
535
|
-
"setup.summary_value": "Значение",
|
|
536
553
|
"setup.security_header": "\n --- Безопасность ---",
|
|
537
554
|
"setup.security_status_off": " Безопасность: ВЫКЛ (по умолчанию — все команды разрешены)",
|
|
538
555
|
"setup.security_status_on": " Безопасность: ВКЛ (по умолчанию — политика balanced)",
|
|
@@ -576,6 +593,9 @@
|
|
|
576
593
|
"exec.audit_incomplete": "❗ Финальная проверка не пройдена: {summary}. Задача НЕ завершена. Незакрытые шаги: {steps}. Устрани одним путём: (a) если результат шага уже существует на диске — закрой шаг (plan update step=N status=done); (b) если шаг больше не нужен — status=skipped; (c) если план разошёлся с реальностью (другие имена файлов, сменился подход) — сделай re-plan. Не повторяй plan update без изменений.",
|
|
577
594
|
"exec.mass_edit_warning": "⚠️ План затрагивает {count} файлов — проверьте полный список перед продолжением.",
|
|
578
595
|
"exec.escalation": "\n\n⚠️ Агент застрял на шаге {stepId} ({description}). Эскалация к пользователю — пожалуйста, подскажите как действовать.",
|
|
596
|
+
"exec.escalation_directive": "Ты застрял уже несколько попыток. Перестань повторять одно и то же и выбери ОДНО: (1) смени подход принципиально, (2) найди точный текст ошибки через web_search (или инструмент поиска ошибок), (3) задай пользователю короткий уточняющий вопрос, (4) если шаг невыполним — plan update step=<n> status=skipped с заметкой (или re-plan). Кратко объясни выбор.",
|
|
597
|
+
"exec.test_churn_nudge": "Ты несколько раз подряд правил тест/спек-файл \"{file}\" и не изменил ни строчки production-кода. Если тесты падают — исправляй КОД ПОД ТЕСТОМ (а не тест), если только сам тест не ошибочен — тогда объясни, почему. Если задумано test-first, теперь напиши реализацию.",
|
|
598
|
+
"exec.script_workaround_nudge": "Ограничение безопасности уже заблокировало одну из твоих команд. Написание shell-скрипта (.bat/.cmd/.sh/.ps1), чтобы выполнить её иначе, НЕ снимает ограничение и обычно просто падает. Вместо этого: используй write_file для вывода в файл, запускай по одной простой команде за вызов, передавай \"workdir\" вместо \"cd\" или спроси пользователя.",
|
|
579
599
|
"exec.hints": "\n[Подсказки]\n{hints}",
|
|
580
600
|
"exec.file_rewrite_warning": "⚠️ Файл {file} был перезаписан {count} раз. Попробуйте другой подход — текущая стратегия исправлений не работает.",
|
|
581
601
|
"exec.forbidden_cmd": "ПРЕКРАТИ использовать \"{cmd}\" через bash — это не команда Windows cmd.exe, и она уже неоднократно падала в этой сессии. Используй предназначенный тул: grep → тул grep, ls/dir → list_dir, find → glob, rm → delete_file, sed → edit_file, touch → write_file, which → `where`, cp/mv → move_file, diff → read_file. Больше не вызывай bash для этого.",
|
|
@@ -583,6 +603,7 @@
|
|
|
583
603
|
"exec.error_search_failed": "Поиск в интернете для \"{query}\" ничего не дал.",
|
|
584
604
|
"exec.error_search_no_query": "Текст ошибки незначимый — поиск в интернете пропущен.",
|
|
585
605
|
"exec.npm_exec_hint": "\"could not determine executable to run\" — у пакета/скрипта нет \"bin\". Используй \"npm run <script>\" (скрипт должен быть в package.json) или \"bunx <pkg>\" для пакета с объявленным bin.",
|
|
606
|
+
"exec.interactive_hint": "команде нужен интерактивный ввод, но у шелла нет TTY (запрос отменён). Запусти её неинтерактивно — передай все нужные флаги/аргументы (например, `bun create vite <name> --template react-ts` вместо голого интерактивного скаффолда).",
|
|
586
607
|
"exec.hidden_tool_hint": "\"{tool}\" — не команда оболочки, это инструмент MMA, который сейчас скрыт. Вызови тул enable_tools с tags [\"shell\"], чтобы включить его; он станет доступен на следующей итерации.",
|
|
587
608
|
"exec.task_reminder": "Задача: {task}. Продолжай работу — не повторяй неудачные действия.",
|
|
588
609
|
"hall.max_retries_exhausted": "Модель вернула пустой или недостаточный ответ после нескольких попыток",
|
|
@@ -627,10 +648,18 @@
|
|
|
627
648
|
"migration.dir_bak": "- .mma/ → .mma.bak/ ({count} файлов)",
|
|
628
649
|
"migration.migrated": "Мигрировано:",
|
|
629
650
|
"migration.not_needed": "Миграция не требуется",
|
|
630
|
-
"ui.error_prefix": "
|
|
651
|
+
"ui.error_prefix": "✗ ",
|
|
631
652
|
"ui.success_prefix": "✓ ",
|
|
632
653
|
"ui.warning_prefix": "⚠ ",
|
|
633
654
|
"ui.thinking": "Думаю…",
|
|
655
|
+
"ui.thinking_label": "размышляю",
|
|
656
|
+
"ui.thinking_label_1": "размышляю",
|
|
657
|
+
"ui.thinking_label_2": "обдумываю",
|
|
658
|
+
"ui.thinking_label_3": "прикидываю",
|
|
659
|
+
"ui.action_fallback": "Действие",
|
|
660
|
+
"ui.actions_summary": "{count} действий",
|
|
661
|
+
"ui.plan_update": "шаг {step} → {status}",
|
|
662
|
+
"ui.todo_action": "{action} · {count}",
|
|
634
663
|
"ui.tool_running": "{tool}…",
|
|
635
664
|
"ui.step_context": "шаг {id}: {desc}",
|
|
636
665
|
"indexer.map_header": "Карта проекта",
|
|
@@ -735,6 +764,7 @@
|
|
|
735
764
|
"cli.usage_account": "Аккаунт: куплено {credits} · израсходовано {used}",
|
|
736
765
|
"cli.usage_empty": "Провайдер не вернул данных о балансе.",
|
|
737
766
|
"repl.ctrl_c_interrupt": "\n[Ctrl+C] Остановка агента... (ещё раз — принудительно)",
|
|
767
|
+
"repl.force_exit": "\nПринудительный выход — фоновая очистка может быть неполной.",
|
|
738
768
|
"exec.stop_directive": "STOP. Step {stepId} (\"{description}\") took {iterations} iterations with no progress. DO NOT continue this step. Immediately call: plan update step={stepId} status=done (if code works despite warnings) OR plan update step={stepId} status=skipped note=\"reason\". Do NOT make any other tool calls before updating the plan.",
|
|
739
769
|
"exec.test_runner_fail": "[test-runner] {framework}: {failed} test(s) FAILING, {passed} passing — do NOT mark verification steps as done while tests fail. Investigate the failures, fix the code, then re-run the tests.",
|
|
740
770
|
"exec.test_runner_pass": "[test-runner] {framework}: all {passed} test(s) passing.",
|
|
@@ -753,6 +783,11 @@
|
|
|
753
783
|
"moe.execution_complete": "Выполнение завершено: {succeeded}/{total} успешно",
|
|
754
784
|
"moe.cycles_exhausted": "Достигнут лимит re-plan циклов ({max}) — возвращаю частичные результаты",
|
|
755
785
|
"moe.partial_result": "Частичный результат",
|
|
786
|
+
"moe.planning": "🤖 Планирую в режиме MoE...\n",
|
|
787
|
+
"moe.plan_fallback": "⚠️ Валидация плана не прошла. Возврат к одиночному режиму.\n",
|
|
788
|
+
"moe.plan_autofixed": "🔧 Автоисправлено проблем плана: {count}.\n",
|
|
789
|
+
"moe.plan_failed": "План MoE не построен: {error} — возврат к одиночному режиму",
|
|
790
|
+
"moe.no_orchestrator": "MoE включён, но orchestrator.model не задан — возврат к одиночному режиму. Укажите orchestrator.model для активации MoE.",
|
|
756
791
|
"moe.scope_approved": "🔓 Scope расширен для \"{subtask}\": {files}",
|
|
757
792
|
"moe.scope_rejected": "⛔ Запрос scope отклонён для \"{subtask}\"",
|
|
758
793
|
"prompt.overflow.compressing": "Переполнение системного промпта: сжимаю {count} блок(ов) перед первым запуском — на локальной модели это может занять время.",
|
|
@@ -762,9 +797,9 @@
|
|
|
762
797
|
"prompt.overflow.hint_needed": "промпту нужно ~{needed} токенов системного бюджета (сейчас: {window} × {fraction} = {budget})",
|
|
763
798
|
"prompt.overflow.hint_window": "подними contextWindow минимум до {required} (стандартный размер {recommended}) — {how}",
|
|
764
799
|
"prompt.overflow.hint_fraction": "или оставь окно и подними contextBudget.systemPrompt до ~{fraction} (выполни: mma context --system {fraction})",
|
|
765
|
-
"prompt.overflow.exceeded": "Промпт переполнен:
|
|
800
|
+
"prompt.overflow.exceeded": "Промпт переполнен: системному промпту нужно ~{needed} токенов (бюджет {budget} токенов); \"{label}\" ({original} токенов) было {mode} до {resolved} токенов. Чтобы включить всё полностью, {hint}.",
|
|
766
801
|
"prompt.overflow.failed": "Не удалось разрешить переполнение промпта: {error} — слишком большие блоки будут отброшены.",
|
|
767
|
-
"prompt.overflow.startup": "Проверка при старте: {
|
|
802
|
+
"prompt.overflow.startup": "Проверка при старте: системному промпту нужно ~{needed} токенов (бюджет: {budget} токенов); {block} ({original} токенов) будет суммаризован/обрезан перед первым запуском. Чтобы включить всё полностью, {hint}.",
|
|
768
803
|
"tool.session_info.no_active": "Нет активной сессии",
|
|
769
804
|
"tool.session_info.result": "Сессия: \"{name}\" ({id})\nМодель: {model}\nПровайдер: {provider}\nКонтекстное окно: {contextWindow} токенов\nСообщений: {messages}\nСоздана: {createdAt}\nОбновлена: {updatedAt}",
|
|
770
805
|
"tool.session_info.context": "Использовано контекста: {used} / {budget} токенов ({percent}%)",
|
package/dist/index.js
CHANGED
|
@@ -7,16 +7,20 @@ export { MigrationDetector, BackupManager } from "./migration/index";
|
|
|
7
7
|
import { MigrationDetector } from "./migration/detect";
|
|
8
8
|
import { BackupManager } from "./migration/backup";
|
|
9
9
|
import { t } from "./i18n/index";
|
|
10
|
+
import { defaultOutputBus, getDefaultChannel } from "./output";
|
|
10
11
|
import { homedir } from "os";
|
|
11
12
|
import { join } from "path";
|
|
12
13
|
export function checkMigration(configDir) {
|
|
13
14
|
const dir = configDir || join(homedir(), ".mma");
|
|
14
15
|
const detector = new MigrationDetector(dir);
|
|
15
16
|
if (detector.needsMigration()) {
|
|
17
|
+
// Ensure a terminal subscriber exists before emitting to the bus; library
|
|
18
|
+
// consumers have no other eager channel creation.
|
|
19
|
+
getDefaultChannel();
|
|
16
20
|
const backup = new BackupManager(dir);
|
|
17
21
|
backup.backupConfig();
|
|
18
22
|
backup.backupAll();
|
|
19
23
|
const summary = backup.getBackupSummary();
|
|
20
|
-
|
|
24
|
+
defaultOutputBus.log("info", "mma", t("migration.summary", { summary }));
|
|
21
25
|
}
|
|
22
26
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** Безопасно приводит значение к конечному числу; иначе undefined. */
|
|
2
|
+
function num(value) {
|
|
3
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
4
|
+
}
|
|
5
|
+
/** Объект ли это (для защиты от null/строк в ответе). */
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === "object" && value !== null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Разбирает usage-объект провайдера в нормализованный `CacheUsage` согласно
|
|
11
|
+
* формату отчёта. Возвращает undefined, когда провайдер не сообщает о кеше —
|
|
12
|
+
* вызывающий не должен выдавать отсутствие данных за «cache miss».
|
|
13
|
+
*
|
|
14
|
+
* `estimatedPromptTokens` нужен только для формата `ollama`, который не
|
|
15
|
+
* отдаёт cache-полей: кешированное вычисляется как разница оценки и
|
|
16
|
+
* `prompt_eval_count`.
|
|
17
|
+
*/
|
|
18
|
+
export function parseCacheUsage(usage, format, estimatedPromptTokens) {
|
|
19
|
+
if (!isRecord(usage))
|
|
20
|
+
return undefined;
|
|
21
|
+
switch (format) {
|
|
22
|
+
case "openai": {
|
|
23
|
+
const details = usage.prompt_tokens_details;
|
|
24
|
+
if (!isRecord(details))
|
|
25
|
+
return undefined;
|
|
26
|
+
const cached = num(details.cached_tokens);
|
|
27
|
+
if (cached === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
const prompt = num(usage.prompt_tokens) ?? cached;
|
|
30
|
+
const write = num(details.cache_write_tokens) ?? 0;
|
|
31
|
+
return {
|
|
32
|
+
cachedTokens: cached,
|
|
33
|
+
cacheWriteTokens: write,
|
|
34
|
+
uncachedTokens: Math.max(0, prompt - cached),
|
|
35
|
+
source: "api",
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
case "deepseek": {
|
|
39
|
+
const hit = num(usage.prompt_cache_hit_tokens);
|
|
40
|
+
const miss = num(usage.prompt_cache_miss_tokens);
|
|
41
|
+
if (hit === undefined && miss === undefined)
|
|
42
|
+
return undefined;
|
|
43
|
+
return {
|
|
44
|
+
cachedTokens: hit ?? 0,
|
|
45
|
+
cacheWriteTokens: 0,
|
|
46
|
+
uncachedTokens: miss ?? 0,
|
|
47
|
+
source: "api",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
case "anthropic": {
|
|
51
|
+
const read = num(usage.cache_read_input_tokens);
|
|
52
|
+
const creation = num(usage.cache_creation_input_tokens);
|
|
53
|
+
if (read === undefined && creation === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
return {
|
|
56
|
+
cachedTokens: read ?? 0,
|
|
57
|
+
cacheWriteTokens: creation ?? 0,
|
|
58
|
+
uncachedTokens: num(usage.input_tokens) ?? 0,
|
|
59
|
+
source: "api",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
case "ollama": {
|
|
63
|
+
const evaluated = num(usage.prompt_eval_count);
|
|
64
|
+
if (evaluated === undefined || estimatedPromptTokens === undefined)
|
|
65
|
+
return undefined;
|
|
66
|
+
return {
|
|
67
|
+
cachedTokens: Math.max(0, estimatedPromptTokens - evaluated),
|
|
68
|
+
cacheWriteTokens: 0,
|
|
69
|
+
uncachedTokens: evaluated,
|
|
70
|
+
source: "derived",
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
default:
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
package/dist/llm/image-utils.js
CHANGED
|
@@ -41,27 +41,31 @@ async function readClipboardFallback() {
|
|
|
41
41
|
const { execSync } = await import("child_process");
|
|
42
42
|
const { readFileSync, unlinkSync } = await import("fs");
|
|
43
43
|
const { join } = await import("path");
|
|
44
|
+
if (platform() !== "linux")
|
|
45
|
+
return null; // macOS/Windows use Bun.Image
|
|
44
46
|
const tmpPath = join(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
else {
|
|
52
|
-
return null; // macOS/Windows should use Bun.Image
|
|
53
|
-
}
|
|
54
|
-
const buf = readFileSync(tmpPath);
|
|
55
|
-
unlinkSync(tmpPath);
|
|
56
|
-
return buf.length > 0 ? buf : null;
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
47
|
+
// Try Wayland (wl-paste) first, then X11 (xclip)
|
|
48
|
+
const commands = [
|
|
49
|
+
`wl-paste --type image/png > "${tmpPath}" 2>/dev/null`,
|
|
50
|
+
`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`,
|
|
51
|
+
];
|
|
52
|
+
for (const cmd of commands) {
|
|
59
53
|
try {
|
|
54
|
+
execSync(cmd, { timeout: 5000 });
|
|
55
|
+
const buf = readFileSync(tmpPath);
|
|
60
56
|
unlinkSync(tmpPath);
|
|
57
|
+
if (buf.length > 0)
|
|
58
|
+
return buf;
|
|
61
59
|
}
|
|
62
|
-
catch {
|
|
63
|
-
|
|
60
|
+
catch {
|
|
61
|
+
// try next command
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
unlinkSync(tmpPath);
|
|
64
66
|
}
|
|
67
|
+
catch { }
|
|
68
|
+
return null;
|
|
65
69
|
}
|
|
66
70
|
/**
|
|
67
71
|
* Load an image from a file path, resize via Bun.Image, return as JPEG data URL.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Типизированные ошибки LLM-транспорта.
|
|
3
|
+
*
|
|
4
|
+
* Раньше свойства `recoverableLlm` / `llmTerminal` / `llmStatus` навешивались
|
|
5
|
+
* на обычные Error через `(err as any).xxx = ...` в 8 местах openai-compat.ts
|
|
6
|
+
* и читались структурно в agent.ts и providers/fallback.ts — утка вместо
|
|
7
|
+
* типа. Здесь — единый класс с явными флагами.
|
|
8
|
+
*
|
|
9
|
+
* Семантика флагов:
|
|
10
|
+
* - `terminal`: поток уже не может продолжать (ответ доставлен, соединение
|
|
11
|
+
* сломано, запрос доретриен) — на уровне стрима ретраить НЕЛЬЗЯ;
|
|
12
|
+
* - `recoverable`: причину стоит вернуть модели через агентный цикл
|
|
13
|
+
* (например, токен-лимит на середине tool_call) вместо смерти сессии;
|
|
14
|
+
* - `llmStatus`: HTTP-статус для решения о failover между провайдерами.
|
|
15
|
+
*
|
|
16
|
+
* Ошибка может нести одновременно terminal + recoverable (обрезанный
|
|
17
|
+
* tool_call: стрим не ретраим, но модель просим адаптироваться).
|
|
18
|
+
*/
|
|
19
|
+
export class LlmError extends Error {
|
|
20
|
+
/** Поток не может продолжать — на уровне стрима не ретраить. */
|
|
21
|
+
terminal;
|
|
22
|
+
/** Причину вернуть модели через агентный цикл. */
|
|
23
|
+
recoverable;
|
|
24
|
+
/** HTTP-статус (для failover), если известен. */
|
|
25
|
+
llmStatus;
|
|
26
|
+
constructor(message, options = {}) {
|
|
27
|
+
super(message);
|
|
28
|
+
this.name = "LlmError";
|
|
29
|
+
this.terminal = options.terminal ?? false;
|
|
30
|
+
this.recoverable = options.recoverable ?? false;
|
|
31
|
+
this.llmStatus = options.llmStatus;
|
|
32
|
+
}
|
|
33
|
+
markTerminal() {
|
|
34
|
+
this.terminal = true;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
markRecoverable() {
|
|
38
|
+
this.recoverable = true;
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
}
|
package/dist/llm/model-loader.js
CHANGED
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask LM Studio's native API which context length the model is currently
|
|
3
|
+
* loaded with. Prefers the running instance (`loaded_instances[].config.
|
|
4
|
+
* context_length`), falls back to the model's `max_context_length`. Returns
|
|
5
|
+
* null when the endpoint is unavailable (not LM Studio), the model is not
|
|
6
|
+
* found/loaded, or the request fails — the caller must degrade silently.
|
|
7
|
+
*/
|
|
8
|
+
export async function getLoadedContextLength(baseUrl, model, timeoutMs = 3000) {
|
|
9
|
+
const base = baseUrl.replace(/\/$/, "").replace(/\/v1\/?$/, "");
|
|
10
|
+
try {
|
|
11
|
+
const response = await fetch(`${base}/api/v1/models`, {
|
|
12
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
13
|
+
});
|
|
14
|
+
if (!response.ok)
|
|
15
|
+
return null;
|
|
16
|
+
const data = (await response.json());
|
|
17
|
+
const models = data.models || [];
|
|
18
|
+
const found = models.find((m) => m.key === model || m.name === model || model.includes(m.key));
|
|
19
|
+
if (!found)
|
|
20
|
+
return null;
|
|
21
|
+
const loadedInstance = (found.loaded_instances ?? [])[0];
|
|
22
|
+
const actual = loadedInstance?.config?.context_length ?? found.max_context_length;
|
|
23
|
+
if (typeof actual !== "number" || actual <= 0)
|
|
24
|
+
return null;
|
|
25
|
+
return { model: found.key ?? found.name ?? model, actual };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
1
31
|
export class ModelLoader {
|
|
2
32
|
baseUrl;
|
|
3
33
|
logger;
|