micro-models-agent 1.6.0 → 2.0.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 +49 -0
- package/dist/i18n/en.json +103 -10
- package/dist/i18n/ru.json +103 -10
- package/dist/main.js +1612 -403
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2312,6 +2312,7 @@ var init_defaults = __esm(() => {
|
|
|
2312
2312
|
description: "browser + file reading for visual tasks"
|
|
2313
2313
|
}
|
|
2314
2314
|
},
|
|
2315
|
+
modelCapabilities: {},
|
|
2315
2316
|
contextWindow: 32768,
|
|
2316
2317
|
contextBudget: {
|
|
2317
2318
|
systemPrompt: 0.1,
|
|
@@ -2803,6 +2804,10 @@ Fix the error and re-edit the file (a clean write clears the failure), or mark t
|
|
|
2803
2804
|
"cli.list_sessions": "List all sessions",
|
|
2804
2805
|
"cli.show_details": "Show session details",
|
|
2805
2806
|
"cli.delete_session": "Delete a session",
|
|
2807
|
+
"cli.export_session": "Export a session to a file (md, json, or jsonl)",
|
|
2808
|
+
"cli.export_format": "Output format: md|json|jsonl (default md)",
|
|
2809
|
+
"cli.export_out": "Output path ('-' for stdout)",
|
|
2810
|
+
"cli.export_no_redact": "Do not redact secrets",
|
|
2806
2811
|
"cli.first_run": "First run detected. Running setup wizard...",
|
|
2807
2812
|
"cli.first_run_oneshot": "No configuration found — running with defaults. Run `mma` (no arguments) once to set up the wizard.",
|
|
2808
2813
|
"cli.setup_saved_restart": "Settings saved. Restarting with the new configuration...",
|
|
@@ -2871,20 +2876,21 @@ Available commands:`,
|
|
|
2871
2876
|
"repl.exit_usage": "Usage: /exit",
|
|
2872
2877
|
"repl.clear": "Clear the screen",
|
|
2873
2878
|
"repl.clear_usage": "Usage: /clear",
|
|
2879
|
+
"repl.clear_hint": "Screen cleared. To start a fresh session and context: /new",
|
|
2874
2880
|
"repl.run": "Run a prompt through the agent",
|
|
2875
2881
|
"repl.run_usage": "Usage: /run <prompt>",
|
|
2876
|
-
"repl.config": "Show
|
|
2877
|
-
"repl.config_usage": "Usage: /config",
|
|
2878
|
-
"repl.reasoning": "
|
|
2879
|
-
"repl.reasoning_usage": "Usage: /reasoning [auto|none|low|medium|high|max]",
|
|
2882
|
+
"repl.config": "Show or change settings (get / set / reset)",
|
|
2883
|
+
"repl.config_usage": "Usage: /config [<key> [value]] | /config reset <key> | /config reset --all [--yes] | /config migrate",
|
|
2884
|
+
"repl.reasoning": "Show reasoning status, toggle display, or set effort level",
|
|
2885
|
+
"repl.reasoning_usage": "Usage: /reasoning [show|hide|level <auto|default|none|low|medium|high|max>]",
|
|
2880
2886
|
"repl.reasoning_level_set": "Reasoning level set to: {level}",
|
|
2881
2887
|
"repl.reasoning_invalid_level": "Invalid level '{level}'. Valid: {valid}",
|
|
2882
|
-
"repl.verbose": "Chat verbosity
|
|
2888
|
+
"repl.verbose": "Chat verbosity (quiet, normal, verbose)",
|
|
2883
2889
|
"repl.verbose_usage": "Usage: /verbose [quiet|normal|verbose]",
|
|
2884
2890
|
"repl.verbose_set": "Chat verbosity: {level}",
|
|
2885
2891
|
"repl.verbose_invalid_level": "Invalid level '{level}'. Valid: {valid}",
|
|
2886
2892
|
"repl.last_action_none": "No recent action to show.",
|
|
2887
|
-
"repl.status": "Show
|
|
2893
|
+
"repl.status": "Show a compact status line",
|
|
2888
2894
|
"repl.status_usage": "Usage: /status",
|
|
2889
2895
|
"repl.plugins": "List loaded plugins",
|
|
2890
2896
|
"repl.plugins_usage": "Usage: /plugins [--all]",
|
|
@@ -2924,11 +2930,13 @@ Available commands:`,
|
|
|
2924
2930
|
"repl.context": "Context:",
|
|
2925
2931
|
"repl.sysprompt_label": "System prompt:",
|
|
2926
2932
|
"repl.sysprompt_size": "{used} / {budget} tokens",
|
|
2927
|
-
"repl.sysprompt_desc": "
|
|
2933
|
+
"repl.sysprompt_desc": "System prompt size and blocks (use --full for the text)",
|
|
2934
|
+
"repl.sysprompt_usage": "Usage: /sysprompt [--full]",
|
|
2935
|
+
"repl.sysprompt_full_hint": "Full prompt text hidden — run /sysprompt --full to print it.",
|
|
2928
2936
|
"repl.sysprompt_tokens": "System prompt ({count} tokens):",
|
|
2929
2937
|
"repl.excluded_blocks": `
|
|
2930
2938
|
Excluded blocks: {count}`,
|
|
2931
|
-
"repl.context_usage": "Usage: /context [<size> | system <
|
|
2939
|
+
"repl.context_usage": "Usage: /context [<size, min 1024> | system <share> | reserve <share>] (share 0.05–0.9 or e.g. 10%; system+reserve ≤ 0.95)",
|
|
2932
2940
|
"repl.msgs": "msgs",
|
|
2933
2941
|
"repl.max_iters": "Max iters:",
|
|
2934
2942
|
"repl.stuck_thresh": "Stuck thresh:",
|
|
@@ -2972,13 +2980,105 @@ Excluded blocks: {count}`,
|
|
|
2972
2980
|
"repl.provider_list": "List configured providers or hot-swap the active one",
|
|
2973
2981
|
"repl.provider_current": "Current provider",
|
|
2974
2982
|
"repl.provider_set": "Provider set to: {name}",
|
|
2975
|
-
"repl.provider_usage":
|
|
2983
|
+
"repl.provider_usage": `Usage: /provider list | /provider use <name> | /provider add <name> [flags]
|
|
2984
|
+
--url <url> base API URL (fallback: known presets)
|
|
2985
|
+
--key <key> API key
|
|
2986
|
+
--priority <n> fallback order; lower = tried first
|
|
2987
|
+
--context-window <n> per-provider context window (tokens)
|
|
2988
|
+
--rpm <n> max requests/minute (default 60)
|
|
2989
|
+
--parallel <n> max parallel tasks (default 1)`,
|
|
2976
2990
|
"repl.provider_add_missing_value": "Missing value for {flag}",
|
|
2991
|
+
"repl.provider_add_invalid_number": "Invalid number for {flag}: '{value}'",
|
|
2977
2992
|
"repl.provider_switch_hint": "Switch to it with: /provider use {name}",
|
|
2993
|
+
"repl.provider_flag_url": "Base API URL (fallback: known presets)",
|
|
2994
|
+
"repl.provider_flag_key": "API key",
|
|
2995
|
+
"repl.provider_flag_priority": "Fallback order; lower = tried first",
|
|
2996
|
+
"repl.provider_flag_context_window": "Per-provider context window (tokens)",
|
|
2997
|
+
"repl.provider_flag_rpm": "Max requests per minute (default 60)",
|
|
2998
|
+
"repl.provider_flag_parallel": "Max parallel tasks (default 1)",
|
|
2978
2999
|
"repl.model_list": "List models of the active provider or switch the model",
|
|
2979
3000
|
"repl.model_current": "Current model",
|
|
2980
3001
|
"repl.model_set": "Model set to: {name}",
|
|
2981
|
-
"repl.model_usage": "/model list
|
|
3002
|
+
"repl.model_usage": "Usage: /model list | /model use <name>",
|
|
3003
|
+
"repl.unknown_sub": "Unknown subcommand '{sub}' for /{cmd}. See usage below.",
|
|
3004
|
+
"repl.help_unknown": "Unknown command '/{name}'",
|
|
3005
|
+
"repl.help_aliases": "Aliases: {names}",
|
|
3006
|
+
"repl.help_examples": "Examples:",
|
|
3007
|
+
"repl.export": "Export a session to a file",
|
|
3008
|
+
"repl.export_usage": "Usage: /export [<id|name>] [--format md|json|jsonl] [--out <path>] [--no-redact]",
|
|
3009
|
+
"config.header": "Managed settings",
|
|
3010
|
+
"config.col_setting": "Setting",
|
|
3011
|
+
"config.col_value": "Value",
|
|
3012
|
+
"config.col_domain": "Domain",
|
|
3013
|
+
"config.col_change": "Change with",
|
|
3014
|
+
"config.session_line": "Session: {name} ({id}) — {count} messages",
|
|
3015
|
+
"config.usage_hint": "Get: /config <key> · Set: /config <key> <value> · Reset: /config reset <key>",
|
|
3016
|
+
"config.saved": "saved · reset: /config reset {key}",
|
|
3017
|
+
"config.read_only_hint": "read-only",
|
|
3018
|
+
"config.read_only": "'{key}' is read-only",
|
|
3019
|
+
"config.unknown_key": "Unknown key '{key}'. {suggestion}",
|
|
3020
|
+
"config.suggest": "Did you mean '{name}'?",
|
|
3021
|
+
"config.valid_keys": "Valid keys: {keys}",
|
|
3022
|
+
"config.invalid_value": "Invalid value for {key}. {hint}",
|
|
3023
|
+
"config.range": "Value out of range for {key}",
|
|
3024
|
+
"config.combined": "system + reserve must stay below 0.95",
|
|
3025
|
+
"config.hint_string": "Expected a non-empty string",
|
|
3026
|
+
"config.hint_enum": "Allowed: {values}",
|
|
3027
|
+
"config.hint_bool": "Expected on/off",
|
|
3028
|
+
"config.hint_share": "Expected 0.05–0.9 or a percentage (e.g. 10%)",
|
|
3029
|
+
"config.hint_int": "Expected an integer ≥ {min}",
|
|
3030
|
+
"config.reset_ok": "{key} restored to session-start value: {value} · saved",
|
|
3031
|
+
"config.reset_unchanged": "{key} already at session value",
|
|
3032
|
+
"config.reset_none": "No settings changed this session",
|
|
3033
|
+
"config.reset_all_confirm": "Reset {count} changed setting(s) to session-start values? [y/N] ",
|
|
3034
|
+
"config.reset_all_done": "Restored {count} setting(s) · saved",
|
|
3035
|
+
"config.reset_all_needs_yes": "Refusing to reset without confirmation in non-interactive mode; pass --yes",
|
|
3036
|
+
"config.reset_cancelled": "Reset cancelled",
|
|
3037
|
+
"config.reset_usage": "Usage: /config reset <key> | /config reset --all [--yes]",
|
|
3038
|
+
"config.alias_label": "alias of",
|
|
3039
|
+
"config.group_label": "group",
|
|
3040
|
+
"reasoning.status": "Reasoning: display {display} · effort {level} {auto}",
|
|
3041
|
+
"reasoning.on": "on",
|
|
3042
|
+
"reasoning.off": "off",
|
|
3043
|
+
"reasoning.auto_on": "(auto policy)",
|
|
3044
|
+
"reasoning.auto_off": "(auto policy off)",
|
|
3045
|
+
"reasoning.auto_off_hint": "Auto policy off. Restore with: /config reset reasoning.mode",
|
|
3046
|
+
"reasoning.display_set": "Reasoning display: {state}",
|
|
3047
|
+
"reasoning.unknown_sub": "Unknown argument '{sub}'.",
|
|
3048
|
+
"reasoning.sub_show": "Show reasoning content",
|
|
3049
|
+
"reasoning.sub_hide": "Hide reasoning content",
|
|
3050
|
+
"reasoning.sub_level": "Set reasoning effort level",
|
|
3051
|
+
"verbose.status": "Verbosity: {level}",
|
|
3052
|
+
"verbose.sub_quiet": "One line per action",
|
|
3053
|
+
"verbose.sub_normal": "Add short result summaries",
|
|
3054
|
+
"verbose.sub_verbose": "Full per-action detail",
|
|
3055
|
+
"context.unknown_arg": "Unknown argument '{arg}'.",
|
|
3056
|
+
"context.sub_system": "System-prompt share",
|
|
3057
|
+
"context.sub_reserve": "Response-reserve share",
|
|
3058
|
+
"model.not_in_list": "Note: '{name}' is not in the known model list",
|
|
3059
|
+
"model.sub_list": "List models of the active provider",
|
|
3060
|
+
"model.sub_use": "Switch model",
|
|
3061
|
+
"provider.sub_list": "List configured providers",
|
|
3062
|
+
"provider.sub_use": "Switch active provider",
|
|
3063
|
+
"provider.sub_add": "Add a provider",
|
|
3064
|
+
"map.sub_summary": "Show the project map summary",
|
|
3065
|
+
"map.sub_refresh": "Rebuild the project index",
|
|
3066
|
+
"map.sub_find": "Search the project map",
|
|
3067
|
+
"lsp.sub_status": "Show LSP server status",
|
|
3068
|
+
"lsp.sub_restart": "Reset disabled servers",
|
|
3069
|
+
"lsp.sub_check": "Run an LSP check on a path",
|
|
3070
|
+
"skill.sub_list": "List available skills",
|
|
3071
|
+
"skill.sub_loaded": "List loaded skills",
|
|
3072
|
+
"skill.sub_load": "Load a skill",
|
|
3073
|
+
"skill.sub_unload": "Unload a skill",
|
|
3074
|
+
"skill.sub_search": "Search skills",
|
|
3075
|
+
"export.written": "Exported to {path}",
|
|
3076
|
+
"export.redacted": "secrets redacted (--no-redact to disable)",
|
|
3077
|
+
"export.raw": "secrets NOT redacted",
|
|
3078
|
+
"export.empty": "session has no messages — nothing exported",
|
|
3079
|
+
"export.invalid_format": "Unknown format '{format}'. Use md|json|jsonl",
|
|
3080
|
+
"export.missing_value": "Missing value for {flag}",
|
|
3081
|
+
"export.write_failed": "Failed to write export: {error}",
|
|
2982
3082
|
"repl.group.general": "General",
|
|
2983
3083
|
"repl.group.agent": "Agent",
|
|
2984
3084
|
"repl.group.session": "Sessions",
|
|
@@ -3676,6 +3776,10 @@ var init_ru = __esm(() => {
|
|
|
3676
3776
|
"cli.list_sessions": "Список всех сессий",
|
|
3677
3777
|
"cli.show_details": "Показать детали сессии",
|
|
3678
3778
|
"cli.delete_session": "Удалить сессию",
|
|
3779
|
+
"cli.export_session": "Экспортировать сессию в файл (md, json или jsonl)",
|
|
3780
|
+
"cli.export_format": "Формат вывода: md|json|jsonl (по умолчанию md)",
|
|
3781
|
+
"cli.export_out": "Путь вывода ('-' для stdout)",
|
|
3782
|
+
"cli.export_no_redact": "Не скрывать секреты",
|
|
3679
3783
|
"cli.first_run": "Первый запуск. Запускаем мастер настройки...",
|
|
3680
3784
|
"cli.first_run_oneshot": "Конфигурация не найдена — запуск с настройками по умолчанию. Запустите `mma` без аргументов один раз для настройки.",
|
|
3681
3785
|
"cli.setup_saved_restart": "Настройки сохранены. Перезапуск с новой конфигурацией...",
|
|
@@ -3744,20 +3848,21 @@ var init_ru = __esm(() => {
|
|
|
3744
3848
|
"repl.exit_usage": "Использование: /exit",
|
|
3745
3849
|
"repl.clear": "Очистить экран",
|
|
3746
3850
|
"repl.clear_usage": "Использование: /clear",
|
|
3851
|
+
"repl.clear_hint": "Экран очищен. Новая сессия и контекст: /new",
|
|
3747
3852
|
"repl.run": "Выполнить запрос через агента",
|
|
3748
3853
|
"repl.run_usage": "Использование: /run <запрос>",
|
|
3749
|
-
"repl.config": "Показать
|
|
3750
|
-
"repl.config_usage": "Использование: /config",
|
|
3751
|
-
"repl.reasoning": "
|
|
3752
|
-
"repl.reasoning_usage": "Использование: /reasoning [auto|none|low|medium|high|max]",
|
|
3854
|
+
"repl.config": "Показать или изменить настройки (get / set / reset)",
|
|
3855
|
+
"repl.config_usage": "Использование: /config [<ключ> [значение]] | /config reset <ключ> | /config reset --all [--yes] | /config migrate",
|
|
3856
|
+
"repl.reasoning": "Показать статус рассуждений, переключить показ или уровень",
|
|
3857
|
+
"repl.reasoning_usage": "Использование: /reasoning [show|hide|level <auto|default|none|low|medium|high|max>]",
|
|
3753
3858
|
"repl.reasoning_level_set": "Уровень рассуждений установлен: {level}",
|
|
3754
3859
|
"repl.reasoning_invalid_level": "Неверный уровень '{level}'. Допустимые: {valid}",
|
|
3755
|
-
"repl.verbose": "Подробность
|
|
3860
|
+
"repl.verbose": "Подробность вывода (quiet, normal, verbose)",
|
|
3756
3861
|
"repl.verbose_usage": "Использование: /verbose [quiet|normal|verbose]",
|
|
3757
3862
|
"repl.verbose_set": "Подробность вывода: {level}",
|
|
3758
3863
|
"repl.verbose_invalid_level": "Неверный уровень '{level}'. Допустимые: {valid}",
|
|
3759
3864
|
"repl.last_action_none": "Нет недавнего действия для показа.",
|
|
3760
|
-
"repl.status": "Показать
|
|
3865
|
+
"repl.status": "Показать компактную строку статуса",
|
|
3761
3866
|
"repl.status_usage": "Использование: /status",
|
|
3762
3867
|
"repl.plugins": "Список загруженных плагинов",
|
|
3763
3868
|
"repl.plugins_usage": "Использование: /plugins [--all]",
|
|
@@ -3797,11 +3902,13 @@ var init_ru = __esm(() => {
|
|
|
3797
3902
|
"repl.context": "Контекст:",
|
|
3798
3903
|
"repl.sysprompt_label": "Системный промпт:",
|
|
3799
3904
|
"repl.sysprompt_size": "{used} / {budget} токенов",
|
|
3800
|
-
"repl.sysprompt_desc": "
|
|
3905
|
+
"repl.sysprompt_desc": "Размер системного промпта и блоки (текст — через --full)",
|
|
3906
|
+
"repl.sysprompt_usage": "Использование: /sysprompt [--full]",
|
|
3907
|
+
"repl.sysprompt_full_hint": "Полный текст промпта скрыт — выполните /sysprompt --full.",
|
|
3801
3908
|
"repl.sysprompt_tokens": "Системный промпт ({count} токенов):",
|
|
3802
3909
|
"repl.excluded_blocks": `
|
|
3803
3910
|
Исключённые блоки: {count}`,
|
|
3804
|
-
"repl.context_usage": "Использование: /context [
|
|
3911
|
+
"repl.context_usage": "Использование: /context [<размер, мин 1024> | system <доля> | reserve <доля>] (доля 0.05–0.9 или напр. 10%; system+reserve ≤ 0.95)",
|
|
3805
3912
|
"repl.msgs": "сообщ.",
|
|
3806
3913
|
"repl.max_iters": "Макс итераций:",
|
|
3807
3914
|
"repl.stuck_thresh": "Порог зависания:",
|
|
@@ -3845,13 +3952,105 @@ var init_ru = __esm(() => {
|
|
|
3845
3952
|
"repl.provider_list": "Список настроенных провайдеров или горячая смена активного",
|
|
3846
3953
|
"repl.provider_current": "Текущий провайдер",
|
|
3847
3954
|
"repl.provider_set": "Провайдер установлен: {name}",
|
|
3848
|
-
"repl.provider_usage":
|
|
3955
|
+
"repl.provider_usage": `Использование: /provider list | /provider use <имя> | /provider add <имя> [флаги]
|
|
3956
|
+
--url <url> базовый URL API (иначе — из пресетов)
|
|
3957
|
+
--key <ключ> API-ключ
|
|
3958
|
+
--priority <n> порядок fallback; меньше = раньше
|
|
3959
|
+
--context-window <n> окно контекста провайдера (токены)
|
|
3960
|
+
--rpm <n> запросов/мин (по умолчанию 60)
|
|
3961
|
+
--parallel <n> параллельных задач (по умолчанию 1)`,
|
|
3849
3962
|
"repl.provider_add_missing_value": "Нет значения для {flag}",
|
|
3963
|
+
"repl.provider_add_invalid_number": "Неверное число для {flag}: '{value}'",
|
|
3850
3964
|
"repl.provider_switch_hint": "Переключитесь на него: /provider use {name}",
|
|
3965
|
+
"repl.provider_flag_url": "Базовый URL API (иначе — из пресетов)",
|
|
3966
|
+
"repl.provider_flag_key": "API-ключ",
|
|
3967
|
+
"repl.provider_flag_priority": "Порядок fallback; меньше = раньше",
|
|
3968
|
+
"repl.provider_flag_context_window": "Окно контекста провайдера (токены)",
|
|
3969
|
+
"repl.provider_flag_rpm": "Запросов в минуту (по умолчанию 60)",
|
|
3970
|
+
"repl.provider_flag_parallel": "Параллельных задач (по умолчанию 1)",
|
|
3851
3971
|
"repl.model_list": "Список моделей активного провайдера или смена модели",
|
|
3852
3972
|
"repl.model_current": "Текущая модель",
|
|
3853
3973
|
"repl.model_set": "Модель установлена: {name}",
|
|
3854
|
-
"repl.model_usage": "/model list
|
|
3974
|
+
"repl.model_usage": "Использование: /model list | /model use <имя>",
|
|
3975
|
+
"repl.unknown_sub": "Неизвестная подкоманда '{sub}' для /{cmd}. См. использование ниже.",
|
|
3976
|
+
"repl.help_unknown": "Неизвестная команда '/{name}'",
|
|
3977
|
+
"repl.help_aliases": "Алиасы: {names}",
|
|
3978
|
+
"repl.help_examples": "Примеры:",
|
|
3979
|
+
"repl.export": "Экспортировать сессию в файл",
|
|
3980
|
+
"repl.export_usage": "Использование: /export [<id|имя>] [--format md|json|jsonl] [--out <путь>] [--no-redact]",
|
|
3981
|
+
"config.header": "Управляемые настройки",
|
|
3982
|
+
"config.col_setting": "Настройка",
|
|
3983
|
+
"config.col_value": "Значение",
|
|
3984
|
+
"config.col_domain": "Домен",
|
|
3985
|
+
"config.col_change": "Как менять",
|
|
3986
|
+
"config.session_line": "Сессия: {name} ({id}) — {count} сообщений",
|
|
3987
|
+
"config.usage_hint": "Чтение: /config <ключ> · Запись: /config <ключ> <значение> · Сброс: /config reset <ключ>",
|
|
3988
|
+
"config.saved": "сохранено · сброс: /config reset {key}",
|
|
3989
|
+
"config.read_only_hint": "только чтение",
|
|
3990
|
+
"config.read_only": "'{key}' — только чтение",
|
|
3991
|
+
"config.unknown_key": "Неизвестный ключ '{key}'. {suggestion}",
|
|
3992
|
+
"config.suggest": "Возможно, вы имели в виду '{name}'?",
|
|
3993
|
+
"config.valid_keys": "Допустимые ключи: {keys}",
|
|
3994
|
+
"config.invalid_value": "Неверное значение для {key}. {hint}",
|
|
3995
|
+
"config.range": "Значение вне диапазона для {key}",
|
|
3996
|
+
"config.combined": "system + reserve должны оставаться ниже 0.95",
|
|
3997
|
+
"config.hint_string": "Ожидается непустая строка",
|
|
3998
|
+
"config.hint_enum": "Допустимые: {values}",
|
|
3999
|
+
"config.hint_bool": "Ожидается on/off",
|
|
4000
|
+
"config.hint_share": "Ожидается 0.05–0.9 или процент (напр. 10%)",
|
|
4001
|
+
"config.hint_int": "Ожидается целое ≥ {min}",
|
|
4002
|
+
"config.reset_ok": "{key} восстановлен к значению на старте сессии: {value} · сохранено",
|
|
4003
|
+
"config.reset_unchanged": "{key} уже соответствует значению сессии",
|
|
4004
|
+
"config.reset_none": "В этой сессии настройки не менялись",
|
|
4005
|
+
"config.reset_all_confirm": "Сбросить {count} изменённых настроек к значениям на старте сессии? [y/N] ",
|
|
4006
|
+
"config.reset_all_done": "Восстановлено настроек: {count} · сохранено",
|
|
4007
|
+
"config.reset_all_needs_yes": "Отказ от сброса без подтверждения в неинтерактивном режиме; укажите --yes",
|
|
4008
|
+
"config.reset_cancelled": "Сброс отменён",
|
|
4009
|
+
"config.reset_usage": "Использование: /config reset <ключ> | /config reset --all [--yes]",
|
|
4010
|
+
"config.alias_label": "алиас",
|
|
4011
|
+
"config.group_label": "группа",
|
|
4012
|
+
"reasoning.status": "Рассуждения: показ {display} · усилие {level} {auto}",
|
|
4013
|
+
"reasoning.on": "вкл",
|
|
4014
|
+
"reasoning.off": "выкл",
|
|
4015
|
+
"reasoning.auto_on": "(авто-политика)",
|
|
4016
|
+
"reasoning.auto_off": "(авто-политика выключена)",
|
|
4017
|
+
"reasoning.auto_off_hint": "Авто-политика выключена. Вернуть: /config reset reasoning.mode",
|
|
4018
|
+
"reasoning.display_set": "Показ рассуждений: {state}",
|
|
4019
|
+
"reasoning.unknown_sub": "Неизвестный аргумент '{sub}'.",
|
|
4020
|
+
"reasoning.sub_show": "Показывать рассуждения",
|
|
4021
|
+
"reasoning.sub_hide": "Скрыть рассуждения",
|
|
4022
|
+
"reasoning.sub_level": "Установить уровень рассуждений",
|
|
4023
|
+
"verbose.status": "Подробность: {level}",
|
|
4024
|
+
"verbose.sub_quiet": "Одна строка на действие",
|
|
4025
|
+
"verbose.sub_normal": "Плюс короткие сводки результатов",
|
|
4026
|
+
"verbose.sub_verbose": "Полная деталь по действиям",
|
|
4027
|
+
"context.unknown_arg": "Неизвестный аргумент '{arg}'.",
|
|
4028
|
+
"context.sub_system": "Доля системного промпта",
|
|
4029
|
+
"context.sub_reserve": "Доля резерва ответа",
|
|
4030
|
+
"model.not_in_list": "Примечание: '{name}' нет в списке известных моделей",
|
|
4031
|
+
"model.sub_list": "Список моделей активного провайдера",
|
|
4032
|
+
"model.sub_use": "Сменить модель",
|
|
4033
|
+
"provider.sub_list": "Список настроенных провайдеров",
|
|
4034
|
+
"provider.sub_use": "Сменить активного провайдера",
|
|
4035
|
+
"provider.sub_add": "Добавить провайдера",
|
|
4036
|
+
"map.sub_summary": "Показать сводку карты проекта",
|
|
4037
|
+
"map.sub_refresh": "Перестроить индекс проекта",
|
|
4038
|
+
"map.sub_find": "Поиск по карте проекта",
|
|
4039
|
+
"lsp.sub_status": "Статус LSP-серверов",
|
|
4040
|
+
"lsp.sub_restart": "Сбросить отключённые серверы",
|
|
4041
|
+
"lsp.sub_check": "Запустить LSP-проверку пути",
|
|
4042
|
+
"skill.sub_list": "Список доступных скиллов",
|
|
4043
|
+
"skill.sub_loaded": "Список загруженных скиллов",
|
|
4044
|
+
"skill.sub_load": "Загрузить скилл",
|
|
4045
|
+
"skill.sub_unload": "Выгрузить скилл",
|
|
4046
|
+
"skill.sub_search": "Поиск скиллов",
|
|
4047
|
+
"export.written": "Экспортировано в {path}",
|
|
4048
|
+
"export.redacted": "секреты скрыты (--no-redact чтобы отключить)",
|
|
4049
|
+
"export.raw": "секреты НЕ скрыты",
|
|
4050
|
+
"export.empty": "в сессии нет сообщений — экспорт не создан",
|
|
4051
|
+
"export.invalid_format": "Неизвестный формат '{format}'. Используйте md|json|jsonl",
|
|
4052
|
+
"export.missing_value": "Нет значения для {flag}",
|
|
4053
|
+
"export.write_failed": "Не удалось записать экспорт: {error}",
|
|
3855
4054
|
"repl.reload": "Перезагрузить агента с текущим конфигом",
|
|
3856
4055
|
"repl.reload_usage": "Использование: /reload",
|
|
3857
4056
|
"repl.reloading": "Перезагрузка агента...",
|
|
@@ -5118,7 +5317,7 @@ var init_domains = __esm(() => {
|
|
|
5118
5317
|
"reasoning",
|
|
5119
5318
|
"hallucination"
|
|
5120
5319
|
],
|
|
5121
|
-
provider: ["provider", "orchestrator", "retry", "pricing"],
|
|
5320
|
+
provider: ["provider", "orchestrator", "retry", "pricing", "modelCapabilities"],
|
|
5122
5321
|
moe: ["moe", "experts"],
|
|
5123
5322
|
security: ["security"],
|
|
5124
5323
|
browser: ["browser"],
|
|
@@ -6605,7 +6804,7 @@ class OpenAICompatProvider {
|
|
|
6605
6804
|
}
|
|
6606
6805
|
}
|
|
6607
6806
|
async* streamOnce(messages, tools, signal, options, onEmit, idleTimeoutMs) {
|
|
6608
|
-
const maxTokens = options?.maxTokens ?? this.config.maxCompletionTokens ??
|
|
6807
|
+
const maxTokens = options?.maxTokens ?? this.config.maxCompletionTokens ?? DEFAULT_MAX_COMPLETION_TOKENS;
|
|
6609
6808
|
const body = buildRequestBody({
|
|
6610
6809
|
model: this.model,
|
|
6611
6810
|
messages,
|
|
@@ -6871,7 +7070,7 @@ class OpenAICompatProvider {
|
|
|
6871
7070
|
};
|
|
6872
7071
|
}
|
|
6873
7072
|
async doNonStreaming(messages, tools, signal, options) {
|
|
6874
|
-
const maxTokens = options?.maxTokens ?? this.config.maxCompletionTokens ??
|
|
7073
|
+
const maxTokens = options?.maxTokens ?? this.config.maxCompletionTokens ?? DEFAULT_MAX_COMPLETION_TOKENS;
|
|
6875
7074
|
const body = buildRequestBody({
|
|
6876
7075
|
model: this.model,
|
|
6877
7076
|
messages,
|
|
@@ -7047,7 +7246,7 @@ class OpenAICompatProvider {
|
|
|
7047
7246
|
});
|
|
7048
7247
|
}
|
|
7049
7248
|
}
|
|
7050
|
-
var REQUEST_TIMEOUT_MS = 120000, MAX_RATE_WAIT_MS = 30000, cachedUserAgent = null;
|
|
7249
|
+
var REQUEST_TIMEOUT_MS = 120000, MAX_RATE_WAIT_MS = 30000, DEFAULT_MAX_COMPLETION_TOKENS = 8192, cachedUserAgent = null;
|
|
7051
7250
|
var init_openai_compat = __esm(() => {
|
|
7052
7251
|
init_token_counter();
|
|
7053
7252
|
init_i18n();
|
|
@@ -7547,7 +7746,7 @@ var init_factory = __esm(() => {
|
|
|
7547
7746
|
});
|
|
7548
7747
|
|
|
7549
7748
|
// src/llm/model-loader.ts
|
|
7550
|
-
async function
|
|
7749
|
+
async function probeModel(baseUrl, model, timeoutMs = 3000) {
|
|
7551
7750
|
const base = baseUrl.replace(/\/$/, "").replace(/\/v1\/?$/, "");
|
|
7552
7751
|
try {
|
|
7553
7752
|
const response = await fetch(`${base}/api/v1/models`, {
|
|
@@ -7561,10 +7760,18 @@ async function getLoadedContextLength(baseUrl, model, timeoutMs = 3000) {
|
|
|
7561
7760
|
if (!found)
|
|
7562
7761
|
return null;
|
|
7563
7762
|
const loadedInstance = (found.loaded_instances ?? [])[0];
|
|
7564
|
-
const
|
|
7565
|
-
if (typeof
|
|
7763
|
+
const contextLength = loadedInstance?.config?.context_length ?? found.max_context_length;
|
|
7764
|
+
if (typeof contextLength !== "number" || contextLength <= 0)
|
|
7566
7765
|
return null;
|
|
7567
|
-
|
|
7766
|
+
const raw = found.capabilities;
|
|
7767
|
+
let capabilities;
|
|
7768
|
+
if (raw && typeof raw.vision === "boolean") {
|
|
7769
|
+
capabilities = { vision: raw.vision };
|
|
7770
|
+
if (typeof raw.trained_for_tool_use === "boolean") {
|
|
7771
|
+
capabilities.tools = raw.trained_for_tool_use;
|
|
7772
|
+
}
|
|
7773
|
+
}
|
|
7774
|
+
return { model: found.key ?? found.name ?? model, contextLength, capabilities };
|
|
7568
7775
|
} catch {
|
|
7569
7776
|
return null;
|
|
7570
7777
|
}
|
|
@@ -15436,6 +15643,15 @@ var init_tool_output = __esm(() => {
|
|
|
15436
15643
|
init_i18n();
|
|
15437
15644
|
});
|
|
15438
15645
|
|
|
15646
|
+
// src/core/agent/tool-images.ts
|
|
15647
|
+
function queueToolImages(sink, images) {
|
|
15648
|
+
if (!sink || !images || images.length === 0)
|
|
15649
|
+
return;
|
|
15650
|
+
for (const image of images) {
|
|
15651
|
+
sink.addPendingImage(image);
|
|
15652
|
+
}
|
|
15653
|
+
}
|
|
15654
|
+
|
|
15439
15655
|
// src/core/agent/tool-batch.ts
|
|
15440
15656
|
class ToolBatchExecutor {
|
|
15441
15657
|
deps;
|
|
@@ -15565,6 +15781,7 @@ class ToolBatchExecutor {
|
|
|
15565
15781
|
arguments: call.arguments
|
|
15566
15782
|
});
|
|
15567
15783
|
answeredToolCallIds.add(call.id);
|
|
15784
|
+
queueToolImages(contextManager, result.images);
|
|
15568
15785
|
const tokensAfterTool = contextManager.getEstimatedTokens();
|
|
15569
15786
|
const costAfterTool = this.deps.costTracker.total;
|
|
15570
15787
|
onTool?.({
|
|
@@ -21290,6 +21507,119 @@ var init_session = __esm(() => {
|
|
|
21290
21507
|
init_i18n();
|
|
21291
21508
|
});
|
|
21292
21509
|
|
|
21510
|
+
// src/llm/image-utils.ts
|
|
21511
|
+
var exports_image_utils = {};
|
|
21512
|
+
__export(exports_image_utils, {
|
|
21513
|
+
readClipboardImage: () => readClipboardImage,
|
|
21514
|
+
loadUrlAsDataUrl: () => loadUrlAsDataUrl,
|
|
21515
|
+
loadFileAsDataUrl: () => loadFileAsDataUrl,
|
|
21516
|
+
detectMime: () => detectMime,
|
|
21517
|
+
bufferToDataUrl: () => bufferToDataUrl
|
|
21518
|
+
});
|
|
21519
|
+
import { readFileSync as readFileSync20 } from "fs";
|
|
21520
|
+
import { extname as extname4 } from "path";
|
|
21521
|
+
function detectMime(filePath) {
|
|
21522
|
+
const ext = extname4(filePath).toLowerCase();
|
|
21523
|
+
return MIME_MAP[ext] ?? "image/png";
|
|
21524
|
+
}
|
|
21525
|
+
async function readClipboardImage() {
|
|
21526
|
+
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21527
|
+
try {
|
|
21528
|
+
const img = Bun.Image.fromClipboard();
|
|
21529
|
+
if (img) {
|
|
21530
|
+
const buf = await img.resize(800, 800, { fit: "inside" }).jpeg({ quality: 60 }).buffer();
|
|
21531
|
+
return Buffer.from(buf);
|
|
21532
|
+
}
|
|
21533
|
+
} catch {}
|
|
21534
|
+
}
|
|
21535
|
+
return readClipboardFallback();
|
|
21536
|
+
}
|
|
21537
|
+
async function readClipboardFallback() {
|
|
21538
|
+
const { platform: platform7 } = await import("os");
|
|
21539
|
+
const { execSync } = await import("child_process");
|
|
21540
|
+
const { readFileSync: readFileSync21, unlinkSync: unlinkSync5 } = await import("fs");
|
|
21541
|
+
const { join: join29 } = await import("path");
|
|
21542
|
+
if (platform7() !== "linux")
|
|
21543
|
+
return null;
|
|
21544
|
+
const tmpPath = join29(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
21545
|
+
const commands = [
|
|
21546
|
+
`wl-paste --type image/png > "${tmpPath}" 2>/dev/null`,
|
|
21547
|
+
`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`
|
|
21548
|
+
];
|
|
21549
|
+
for (const cmd of commands) {
|
|
21550
|
+
try {
|
|
21551
|
+
execSync(cmd, { timeout: 5000 });
|
|
21552
|
+
const buf = readFileSync21(tmpPath);
|
|
21553
|
+
unlinkSync5(tmpPath);
|
|
21554
|
+
if (buf.length > 0)
|
|
21555
|
+
return buf;
|
|
21556
|
+
} catch {}
|
|
21557
|
+
}
|
|
21558
|
+
try {
|
|
21559
|
+
unlinkSync5(tmpPath);
|
|
21560
|
+
} catch {}
|
|
21561
|
+
return null;
|
|
21562
|
+
}
|
|
21563
|
+
async function loadFileAsDataUrl(filePath) {
|
|
21564
|
+
const buf = readFileSync20(filePath);
|
|
21565
|
+
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21566
|
+
try {
|
|
21567
|
+
const img = new Bun.Image(buf);
|
|
21568
|
+
const { width } = await img.metadata();
|
|
21569
|
+
const targetWidth = Math.min(800, width || 800);
|
|
21570
|
+
const dataUrl = await img.resize(targetWidth, 800, { fit: "inside" }).jpeg({ quality: 60 }).dataurl();
|
|
21571
|
+
return { dataUrl };
|
|
21572
|
+
} catch {}
|
|
21573
|
+
}
|
|
21574
|
+
const b64 = buf.toString("base64");
|
|
21575
|
+
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
21576
|
+
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "webp" ? "image/webp" : "image/png";
|
|
21577
|
+
return { dataUrl: `data:${mime};base64,${b64}` };
|
|
21578
|
+
}
|
|
21579
|
+
async function loadUrlAsDataUrl(url) {
|
|
21580
|
+
const resp = await fetch(url);
|
|
21581
|
+
if (!resp.ok) {
|
|
21582
|
+
throw new Error(`Failed to fetch image: ${resp.status} ${resp.statusText}`);
|
|
21583
|
+
}
|
|
21584
|
+
const buf = Buffer.from(await resp.arrayBuffer());
|
|
21585
|
+
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21586
|
+
try {
|
|
21587
|
+
const img = new Bun.Image(buf);
|
|
21588
|
+
const { width } = await img.metadata();
|
|
21589
|
+
const targetWidth = Math.min(800, width || 800);
|
|
21590
|
+
const dataUrl = await img.resize(targetWidth, 800, { fit: "inside" }).jpeg({ quality: 60 }).dataurl();
|
|
21591
|
+
return { dataUrl };
|
|
21592
|
+
} catch {}
|
|
21593
|
+
}
|
|
21594
|
+
const b64 = buf.toString("base64");
|
|
21595
|
+
return { dataUrl: `data:image/png;base64,${b64}` };
|
|
21596
|
+
}
|
|
21597
|
+
async function bufferToDataUrl(buf) {
|
|
21598
|
+
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21599
|
+
try {
|
|
21600
|
+
const img = new Bun.Image(buf);
|
|
21601
|
+
const { width } = await img.metadata();
|
|
21602
|
+
const targetWidth = Math.min(800, width || 800);
|
|
21603
|
+
const dataUrl = await img.resize(targetWidth, 800, { fit: "inside" }).jpeg({ quality: 60 }).dataurl();
|
|
21604
|
+
return { dataUrl };
|
|
21605
|
+
} catch {}
|
|
21606
|
+
}
|
|
21607
|
+
const b64 = buf.toString("base64");
|
|
21608
|
+
return { dataUrl: `data:image/png;base64,${b64}` };
|
|
21609
|
+
}
|
|
21610
|
+
var MIME_MAP;
|
|
21611
|
+
var init_image_utils = __esm(() => {
|
|
21612
|
+
MIME_MAP = {
|
|
21613
|
+
".png": "image/png",
|
|
21614
|
+
".jpg": "image/jpeg",
|
|
21615
|
+
".jpeg": "image/jpeg",
|
|
21616
|
+
".gif": "image/gif",
|
|
21617
|
+
".webp": "image/webp",
|
|
21618
|
+
".bmp": "image/bmp",
|
|
21619
|
+
".svg": "image/svg+xml"
|
|
21620
|
+
};
|
|
21621
|
+
});
|
|
21622
|
+
|
|
21293
21623
|
// src/tools/browser.ts
|
|
21294
21624
|
import { join as join29 } from "path";
|
|
21295
21625
|
import { mkdirSync as mkdirSync16 } from "fs";
|
|
@@ -21326,18 +21656,9 @@ function formatScreenshotForTextModel(snapshot) {
|
|
|
21326
21656
|
|
|
21327
21657
|
${snapshot}`;
|
|
21328
21658
|
}
|
|
21329
|
-
function
|
|
21330
|
-
const
|
|
21331
|
-
return
|
|
21332
|
-
}
|
|
21333
|
-
function formatScreenshotResult(snapshot, screenshot, supportsVision) {
|
|
21334
|
-
if (!supportsVision) {
|
|
21335
|
-
return formatScreenshotForTextModel(snapshot);
|
|
21336
|
-
}
|
|
21337
|
-
const base642 = screenshot.toString("base64");
|
|
21338
|
-
return `${snapshot}
|
|
21339
|
-
|
|
21340
|
-
[Screenshot: data:image/png;base64,${base642}]`;
|
|
21659
|
+
async function screenshotToImagePart(screenshot) {
|
|
21660
|
+
const { dataUrl } = await bufferToDataUrl(screenshot);
|
|
21661
|
+
return { type: "image_url", image_url: { url: dataUrl } };
|
|
21341
21662
|
}
|
|
21342
21663
|
function createBrowserTool() {
|
|
21343
21664
|
return {
|
|
@@ -21402,12 +21723,15 @@ function createBrowserTool() {
|
|
|
21402
21723
|
}
|
|
21403
21724
|
const s = getSession(ctx);
|
|
21404
21725
|
const result = await serialize(() => s.execute(action, args));
|
|
21405
|
-
const supportsVision = modelSupportsVision(ctx.config.model);
|
|
21406
21726
|
if (result.screenshot) {
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
|
|
21410
|
-
|
|
21727
|
+
if (ctx.capabilities?.vision) {
|
|
21728
|
+
return {
|
|
21729
|
+
success: result.success,
|
|
21730
|
+
output: result.output,
|
|
21731
|
+
images: [await screenshotToImagePart(result.screenshot)]
|
|
21732
|
+
};
|
|
21733
|
+
}
|
|
21734
|
+
return { success: result.success, output: formatScreenshotForTextModel(result.output) };
|
|
21411
21735
|
}
|
|
21412
21736
|
return { success: result.success, output: result.output };
|
|
21413
21737
|
}
|
|
@@ -21426,125 +21750,13 @@ var session = null, sessionFactory, actionChain;
|
|
|
21426
21750
|
var init_browser = __esm(() => {
|
|
21427
21751
|
init_session();
|
|
21428
21752
|
init_types();
|
|
21753
|
+
init_image_utils();
|
|
21429
21754
|
init_i18n();
|
|
21430
21755
|
init_output();
|
|
21431
21756
|
init_utils();
|
|
21432
21757
|
actionChain = Promise.resolve();
|
|
21433
21758
|
});
|
|
21434
21759
|
|
|
21435
|
-
// src/llm/image-utils.ts
|
|
21436
|
-
var exports_image_utils = {};
|
|
21437
|
-
__export(exports_image_utils, {
|
|
21438
|
-
readClipboardImage: () => readClipboardImage,
|
|
21439
|
-
loadUrlAsDataUrl: () => loadUrlAsDataUrl,
|
|
21440
|
-
loadFileAsDataUrl: () => loadFileAsDataUrl,
|
|
21441
|
-
detectMime: () => detectMime,
|
|
21442
|
-
bufferToDataUrl: () => bufferToDataUrl
|
|
21443
|
-
});
|
|
21444
|
-
import { readFileSync as readFileSync20 } from "fs";
|
|
21445
|
-
import { extname as extname4 } from "path";
|
|
21446
|
-
function detectMime(filePath) {
|
|
21447
|
-
const ext = extname4(filePath).toLowerCase();
|
|
21448
|
-
return MIME_MAP[ext] ?? "image/png";
|
|
21449
|
-
}
|
|
21450
|
-
async function readClipboardImage() {
|
|
21451
|
-
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21452
|
-
try {
|
|
21453
|
-
const img = Bun.Image.fromClipboard();
|
|
21454
|
-
if (img) {
|
|
21455
|
-
const buf = await img.resize(800, 800, { fit: "inside" }).jpeg({ quality: 60 }).buffer();
|
|
21456
|
-
return Buffer.from(buf);
|
|
21457
|
-
}
|
|
21458
|
-
} catch {}
|
|
21459
|
-
}
|
|
21460
|
-
return readClipboardFallback();
|
|
21461
|
-
}
|
|
21462
|
-
async function readClipboardFallback() {
|
|
21463
|
-
const { platform: platform7 } = await import("os");
|
|
21464
|
-
const { execSync } = await import("child_process");
|
|
21465
|
-
const { readFileSync: readFileSync21, unlinkSync: unlinkSync5 } = await import("fs");
|
|
21466
|
-
const { join: join30 } = await import("path");
|
|
21467
|
-
if (platform7() !== "linux")
|
|
21468
|
-
return null;
|
|
21469
|
-
const tmpPath = join30(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
21470
|
-
const commands = [
|
|
21471
|
-
`wl-paste --type image/png > "${tmpPath}" 2>/dev/null`,
|
|
21472
|
-
`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`
|
|
21473
|
-
];
|
|
21474
|
-
for (const cmd of commands) {
|
|
21475
|
-
try {
|
|
21476
|
-
execSync(cmd, { timeout: 5000 });
|
|
21477
|
-
const buf = readFileSync21(tmpPath);
|
|
21478
|
-
unlinkSync5(tmpPath);
|
|
21479
|
-
if (buf.length > 0)
|
|
21480
|
-
return buf;
|
|
21481
|
-
} catch {}
|
|
21482
|
-
}
|
|
21483
|
-
try {
|
|
21484
|
-
unlinkSync5(tmpPath);
|
|
21485
|
-
} catch {}
|
|
21486
|
-
return null;
|
|
21487
|
-
}
|
|
21488
|
-
async function loadFileAsDataUrl(filePath) {
|
|
21489
|
-
const buf = readFileSync20(filePath);
|
|
21490
|
-
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21491
|
-
try {
|
|
21492
|
-
const img = new Bun.Image(buf);
|
|
21493
|
-
const { width } = await img.metadata();
|
|
21494
|
-
const targetWidth = Math.min(800, width || 800);
|
|
21495
|
-
const dataUrl = await img.resize(targetWidth, 800, { fit: "inside" }).jpeg({ quality: 60 }).dataurl();
|
|
21496
|
-
return { dataUrl };
|
|
21497
|
-
} catch {}
|
|
21498
|
-
}
|
|
21499
|
-
const b64 = buf.toString("base64");
|
|
21500
|
-
const ext = filePath.split(".").pop()?.toLowerCase();
|
|
21501
|
-
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "webp" ? "image/webp" : "image/png";
|
|
21502
|
-
return { dataUrl: `data:${mime};base64,${b64}` };
|
|
21503
|
-
}
|
|
21504
|
-
async function loadUrlAsDataUrl(url) {
|
|
21505
|
-
const resp = await fetch(url);
|
|
21506
|
-
if (!resp.ok) {
|
|
21507
|
-
throw new Error(`Failed to fetch image: ${resp.status} ${resp.statusText}`);
|
|
21508
|
-
}
|
|
21509
|
-
const buf = Buffer.from(await resp.arrayBuffer());
|
|
21510
|
-
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21511
|
-
try {
|
|
21512
|
-
const img = new Bun.Image(buf);
|
|
21513
|
-
const { width } = await img.metadata();
|
|
21514
|
-
const targetWidth = Math.min(800, width || 800);
|
|
21515
|
-
const dataUrl = await img.resize(targetWidth, 800, { fit: "inside" }).jpeg({ quality: 60 }).dataurl();
|
|
21516
|
-
return { dataUrl };
|
|
21517
|
-
} catch {}
|
|
21518
|
-
}
|
|
21519
|
-
const b64 = buf.toString("base64");
|
|
21520
|
-
return { dataUrl: `data:image/png;base64,${b64}` };
|
|
21521
|
-
}
|
|
21522
|
-
async function bufferToDataUrl(buf) {
|
|
21523
|
-
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
21524
|
-
try {
|
|
21525
|
-
const img = new Bun.Image(buf);
|
|
21526
|
-
const { width } = await img.metadata();
|
|
21527
|
-
const targetWidth = Math.min(800, width || 800);
|
|
21528
|
-
const dataUrl = await img.resize(targetWidth, 800, { fit: "inside" }).jpeg({ quality: 60 }).dataurl();
|
|
21529
|
-
return { dataUrl };
|
|
21530
|
-
} catch {}
|
|
21531
|
-
}
|
|
21532
|
-
const b64 = buf.toString("base64");
|
|
21533
|
-
return { dataUrl: `data:image/png;base64,${b64}` };
|
|
21534
|
-
}
|
|
21535
|
-
var MIME_MAP;
|
|
21536
|
-
var init_image_utils = __esm(() => {
|
|
21537
|
-
MIME_MAP = {
|
|
21538
|
-
".png": "image/png",
|
|
21539
|
-
".jpg": "image/jpeg",
|
|
21540
|
-
".jpeg": "image/jpeg",
|
|
21541
|
-
".gif": "image/gif",
|
|
21542
|
-
".webp": "image/webp",
|
|
21543
|
-
".bmp": "image/bmp",
|
|
21544
|
-
".svg": "image/svg+xml"
|
|
21545
|
-
};
|
|
21546
|
-
});
|
|
21547
|
-
|
|
21548
21760
|
// src/tools/attach-image.ts
|
|
21549
21761
|
import { existsSync as existsSync35 } from "fs";
|
|
21550
21762
|
import { resolve as resolve17 } from "path";
|
|
@@ -24550,7 +24762,7 @@ import {
|
|
|
24550
24762
|
appendFileSync as appendFileSync6
|
|
24551
24763
|
} from "fs";
|
|
24552
24764
|
import { join as join34 } from "path";
|
|
24553
|
-
import { gzipSync } from "zlib";
|
|
24765
|
+
import { gzipSync, gunzipSync } from "zlib";
|
|
24554
24766
|
|
|
24555
24767
|
class SessionStore {
|
|
24556
24768
|
baseDir;
|
|
@@ -24686,6 +24898,24 @@ class SessionStore {
|
|
|
24686
24898
|
return [];
|
|
24687
24899
|
}
|
|
24688
24900
|
}
|
|
24901
|
+
loadRotatedHistory(id) {
|
|
24902
|
+
const gzPath = join34(this.baseDir, `${id}.jsonl.gz`);
|
|
24903
|
+
if (!existsSync41(gzPath))
|
|
24904
|
+
return [];
|
|
24905
|
+
try {
|
|
24906
|
+
const content = gunzipSync(readFileSync25(gzPath)).toString("utf-8");
|
|
24907
|
+
return content.split(`
|
|
24908
|
+
`).filter(Boolean).map((line) => {
|
|
24909
|
+
try {
|
|
24910
|
+
return JSON.parse(line);
|
|
24911
|
+
} catch {
|
|
24912
|
+
return null;
|
|
24913
|
+
}
|
|
24914
|
+
}).filter((m) => m !== null);
|
|
24915
|
+
} catch {
|
|
24916
|
+
return [];
|
|
24917
|
+
}
|
|
24918
|
+
}
|
|
24689
24919
|
appendSessionLog(id, entry) {
|
|
24690
24920
|
const dir = this.sessionDir(id);
|
|
24691
24921
|
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
@@ -24882,6 +25112,12 @@ class SessionManager {
|
|
|
24882
25112
|
return [];
|
|
24883
25113
|
return this.store.loadHistory(this.activeId);
|
|
24884
25114
|
}
|
|
25115
|
+
getHistory(id) {
|
|
25116
|
+
const live = this.store.loadHistory(id);
|
|
25117
|
+
if (live.length > 0)
|
|
25118
|
+
return live;
|
|
25119
|
+
return this.store.loadRotatedHistory(id);
|
|
25120
|
+
}
|
|
24885
25121
|
getSessionContext() {
|
|
24886
25122
|
if (!this.activeId)
|
|
24887
25123
|
return;
|
|
@@ -25291,7 +25527,7 @@ class BrowserModule {
|
|
|
25291
25527
|
"Workflow: open(url) → read snapshot → click/type on element numbers → read updated snapshot.",
|
|
25292
25528
|
'Each snapshot includes a "Content" section with the visible page text, a "Console" section with browser messages, and network errors. Use these to understand the page, detect JS errors, and verify the result of your actions.',
|
|
25293
25529
|
'Always start with "open" action. Use element numbers from snapshot for click/type targets.',
|
|
25294
|
-
'
|
|
25530
|
+
'The "screenshot" action is delivered automatically: a vision model receives the image, a text-only model receives the text snapshot instead. You do not need to decide — just call it and read what you get.'
|
|
25295
25531
|
].join(`
|
|
25296
25532
|
`),
|
|
25297
25533
|
priority: "normal",
|
|
@@ -27704,6 +27940,19 @@ var init_context_log = __esm(() => {
|
|
|
27704
27940
|
SEP2 = "─".repeat(78);
|
|
27705
27941
|
});
|
|
27706
27942
|
|
|
27943
|
+
// src/modules/providers/capabilities.ts
|
|
27944
|
+
function resolveModelCapabilities(preset, probe, override) {
|
|
27945
|
+
const base = preset ? { vision: preset.vision, tools: preset.tools } : { ...DEFAULT_MODEL_CAPABILITIES };
|
|
27946
|
+
return { ...base, ...probe ?? {}, ...override ?? {} };
|
|
27947
|
+
}
|
|
27948
|
+
var DEFAULT_MODEL_CAPABILITIES;
|
|
27949
|
+
var init_capabilities = __esm(() => {
|
|
27950
|
+
DEFAULT_MODEL_CAPABILITIES = {
|
|
27951
|
+
vision: false,
|
|
27952
|
+
tools: false
|
|
27953
|
+
};
|
|
27954
|
+
});
|
|
27955
|
+
|
|
27707
27956
|
// src/core/environment.ts
|
|
27708
27957
|
import { existsSync as existsSync50, readFileSync as readFileSync32, readdirSync as readdirSync16 } from "fs";
|
|
27709
27958
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
@@ -28335,7 +28584,9 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
28335
28584
|
lines.push(`Runtime verification: when a bug is described in terms of runtime behavior (what happens when the app runs), reproduce it — run the app / build / browser tool — and confirm the fix against actual runtime output before calling "plan update step=N status=done". Check existing servers first with process_list/process_log: a stale dev server started BEFORE your change still runs the old pipeline and keeps failing even after the files on disk are fixed. Restart or kill it (process_kill) and verify the exact endpoint/port the user reported — a fresh server on a new port does NOT prove the user's error is gone.`);
|
|
28336
28585
|
const sec = config.security;
|
|
28337
28586
|
if (sec?.enabled) {
|
|
28338
|
-
const secLines = [
|
|
28587
|
+
const secLines = [
|
|
28588
|
+
`SECURITY RESTRICTIONS (enforced — blocked calls return "[SECURITY BLOCKED]", do not retry them):`
|
|
28589
|
+
];
|
|
28339
28590
|
if (sec.bash?.enabled && sec.bash.blacklist.length > 0) {
|
|
28340
28591
|
const cmds = sec.bash.blacklist.slice(0, 15).join(", ");
|
|
28341
28592
|
secLines.push(`Forbidden bash commands: ${cmds}${sec.bash.blacklist.length > 15 ? ", …" : ""}.`);
|
|
@@ -28417,19 +28668,23 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
28417
28668
|
logger4.info(t("env.model_loaded", { model: config.model, seconds: String(loadResult.loadTime) }));
|
|
28418
28669
|
}
|
|
28419
28670
|
}
|
|
28671
|
+
const capabilitiesRef = {};
|
|
28420
28672
|
const contextProbePromise = (async () => {
|
|
28421
28673
|
try {
|
|
28422
|
-
const probe = await
|
|
28674
|
+
const probe = await probeModel(config.provider.baseUrl, config.model);
|
|
28423
28675
|
if (!probe)
|
|
28424
28676
|
return null;
|
|
28425
|
-
if (probe.
|
|
28426
|
-
|
|
28427
|
-
|
|
28428
|
-
|
|
28677
|
+
if (probe.capabilities)
|
|
28678
|
+
capabilitiesRef.probe = probe.capabilities;
|
|
28679
|
+
const contextProbe = { model: probe.model, actual: probe.contextLength };
|
|
28680
|
+
if (probe.contextLength < config.contextWindow) {
|
|
28681
|
+
logger4.logSilent("warn", `Context probe: model "${probe.model}" is loaded with ${probe.contextLength} tokens, but contextWindow is configured as ${config.contextWindow} — overflow/429 risk. Lower contextWindow or reload the model with a larger context.`);
|
|
28682
|
+
} else if (probe.contextLength > config.contextWindow) {
|
|
28683
|
+
logger4.logSilent("info", `Context probe: model "${probe.model}" supports ${probe.contextLength} tokens — consider "mma context ${probe.contextLength}" to use the full window.`);
|
|
28429
28684
|
} else {
|
|
28430
|
-
logger4.logSilent("debug", `Context probe: configured contextWindow matches loaded context (${probe.
|
|
28685
|
+
logger4.logSilent("debug", `Context probe: configured contextWindow matches loaded context (${probe.contextLength})`);
|
|
28431
28686
|
}
|
|
28432
|
-
return
|
|
28687
|
+
return contextProbe;
|
|
28433
28688
|
} catch {
|
|
28434
28689
|
return null;
|
|
28435
28690
|
}
|
|
@@ -28608,6 +28863,14 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
|
|
|
28608
28863
|
get: () => sessionManager,
|
|
28609
28864
|
configurable: true
|
|
28610
28865
|
});
|
|
28866
|
+
Object.defineProperty(toolCtx, "capabilities", {
|
|
28867
|
+
get: () => {
|
|
28868
|
+
const cfg = configRef.current;
|
|
28869
|
+
const spec = BUILTIN_PROVIDERS.find((p) => p.type === cfg.provider.type);
|
|
28870
|
+
return resolveModelCapabilities(spec?.capabilities, capabilitiesRef.probe, cfg.modelCapabilities?.[cfg.model]);
|
|
28871
|
+
},
|
|
28872
|
+
configurable: true
|
|
28873
|
+
});
|
|
28611
28874
|
const toolExecutor = new ToolExecutor(toolRegistry, toolCtx, pluginManager);
|
|
28612
28875
|
toolCtx.llmProvider = llmProvider;
|
|
28613
28876
|
toolCtx.toolExecutor = toolExecutor;
|
|
@@ -28831,6 +29094,7 @@ var init_bootstrap = __esm(() => {
|
|
|
28831
29094
|
init_i18n();
|
|
28832
29095
|
init_agent();
|
|
28833
29096
|
init_context_log();
|
|
29097
|
+
init_capabilities();
|
|
28834
29098
|
init_version();
|
|
28835
29099
|
init_environment();
|
|
28836
29100
|
init_utils();
|
|
@@ -29719,6 +29983,87 @@ var init_setup_order = __esm(() => {
|
|
|
29719
29983
|
];
|
|
29720
29984
|
});
|
|
29721
29985
|
|
|
29986
|
+
// src/modules/session/export.ts
|
|
29987
|
+
function roleHeading(role) {
|
|
29988
|
+
switch (role) {
|
|
29989
|
+
case "user":
|
|
29990
|
+
return "User";
|
|
29991
|
+
case "assistant":
|
|
29992
|
+
return "Assistant";
|
|
29993
|
+
case "tool":
|
|
29994
|
+
return "Tool";
|
|
29995
|
+
case "system":
|
|
29996
|
+
return "System";
|
|
29997
|
+
default:
|
|
29998
|
+
return role;
|
|
29999
|
+
}
|
|
30000
|
+
}
|
|
30001
|
+
function renderSessionMarkdown(meta, messages) {
|
|
30002
|
+
const lines = [];
|
|
30003
|
+
const name = meta?.name ?? "session";
|
|
30004
|
+
const id = meta?.id ?? "unknown";
|
|
30005
|
+
lines.push(`# ${name} (${id})`);
|
|
30006
|
+
lines.push("");
|
|
30007
|
+
if (meta) {
|
|
30008
|
+
lines.push(`- Model: ${meta.model}`);
|
|
30009
|
+
lines.push(`- Created: ${meta.createdAt}`);
|
|
30010
|
+
lines.push(`- Updated: ${meta.updatedAt}`);
|
|
30011
|
+
lines.push(`- Messages: ${meta.messageCount}`);
|
|
30012
|
+
if (meta.projectDir)
|
|
30013
|
+
lines.push(`- Project: ${meta.projectDir}`);
|
|
30014
|
+
}
|
|
30015
|
+
lines.push("");
|
|
30016
|
+
lines.push("---");
|
|
30017
|
+
lines.push("");
|
|
30018
|
+
for (const msg of messages) {
|
|
30019
|
+
const heading = roleHeading(msg.role);
|
|
30020
|
+
const nameSuffix = msg.name ? ` (${msg.name})` : "";
|
|
30021
|
+
lines.push(`## ${heading}${nameSuffix}`);
|
|
30022
|
+
lines.push("");
|
|
30023
|
+
const text = getMessageText(msg.content);
|
|
30024
|
+
lines.push(text.length > 0 ? text : "_(empty)_");
|
|
30025
|
+
lines.push("");
|
|
30026
|
+
if (Array.isArray(msg.tool_calls)) {
|
|
30027
|
+
for (const tc of msg.tool_calls) {
|
|
30028
|
+
lines.push(`- tool_call: \`${tc.function.name}\` ${tc.function.arguments}`);
|
|
30029
|
+
}
|
|
30030
|
+
lines.push("");
|
|
30031
|
+
}
|
|
30032
|
+
}
|
|
30033
|
+
return lines.join(`
|
|
30034
|
+
`);
|
|
30035
|
+
}
|
|
30036
|
+
function buildSessionJson(meta, messages) {
|
|
30037
|
+
return JSON.stringify({ meta, messages }, null, 2);
|
|
30038
|
+
}
|
|
30039
|
+
function buildSessionJsonl(log2) {
|
|
30040
|
+
return log2.map((e) => JSON.stringify(e)).join(`
|
|
30041
|
+
`);
|
|
30042
|
+
}
|
|
30043
|
+
function formatExport(bundle, format) {
|
|
30044
|
+
switch (format) {
|
|
30045
|
+
case "md":
|
|
30046
|
+
return renderSessionMarkdown(bundle.meta, bundle.messages);
|
|
30047
|
+
case "json":
|
|
30048
|
+
return buildSessionJson(bundle.meta, bundle.messages);
|
|
30049
|
+
case "jsonl":
|
|
30050
|
+
return buildSessionJsonl(bundle.log);
|
|
30051
|
+
}
|
|
30052
|
+
}
|
|
30053
|
+
function redactExport(text, redact) {
|
|
30054
|
+
return redact ? redactContextSecrets(text) : text;
|
|
30055
|
+
}
|
|
30056
|
+
function sanitizeFileName(name) {
|
|
30057
|
+
const cleaned = name.replace(/[<>:"/\\|?*\u0000-\u001f]/g, "-").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^[-.]+|[-.]+$/g, "");
|
|
30058
|
+
return cleaned.length > 0 ? cleaned.slice(0, 60) : "session";
|
|
30059
|
+
}
|
|
30060
|
+
function extensionFor(format) {
|
|
30061
|
+
return format === "jsonl" ? "jsonl" : format;
|
|
30062
|
+
}
|
|
30063
|
+
var init_export = __esm(() => {
|
|
30064
|
+
init_context_log();
|
|
30065
|
+
});
|
|
30066
|
+
|
|
29722
30067
|
// src/modules/indexer/map-command.ts
|
|
29723
30068
|
async function runMapAction(module, action, query) {
|
|
29724
30069
|
const summary = async () => {
|
|
@@ -38008,6 +38353,404 @@ var init_cli = __esm(() => {
|
|
|
38008
38353
|
MMA_ROOT = findMmaRoot(HERE);
|
|
38009
38354
|
});
|
|
38010
38355
|
|
|
38356
|
+
// src/config/registry.ts
|
|
38357
|
+
function shareField(key, canonical) {
|
|
38358
|
+
const field = key === "system" ? "systemPrompt" : "responseReserve";
|
|
38359
|
+
const other = key === "system" ? "responseReserve" : "systemPrompt";
|
|
38360
|
+
return {
|
|
38361
|
+
key: canonical,
|
|
38362
|
+
aliases: [`context.${key}`],
|
|
38363
|
+
domain: "budget",
|
|
38364
|
+
valueType: "share",
|
|
38365
|
+
reconfigure: true,
|
|
38366
|
+
get: (c) => c.contextBudget[field],
|
|
38367
|
+
set: (c, v) => setBudgetShare(c, key, v),
|
|
38368
|
+
extraValidate: (c, v) => {
|
|
38369
|
+
const n = v;
|
|
38370
|
+
const total = n + c.contextBudget[other];
|
|
38371
|
+
return total > MAX_COMBINED2 ? "combined" : null;
|
|
38372
|
+
}
|
|
38373
|
+
};
|
|
38374
|
+
}
|
|
38375
|
+
function resolveConfigKey(name) {
|
|
38376
|
+
return BY_NAME.get(name) ?? null;
|
|
38377
|
+
}
|
|
38378
|
+
function configDefs() {
|
|
38379
|
+
return DEFINITIONS;
|
|
38380
|
+
}
|
|
38381
|
+
function canonicalKeys() {
|
|
38382
|
+
return DEFINITIONS.map((d) => d.key);
|
|
38383
|
+
}
|
|
38384
|
+
function keysForGroup(prefix) {
|
|
38385
|
+
return DEFINITIONS.filter((d) => d.key.startsWith(prefix + "."));
|
|
38386
|
+
}
|
|
38387
|
+
function allConfigNames() {
|
|
38388
|
+
const out = [];
|
|
38389
|
+
for (const def of DEFINITIONS) {
|
|
38390
|
+
out.push({ name: def.key, def, alias: false });
|
|
38391
|
+
for (const a of def.aliases)
|
|
38392
|
+
out.push({ name: a, def, alias: true });
|
|
38393
|
+
}
|
|
38394
|
+
return out;
|
|
38395
|
+
}
|
|
38396
|
+
function formatConfigValue(value) {
|
|
38397
|
+
if (typeof value === "boolean")
|
|
38398
|
+
return value ? "on" : "off";
|
|
38399
|
+
return String(value);
|
|
38400
|
+
}
|
|
38401
|
+
function parseBool(raw) {
|
|
38402
|
+
const v = raw.trim().toLowerCase();
|
|
38403
|
+
if (["on", "true", "1", "yes", "y", "enable", "enabled"].includes(v))
|
|
38404
|
+
return { ok: true, value: true };
|
|
38405
|
+
if (["off", "false", "0", "no", "n", "disable", "disabled"].includes(v))
|
|
38406
|
+
return { ok: true, value: false };
|
|
38407
|
+
return { ok: false, reason: "invalid" };
|
|
38408
|
+
}
|
|
38409
|
+
function parseConfigValue(def, raw) {
|
|
38410
|
+
const trimmed = raw.trim();
|
|
38411
|
+
switch (def.valueType) {
|
|
38412
|
+
case "string":
|
|
38413
|
+
return trimmed.length > 0 ? { ok: true, value: trimmed } : { ok: false, reason: "invalid" };
|
|
38414
|
+
case "bool":
|
|
38415
|
+
return parseBool(trimmed);
|
|
38416
|
+
case "enum": {
|
|
38417
|
+
const v = trimmed.toLowerCase();
|
|
38418
|
+
if (def.enumValues && !def.enumValues.includes(v))
|
|
38419
|
+
return { ok: false, reason: "invalid" };
|
|
38420
|
+
return { ok: true, value: v };
|
|
38421
|
+
}
|
|
38422
|
+
case "int": {
|
|
38423
|
+
if (!/^-?\d+$/.test(trimmed))
|
|
38424
|
+
return { ok: false, reason: "invalid" };
|
|
38425
|
+
const n = Number(trimmed);
|
|
38426
|
+
if (!Number.isFinite(n))
|
|
38427
|
+
return { ok: false, reason: "invalid" };
|
|
38428
|
+
if (def.min !== undefined && n < def.min)
|
|
38429
|
+
return { ok: false, reason: "invalid" };
|
|
38430
|
+
if (def.max !== undefined && n > def.max)
|
|
38431
|
+
return { ok: false, reason: "invalid" };
|
|
38432
|
+
return { ok: true, value: n };
|
|
38433
|
+
}
|
|
38434
|
+
case "share": {
|
|
38435
|
+
const isPct = trimmed.endsWith("%");
|
|
38436
|
+
const body = isPct ? trimmed.slice(0, -1).trim() : trimmed;
|
|
38437
|
+
if (!/^-?\d+(\.\d+)?$/.test(body))
|
|
38438
|
+
return { ok: false, reason: "invalid" };
|
|
38439
|
+
let n = Number(body);
|
|
38440
|
+
if (isPct)
|
|
38441
|
+
n = n / 100;
|
|
38442
|
+
if (!Number.isFinite(n) || n < MIN_SHARE2 || n > MAX_SHARE2)
|
|
38443
|
+
return { ok: false, reason: "invalid" };
|
|
38444
|
+
return { ok: true, value: n };
|
|
38445
|
+
}
|
|
38446
|
+
}
|
|
38447
|
+
}
|
|
38448
|
+
function getConfigValue(config, name) {
|
|
38449
|
+
const def = resolveConfigKey(name);
|
|
38450
|
+
if (!def)
|
|
38451
|
+
return { ok: false, reason: "unknown-key", input: name };
|
|
38452
|
+
const value = def.get(config);
|
|
38453
|
+
return { ok: true, key: def.key, def, value, display: formatConfigValue(value) };
|
|
38454
|
+
}
|
|
38455
|
+
function setConfigValue(config, name, raw) {
|
|
38456
|
+
const def = resolveConfigKey(name);
|
|
38457
|
+
if (!def)
|
|
38458
|
+
return { ok: false, reason: "unknown-key", input: name };
|
|
38459
|
+
if (def.readOnly)
|
|
38460
|
+
return { ok: false, reason: "read-only", input: name, key: def.key, def };
|
|
38461
|
+
const parsed = parseConfigValue(def, raw);
|
|
38462
|
+
if (!parsed.ok)
|
|
38463
|
+
return { ok: false, reason: "invalid-value", input: name, key: def.key, def };
|
|
38464
|
+
const extra = def.extraValidate?.(config, parsed.value);
|
|
38465
|
+
if (extra)
|
|
38466
|
+
return { ok: false, reason: extra, input: name, key: def.key, def };
|
|
38467
|
+
def.set(config, parsed.value);
|
|
38468
|
+
return {
|
|
38469
|
+
ok: true,
|
|
38470
|
+
key: def.key,
|
|
38471
|
+
def,
|
|
38472
|
+
value: parsed.value,
|
|
38473
|
+
display: formatConfigValue(parsed.value),
|
|
38474
|
+
reconfigure: def.reconfigure,
|
|
38475
|
+
reasoningChanged: def.key === "reasoning.mode"
|
|
38476
|
+
};
|
|
38477
|
+
}
|
|
38478
|
+
function captureConfigSnapshot(config) {
|
|
38479
|
+
const snapshot = new Map;
|
|
38480
|
+
for (const def of DEFINITIONS) {
|
|
38481
|
+
try {
|
|
38482
|
+
snapshot.set(def.key, structuredClone(def.get(config)));
|
|
38483
|
+
} catch {}
|
|
38484
|
+
}
|
|
38485
|
+
return snapshot;
|
|
38486
|
+
}
|
|
38487
|
+
var REASONING_LEVELS, LOG_LEVELS, VERBOSITY_LEVELS, LOCALES, MIN_SHARE2 = 0.05, MAX_SHARE2 = 0.9, MAX_COMBINED2 = 0.95, DEFINITIONS, BY_NAME;
|
|
38488
|
+
var init_registry2 = __esm(() => {
|
|
38489
|
+
init_defaults();
|
|
38490
|
+
init_budget();
|
|
38491
|
+
REASONING_LEVELS = [
|
|
38492
|
+
"auto",
|
|
38493
|
+
"default",
|
|
38494
|
+
"none",
|
|
38495
|
+
"low",
|
|
38496
|
+
"medium",
|
|
38497
|
+
"high",
|
|
38498
|
+
"max"
|
|
38499
|
+
];
|
|
38500
|
+
LOG_LEVELS = ["silent", "error", "warn", "info", "debug"];
|
|
38501
|
+
VERBOSITY_LEVELS = ["quiet", "normal", "verbose"];
|
|
38502
|
+
LOCALES = ["en", "ru"];
|
|
38503
|
+
DEFINITIONS = [
|
|
38504
|
+
{
|
|
38505
|
+
key: "model",
|
|
38506
|
+
aliases: [],
|
|
38507
|
+
domain: "agent",
|
|
38508
|
+
valueType: "string",
|
|
38509
|
+
reconfigure: true,
|
|
38510
|
+
get: (c) => c.model,
|
|
38511
|
+
set: (c, v) => {
|
|
38512
|
+
c.model = String(v);
|
|
38513
|
+
}
|
|
38514
|
+
},
|
|
38515
|
+
{
|
|
38516
|
+
key: "provider.active",
|
|
38517
|
+
aliases: [],
|
|
38518
|
+
domain: "provider",
|
|
38519
|
+
valueType: "string",
|
|
38520
|
+
reconfigure: true,
|
|
38521
|
+
get: (c) => c.provider.active ?? c.provider.type,
|
|
38522
|
+
set: (c, v) => {
|
|
38523
|
+
c.provider.active = String(v);
|
|
38524
|
+
},
|
|
38525
|
+
extraValidate: (c, v) => {
|
|
38526
|
+
const entries = c.provider.entries ?? [];
|
|
38527
|
+
if (entries.length === 0)
|
|
38528
|
+
return null;
|
|
38529
|
+
const name = String(v);
|
|
38530
|
+
const found = entries.some((e) => e.label === name || e.type === name);
|
|
38531
|
+
return found ? null : "invalid";
|
|
38532
|
+
}
|
|
38533
|
+
},
|
|
38534
|
+
{
|
|
38535
|
+
key: "contextWindow",
|
|
38536
|
+
aliases: ["context.window"],
|
|
38537
|
+
domain: "budget",
|
|
38538
|
+
valueType: "int",
|
|
38539
|
+
min: 1024,
|
|
38540
|
+
reconfigure: true,
|
|
38541
|
+
get: (c) => c.contextWindow,
|
|
38542
|
+
set: (c, v) => {
|
|
38543
|
+
c.contextWindow = v;
|
|
38544
|
+
}
|
|
38545
|
+
},
|
|
38546
|
+
shareField("system", "contextBudget.systemPrompt"),
|
|
38547
|
+
shareField("reserve", "contextBudget.responseReserve"),
|
|
38548
|
+
{
|
|
38549
|
+
key: "showReasoning",
|
|
38550
|
+
aliases: ["reasoning.show"],
|
|
38551
|
+
domain: "reasoning",
|
|
38552
|
+
valueType: "bool",
|
|
38553
|
+
reconfigure: false,
|
|
38554
|
+
get: (c) => c.showReasoning,
|
|
38555
|
+
set: (c, v) => {
|
|
38556
|
+
c.showReasoning = v;
|
|
38557
|
+
}
|
|
38558
|
+
},
|
|
38559
|
+
{
|
|
38560
|
+
key: "reasoning.mode",
|
|
38561
|
+
aliases: ["reasoning.level"],
|
|
38562
|
+
domain: "reasoning",
|
|
38563
|
+
valueType: "enum",
|
|
38564
|
+
enumValues: REASONING_LEVELS,
|
|
38565
|
+
reconfigure: true,
|
|
38566
|
+
get: (c) => c.reasoning?.mode ?? "auto",
|
|
38567
|
+
set: (c, v) => {
|
|
38568
|
+
const base = c.reasoning ?? structuredClone(DEFAULTS.reasoning);
|
|
38569
|
+
c.reasoning = { ...base, mode: v };
|
|
38570
|
+
}
|
|
38571
|
+
},
|
|
38572
|
+
{
|
|
38573
|
+
key: "ui.verbosity",
|
|
38574
|
+
aliases: ["verbosity"],
|
|
38575
|
+
domain: "ui",
|
|
38576
|
+
valueType: "enum",
|
|
38577
|
+
enumValues: VERBOSITY_LEVELS,
|
|
38578
|
+
reconfigure: false,
|
|
38579
|
+
get: (c) => c.ui.verbosity ?? (c.ui.verbose ? "verbose" : "quiet"),
|
|
38580
|
+
set: (c, v) => {
|
|
38581
|
+
c.ui.verbosity = v;
|
|
38582
|
+
}
|
|
38583
|
+
},
|
|
38584
|
+
{
|
|
38585
|
+
key: "maxToolIterations",
|
|
38586
|
+
aliases: [],
|
|
38587
|
+
domain: "agent",
|
|
38588
|
+
valueType: "int",
|
|
38589
|
+
min: 1,
|
|
38590
|
+
reconfigure: false,
|
|
38591
|
+
get: (c) => c.maxToolIterations,
|
|
38592
|
+
set: (c, v) => {
|
|
38593
|
+
c.maxToolIterations = v;
|
|
38594
|
+
}
|
|
38595
|
+
},
|
|
38596
|
+
{
|
|
38597
|
+
key: "stuckThreshold",
|
|
38598
|
+
aliases: [],
|
|
38599
|
+
domain: "agent",
|
|
38600
|
+
valueType: "int",
|
|
38601
|
+
min: 1,
|
|
38602
|
+
reconfigure: false,
|
|
38603
|
+
get: (c) => c.stuckThreshold,
|
|
38604
|
+
set: (c, v) => {
|
|
38605
|
+
c.stuckThreshold = v;
|
|
38606
|
+
}
|
|
38607
|
+
},
|
|
38608
|
+
{
|
|
38609
|
+
key: "logLevel",
|
|
38610
|
+
aliases: [],
|
|
38611
|
+
domain: "agent",
|
|
38612
|
+
valueType: "enum",
|
|
38613
|
+
enumValues: LOG_LEVELS,
|
|
38614
|
+
reconfigure: false,
|
|
38615
|
+
get: (c) => c.logLevel,
|
|
38616
|
+
set: (c, v) => {
|
|
38617
|
+
c.logLevel = String(v);
|
|
38618
|
+
}
|
|
38619
|
+
},
|
|
38620
|
+
{
|
|
38621
|
+
key: "locale",
|
|
38622
|
+
aliases: [],
|
|
38623
|
+
domain: "i18n",
|
|
38624
|
+
valueType: "enum",
|
|
38625
|
+
enumValues: LOCALES,
|
|
38626
|
+
reconfigure: false,
|
|
38627
|
+
get: (c) => c.locale,
|
|
38628
|
+
set: (c, v) => {
|
|
38629
|
+
c.locale = String(v);
|
|
38630
|
+
}
|
|
38631
|
+
},
|
|
38632
|
+
{
|
|
38633
|
+
key: "version",
|
|
38634
|
+
aliases: [],
|
|
38635
|
+
domain: "agent",
|
|
38636
|
+
valueType: "string",
|
|
38637
|
+
reconfigure: false,
|
|
38638
|
+
readOnly: true,
|
|
38639
|
+
get: (c) => c.version
|
|
38640
|
+
}
|
|
38641
|
+
];
|
|
38642
|
+
BY_NAME = new Map;
|
|
38643
|
+
for (const def of DEFINITIONS) {
|
|
38644
|
+
BY_NAME.set(def.key, def);
|
|
38645
|
+
for (const alias of def.aliases)
|
|
38646
|
+
BY_NAME.set(alias, def);
|
|
38647
|
+
}
|
|
38648
|
+
});
|
|
38649
|
+
|
|
38650
|
+
// src/ui/theme.ts
|
|
38651
|
+
function resolveVerbosity(ui) {
|
|
38652
|
+
if (ui?.verbosity)
|
|
38653
|
+
return ui.verbosity;
|
|
38654
|
+
return ui?.verbose ? "verbose" : "quiet";
|
|
38655
|
+
}
|
|
38656
|
+
function toolCategory(tool) {
|
|
38657
|
+
for (const [category, tools] of Object.entries(CATEGORY_TOOLS)) {
|
|
38658
|
+
if (tools.has(tool))
|
|
38659
|
+
return category;
|
|
38660
|
+
}
|
|
38661
|
+
return "meta";
|
|
38662
|
+
}
|
|
38663
|
+
function toolAccent(tool) {
|
|
38664
|
+
switch (toolCategory(tool)) {
|
|
38665
|
+
case "recon":
|
|
38666
|
+
return pc.cyan;
|
|
38667
|
+
case "mutate":
|
|
38668
|
+
return pc.magenta;
|
|
38669
|
+
case "execute":
|
|
38670
|
+
return pc.blue;
|
|
38671
|
+
case "meta":
|
|
38672
|
+
default:
|
|
38673
|
+
return pc.dim;
|
|
38674
|
+
}
|
|
38675
|
+
}
|
|
38676
|
+
function actionMarkFor(tool) {
|
|
38677
|
+
return toolAccent(tool)(glyph.action);
|
|
38678
|
+
}
|
|
38679
|
+
function successMark() {
|
|
38680
|
+
return pc.green(glyph.success);
|
|
38681
|
+
}
|
|
38682
|
+
function failureMark() {
|
|
38683
|
+
return pc.red(glyph.failure);
|
|
38684
|
+
}
|
|
38685
|
+
function formatDuration(ms) {
|
|
38686
|
+
if (ms < 1000)
|
|
38687
|
+
return `${ms}ms`;
|
|
38688
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
38689
|
+
}
|
|
38690
|
+
var glyph, CATEGORY_TOOLS;
|
|
38691
|
+
var init_theme = __esm(() => {
|
|
38692
|
+
init_colors();
|
|
38693
|
+
glyph = {
|
|
38694
|
+
action: "◇",
|
|
38695
|
+
success: "✓",
|
|
38696
|
+
failure: "✗",
|
|
38697
|
+
warning: "⚠",
|
|
38698
|
+
thinking: "✦",
|
|
38699
|
+
question: "?",
|
|
38700
|
+
user: "↵",
|
|
38701
|
+
detail: "↳",
|
|
38702
|
+
group: "│",
|
|
38703
|
+
metric: "⟡",
|
|
38704
|
+
compact: "⟳"
|
|
38705
|
+
};
|
|
38706
|
+
CATEGORY_TOOLS = {
|
|
38707
|
+
recon: new Set([
|
|
38708
|
+
"read_file",
|
|
38709
|
+
"list_dir",
|
|
38710
|
+
"glob",
|
|
38711
|
+
"grep",
|
|
38712
|
+
"file_info",
|
|
38713
|
+
"project_map",
|
|
38714
|
+
"chunk_query",
|
|
38715
|
+
"web_search",
|
|
38716
|
+
"web_fetch",
|
|
38717
|
+
"web_browse",
|
|
38718
|
+
"search_history",
|
|
38719
|
+
"recall",
|
|
38720
|
+
"session_info",
|
|
38721
|
+
"process_list",
|
|
38722
|
+
"process_log"
|
|
38723
|
+
]),
|
|
38724
|
+
mutate: new Set([
|
|
38725
|
+
"write_file",
|
|
38726
|
+
"edit_file",
|
|
38727
|
+
"create_dir",
|
|
38728
|
+
"delete_file",
|
|
38729
|
+
"move_file",
|
|
38730
|
+
"attach_image"
|
|
38731
|
+
]),
|
|
38732
|
+
execute: new Set([
|
|
38733
|
+
"bash",
|
|
38734
|
+
"process_kill",
|
|
38735
|
+
"pipeline_run",
|
|
38736
|
+
"browser",
|
|
38737
|
+
"download_file",
|
|
38738
|
+
"subagent",
|
|
38739
|
+
"mcp_call"
|
|
38740
|
+
]),
|
|
38741
|
+
meta: new Set([
|
|
38742
|
+
"plan",
|
|
38743
|
+
"todo",
|
|
38744
|
+
"verify",
|
|
38745
|
+
"lsp_check",
|
|
38746
|
+
"enable_tools",
|
|
38747
|
+
"set_thinking",
|
|
38748
|
+
"load_skill",
|
|
38749
|
+
"remember"
|
|
38750
|
+
])
|
|
38751
|
+
};
|
|
38752
|
+
});
|
|
38753
|
+
|
|
38011
38754
|
// src/cli/repl-commands.ts
|
|
38012
38755
|
var exports_repl_commands = {};
|
|
38013
38756
|
__export(exports_repl_commands, {
|
|
@@ -38015,7 +38758,8 @@ __export(exports_repl_commands, {
|
|
|
38015
38758
|
COMMAND_GROUPS: () => COMMAND_GROUPS
|
|
38016
38759
|
});
|
|
38017
38760
|
import { join as join55, dirname as dirname25 } from "path";
|
|
38018
|
-
import { existsSync as existsSync60 } from "fs";
|
|
38761
|
+
import { existsSync as existsSync60, writeFileSync as writeFileSync25, mkdirSync as mkdirSync26 } from "fs";
|
|
38762
|
+
import { homedir as homedir18 } from "os";
|
|
38019
38763
|
function registerAllCommands(ctx) {
|
|
38020
38764
|
registerBuiltinCommands(ctx);
|
|
38021
38765
|
registerMmaCommands(ctx);
|
|
@@ -38027,7 +38771,8 @@ function registerBuiltinCommands(ctx) {
|
|
|
38027
38771
|
name: "help",
|
|
38028
38772
|
description: t("repl.help"),
|
|
38029
38773
|
usage: t("repl.help_usage"),
|
|
38030
|
-
|
|
38774
|
+
examples: ["/help", "/help config"],
|
|
38775
|
+
action: (args) => ctx.showHelp(args[0])
|
|
38031
38776
|
});
|
|
38032
38777
|
ctx.registerCommand({
|
|
38033
38778
|
name: "exit",
|
|
@@ -38042,6 +38787,7 @@ function registerBuiltinCommands(ctx) {
|
|
|
38042
38787
|
usage: t("repl.clear_usage"),
|
|
38043
38788
|
action: () => {
|
|
38044
38789
|
ctx.output.clearScreen();
|
|
38790
|
+
ctx.output.writeLine(pc.dim(t("repl.clear_hint")));
|
|
38045
38791
|
}
|
|
38046
38792
|
});
|
|
38047
38793
|
}
|
|
@@ -38117,36 +38863,267 @@ function registerRunCommands(ctx) {
|
|
|
38117
38863
|
}
|
|
38118
38864
|
});
|
|
38119
38865
|
}
|
|
38866
|
+
function changeHint(def) {
|
|
38867
|
+
if (def.readOnly)
|
|
38868
|
+
return t("config.read_only_hint");
|
|
38869
|
+
return SUGAR_HINTS[def.key] ?? `/config ${def.key} <value>`;
|
|
38870
|
+
}
|
|
38871
|
+
function configValueHint(def) {
|
|
38872
|
+
if (!def)
|
|
38873
|
+
return "";
|
|
38874
|
+
switch (def.valueType) {
|
|
38875
|
+
case "enum":
|
|
38876
|
+
return t("config.hint_enum", { values: (def.enumValues ?? []).join(", ") });
|
|
38877
|
+
case "bool":
|
|
38878
|
+
return t("config.hint_bool");
|
|
38879
|
+
case "share":
|
|
38880
|
+
return t("config.hint_share");
|
|
38881
|
+
case "int":
|
|
38882
|
+
return t("config.hint_int", { min: String(def.min ?? 1) });
|
|
38883
|
+
default:
|
|
38884
|
+
return t("config.hint_string");
|
|
38885
|
+
}
|
|
38886
|
+
}
|
|
38887
|
+
function editDistance(a, b) {
|
|
38888
|
+
const dp = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
38889
|
+
for (let i = 1;i <= a.length; i++) {
|
|
38890
|
+
let prev = dp[0];
|
|
38891
|
+
dp[0] = i;
|
|
38892
|
+
for (let j = 1;j <= b.length; j++) {
|
|
38893
|
+
const tmp = dp[j];
|
|
38894
|
+
dp[j] = Math.min(dp[j] + 1, dp[j - 1] + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
38895
|
+
prev = tmp;
|
|
38896
|
+
}
|
|
38897
|
+
}
|
|
38898
|
+
return dp[b.length];
|
|
38899
|
+
}
|
|
38900
|
+
function nearestConfigKey(input) {
|
|
38901
|
+
const names = canonicalKeys();
|
|
38902
|
+
let best = null;
|
|
38903
|
+
for (const name of names) {
|
|
38904
|
+
const d = editDistance(input.toLowerCase(), name.toLowerCase());
|
|
38905
|
+
if (best === null || d < best.dist)
|
|
38906
|
+
best = { name, dist: d };
|
|
38907
|
+
}
|
|
38908
|
+
if (!best)
|
|
38909
|
+
return null;
|
|
38910
|
+
const threshold = Math.max(2, Math.floor(best.name.length / 3));
|
|
38911
|
+
return best.dist <= threshold ? best.name : null;
|
|
38912
|
+
}
|
|
38913
|
+
function renderConfigError(ctx, result) {
|
|
38914
|
+
const key = result.key ?? result.input;
|
|
38915
|
+
switch (result.reason) {
|
|
38916
|
+
case "unknown-key": {
|
|
38917
|
+
const suggestion = nearestConfigKey(result.input);
|
|
38918
|
+
const suffix = suggestion ? t("config.suggest", { name: suggestion }) : t("config.valid_keys", { keys: canonicalKeys().join(", ") });
|
|
38919
|
+
ctx.output.writeLine(pc.yellow(t("config.unknown_key", { key: result.input, suggestion: suffix })), "stderr");
|
|
38920
|
+
return;
|
|
38921
|
+
}
|
|
38922
|
+
case "read-only":
|
|
38923
|
+
ctx.output.writeLine(pc.yellow(t("config.read_only", { key })), "stderr");
|
|
38924
|
+
return;
|
|
38925
|
+
case "range":
|
|
38926
|
+
ctx.output.writeLine(pc.yellow(t("config.range", { key })), "stderr");
|
|
38927
|
+
return;
|
|
38928
|
+
case "combined":
|
|
38929
|
+
ctx.output.writeLine(pc.yellow(t("config.combined")), "stderr");
|
|
38930
|
+
return;
|
|
38931
|
+
default:
|
|
38932
|
+
ctx.output.writeLine(pc.yellow(t("config.invalid_value", { key, hint: configValueHint(result.def) })), "stderr");
|
|
38933
|
+
}
|
|
38934
|
+
}
|
|
38935
|
+
function applyConfigSideEffects(ctx, result) {
|
|
38936
|
+
if (result.key === "ui.verbosity") {
|
|
38937
|
+
ctx.output.setSuppressInfoLogs(result.value === "quiet");
|
|
38938
|
+
} else if (result.key === "reasoning.mode") {
|
|
38939
|
+
ctx.agent.setReasoningLevel(result.value);
|
|
38940
|
+
} else if (result.key === "locale") {
|
|
38941
|
+
setLocale(result.value);
|
|
38942
|
+
}
|
|
38943
|
+
}
|
|
38944
|
+
function persistConfig(ctx) {
|
|
38945
|
+
const configPath = join55(ctx.configDir, "config.json");
|
|
38946
|
+
saveConfig(ctx.config, configPath, dirname25(configPath));
|
|
38947
|
+
}
|
|
38948
|
+
async function mutateConfig(ctx, key, raw) {
|
|
38949
|
+
const result = setConfigValue(ctx.config, key, raw);
|
|
38950
|
+
if (!result.ok)
|
|
38951
|
+
return result;
|
|
38952
|
+
applyConfigSideEffects(ctx, result);
|
|
38953
|
+
persistConfig(ctx);
|
|
38954
|
+
if (result.reconfigure)
|
|
38955
|
+
await ctx.agent.reconfigure(ctx.config);
|
|
38956
|
+
if (result.key === "locale")
|
|
38957
|
+
ctx.reregisterCommands();
|
|
38958
|
+
return result;
|
|
38959
|
+
}
|
|
38960
|
+
function reportSaved(ctx, result) {
|
|
38961
|
+
ctx.output.writeLine(pc.green(t("config.saved", { key: result.key })));
|
|
38962
|
+
}
|
|
38963
|
+
function rawFromValue(value) {
|
|
38964
|
+
if (typeof value === "boolean")
|
|
38965
|
+
return value ? "on" : "off";
|
|
38966
|
+
return String(value);
|
|
38967
|
+
}
|
|
38968
|
+
function printConfigTable(ctx, defs) {
|
|
38969
|
+
const list = defs ?? configDefs();
|
|
38970
|
+
const rows = list.map((def) => [
|
|
38971
|
+
def.key,
|
|
38972
|
+
formatConfigValue(def.get(ctx.config)),
|
|
38973
|
+
def.domain,
|
|
38974
|
+
changeHint(def)
|
|
38975
|
+
]);
|
|
38976
|
+
ctx.output.writeLine(pc.bold(t("config.header")));
|
|
38977
|
+
for (const line of renderTable([
|
|
38978
|
+
t("config.col_setting"),
|
|
38979
|
+
t("config.col_value"),
|
|
38980
|
+
t("config.col_domain"),
|
|
38981
|
+
t("config.col_change")
|
|
38982
|
+
], rows)) {
|
|
38983
|
+
ctx.output.writeLine(line);
|
|
38984
|
+
}
|
|
38985
|
+
const meta = ctx.sessionManager?.getActiveMeta();
|
|
38986
|
+
if (meta) {
|
|
38987
|
+
ctx.output.writeLine(pc.dim(t("config.session_line", {
|
|
38988
|
+
name: meta.name,
|
|
38989
|
+
id: meta.id,
|
|
38990
|
+
count: String(meta.messageCount)
|
|
38991
|
+
})));
|
|
38992
|
+
}
|
|
38993
|
+
ctx.output.writeLine(pc.dim(t("config.usage_hint")));
|
|
38994
|
+
}
|
|
38995
|
+
function confirm(ctx, prompt) {
|
|
38996
|
+
return new Promise((resolve25) => {
|
|
38997
|
+
ctx.withExclusiveInput(async () => {
|
|
38998
|
+
await new Promise((done) => {
|
|
38999
|
+
ctx.rl.question(prompt, (answer) => {
|
|
39000
|
+
resolve25(/^y(es)?$/i.test(answer.trim()));
|
|
39001
|
+
done();
|
|
39002
|
+
});
|
|
39003
|
+
});
|
|
39004
|
+
});
|
|
39005
|
+
});
|
|
39006
|
+
}
|
|
39007
|
+
async function runConfigReset(ctx, rest) {
|
|
39008
|
+
const snapshot = ctx.getConfigSnapshot();
|
|
39009
|
+
const yes = rest.includes("--yes");
|
|
39010
|
+
const all = rest.includes("--all");
|
|
39011
|
+
const target = rest.find((a) => !a.startsWith("--"));
|
|
39012
|
+
if (all) {
|
|
39013
|
+
const changed = canonicalKeys().filter((k) => {
|
|
39014
|
+
const def2 = resolveConfigKey(k);
|
|
39015
|
+
if (!def2 || !snapshot.has(k))
|
|
39016
|
+
return false;
|
|
39017
|
+
return rawFromValue(def2.get(ctx.config)) !== rawFromValue(snapshot.get(k));
|
|
39018
|
+
});
|
|
39019
|
+
if (changed.length === 0) {
|
|
39020
|
+
ctx.output.writeLine(t("config.reset_none"));
|
|
39021
|
+
return;
|
|
39022
|
+
}
|
|
39023
|
+
if (!yes) {
|
|
39024
|
+
if (!process.stdin.isTTY) {
|
|
39025
|
+
ctx.output.writeLine(pc.yellow(t("config.reset_all_needs_yes")), "stderr");
|
|
39026
|
+
return;
|
|
39027
|
+
}
|
|
39028
|
+
const ok = await confirm(ctx, t("config.reset_all_confirm", { count: String(changed.length) }));
|
|
39029
|
+
if (!ok) {
|
|
39030
|
+
ctx.output.writeLine(t("config.reset_cancelled"));
|
|
39031
|
+
return;
|
|
39032
|
+
}
|
|
39033
|
+
}
|
|
39034
|
+
let anyReconfig = false;
|
|
39035
|
+
let localeChanged = false;
|
|
39036
|
+
for (const k of changed) {
|
|
39037
|
+
const result2 = setConfigValue(ctx.config, k, rawFromValue(snapshot.get(k)));
|
|
39038
|
+
if (result2.ok) {
|
|
39039
|
+
applyConfigSideEffects(ctx, result2);
|
|
39040
|
+
anyReconfig = anyReconfig || result2.reconfigure;
|
|
39041
|
+
localeChanged = localeChanged || result2.key === "locale";
|
|
39042
|
+
}
|
|
39043
|
+
}
|
|
39044
|
+
persistConfig(ctx);
|
|
39045
|
+
if (anyReconfig)
|
|
39046
|
+
await ctx.agent.reconfigure(ctx.config);
|
|
39047
|
+
if (localeChanged)
|
|
39048
|
+
ctx.reregisterCommands();
|
|
39049
|
+
ctx.output.writeLine(pc.green(t("config.reset_all_done", { count: String(changed.length) })));
|
|
39050
|
+
return;
|
|
39051
|
+
}
|
|
39052
|
+
if (!target) {
|
|
39053
|
+
ctx.output.writeLine(t("config.reset_usage"));
|
|
39054
|
+
return;
|
|
39055
|
+
}
|
|
39056
|
+
const def = resolveConfigKey(target);
|
|
39057
|
+
if (!def) {
|
|
39058
|
+
renderConfigError(ctx, { reason: "unknown-key", input: target });
|
|
39059
|
+
return;
|
|
39060
|
+
}
|
|
39061
|
+
if (def.readOnly || !snapshot.has(def.key)) {
|
|
39062
|
+
ctx.output.writeLine(t("config.reset_unchanged", { key: def.key }));
|
|
39063
|
+
return;
|
|
39064
|
+
}
|
|
39065
|
+
if (rawFromValue(def.get(ctx.config)) === rawFromValue(snapshot.get(def.key))) {
|
|
39066
|
+
ctx.output.writeLine(t("config.reset_unchanged", { key: def.key }));
|
|
39067
|
+
return;
|
|
39068
|
+
}
|
|
39069
|
+
const result = await mutateConfig(ctx, def.key, rawFromValue(snapshot.get(def.key)));
|
|
39070
|
+
if (!result.ok) {
|
|
39071
|
+
renderConfigError(ctx, result);
|
|
39072
|
+
return;
|
|
39073
|
+
}
|
|
39074
|
+
ctx.output.writeLine(pc.green(t("config.reset_ok", { key: result.key, value: result.display })));
|
|
39075
|
+
}
|
|
39076
|
+
function printReasoningStatus(ctx) {
|
|
39077
|
+
const display = ctx.config.showReasoning ? t("reasoning.on") : t("reasoning.off");
|
|
39078
|
+
const mode = ctx.config.reasoning?.mode ?? "auto";
|
|
39079
|
+
const auto = mode === "auto" ? t("reasoning.auto_on") : t("reasoning.auto_off");
|
|
39080
|
+
ctx.output.writeLine(t("reasoning.status", { display, level: mode, auto }));
|
|
39081
|
+
}
|
|
38120
39082
|
function registerConfigCommands(ctx) {
|
|
38121
39083
|
ctx.registerCommand({
|
|
38122
39084
|
name: "config",
|
|
38123
39085
|
description: t("repl.config"),
|
|
38124
39086
|
usage: t("repl.config_usage"),
|
|
38125
|
-
|
|
39087
|
+
examples: ["/config", "/config model", "/config reasoning.mode high", "/config reset ui.verbosity"],
|
|
39088
|
+
action: async (args) => {
|
|
38126
39089
|
if ((args[0] ?? "").trim().toLowerCase() === "migrate") {
|
|
38127
39090
|
return runConfigMigrate(ctx);
|
|
38128
39091
|
}
|
|
38129
|
-
|
|
38130
|
-
|
|
38131
|
-
|
|
38132
|
-
|
|
38133
|
-
|
|
38134
|
-
|
|
38135
|
-
|
|
38136
|
-
|
|
38137
|
-
|
|
38138
|
-
|
|
38139
|
-
|
|
38140
|
-
|
|
38141
|
-
|
|
38142
|
-
|
|
38143
|
-
|
|
38144
|
-
|
|
38145
|
-
|
|
38146
|
-
|
|
38147
|
-
|
|
38148
|
-
|
|
38149
|
-
ctx.output.writeLine(`${
|
|
39092
|
+
if (args.length === 0) {
|
|
39093
|
+
printConfigTable(ctx);
|
|
39094
|
+
return;
|
|
39095
|
+
}
|
|
39096
|
+
if (args[0] === "reset") {
|
|
39097
|
+
await runConfigReset(ctx, args.slice(1));
|
|
39098
|
+
return;
|
|
39099
|
+
}
|
|
39100
|
+
const name = args[0];
|
|
39101
|
+
if (args.length === 1) {
|
|
39102
|
+
const group = keysForGroup(name);
|
|
39103
|
+
if (group.length > 0) {
|
|
39104
|
+
printConfigTable(ctx, group);
|
|
39105
|
+
return;
|
|
39106
|
+
}
|
|
39107
|
+
const got = getConfigValue(ctx.config, name);
|
|
39108
|
+
if (!got.ok) {
|
|
39109
|
+
renderConfigError(ctx, got);
|
|
39110
|
+
return;
|
|
39111
|
+
}
|
|
39112
|
+
ctx.output.writeLine(`${got.key} = ${got.display}`);
|
|
39113
|
+
return;
|
|
39114
|
+
}
|
|
39115
|
+
const raw = args.slice(1).join(" ");
|
|
39116
|
+
const result = await mutateConfig(ctx, name, raw);
|
|
39117
|
+
if (!result.ok) {
|
|
39118
|
+
renderConfigError(ctx, result);
|
|
39119
|
+
return;
|
|
39120
|
+
}
|
|
39121
|
+
reportSaved(ctx, result);
|
|
39122
|
+
if (result.key === "model") {
|
|
39123
|
+
const known = ctx.knownModels();
|
|
39124
|
+
if (known.length > 0 && !known.includes(String(result.value))) {
|
|
39125
|
+
ctx.output.writeLine(pc.yellow(t("model.not_in_list", { name: String(result.value) })));
|
|
39126
|
+
}
|
|
38150
39127
|
}
|
|
38151
39128
|
}
|
|
38152
39129
|
});
|
|
@@ -38154,37 +39131,60 @@ function registerConfigCommands(ctx) {
|
|
|
38154
39131
|
name: "reasoning",
|
|
38155
39132
|
description: t("repl.reasoning"),
|
|
38156
39133
|
usage: t("repl.reasoning_usage"),
|
|
38157
|
-
|
|
38158
|
-
|
|
38159
|
-
const
|
|
38160
|
-
if (!
|
|
38161
|
-
ctx
|
|
38162
|
-
|
|
38163
|
-
|
|
38164
|
-
|
|
38165
|
-
|
|
38166
|
-
ctx
|
|
38167
|
-
|
|
38168
|
-
|
|
39134
|
+
examples: ["/reasoning", "/reasoning show", "/reasoning level high"],
|
|
39135
|
+
action: async (args) => {
|
|
39136
|
+
const sub = args[0]?.trim().toLowerCase();
|
|
39137
|
+
if (!sub) {
|
|
39138
|
+
printReasoningStatus(ctx);
|
|
39139
|
+
return;
|
|
39140
|
+
}
|
|
39141
|
+
if (sub === "show" || sub === "on" || sub === "hide" || sub === "off") {
|
|
39142
|
+
const on = sub === "show" || sub === "on";
|
|
39143
|
+
const result = await mutateConfig(ctx, "showReasoning", on ? "on" : "off");
|
|
39144
|
+
if (!result.ok) {
|
|
39145
|
+
renderConfigError(ctx, result);
|
|
39146
|
+
return;
|
|
39147
|
+
}
|
|
39148
|
+
ctx.output.writeLine(pc.green(t("reasoning.display_set", { state: on ? t("reasoning.on") : t("reasoning.off") })));
|
|
39149
|
+
return;
|
|
39150
|
+
}
|
|
39151
|
+
if (sub === "level") {
|
|
39152
|
+
const lvl = args[1]?.trim().toLowerCase();
|
|
39153
|
+
if (!lvl) {
|
|
39154
|
+
ctx.output.writeLine(t("repl.reasoning_usage"));
|
|
39155
|
+
return;
|
|
39156
|
+
}
|
|
39157
|
+
const result = await mutateConfig(ctx, "reasoning.mode", lvl);
|
|
39158
|
+
if (!result.ok) {
|
|
39159
|
+
renderConfigError(ctx, result);
|
|
39160
|
+
return;
|
|
39161
|
+
}
|
|
39162
|
+
ctx.output.writeLine(pc.green(t("repl.reasoning_level_set", { level: lvl })));
|
|
39163
|
+
if (lvl !== "auto")
|
|
39164
|
+
ctx.output.writeLine(pc.dim(t("reasoning.auto_off_hint")));
|
|
39165
|
+
return;
|
|
38169
39166
|
}
|
|
39167
|
+
ctx.output.writeLine(pc.yellow(t("reasoning.unknown_sub", { sub })));
|
|
39168
|
+
ctx.output.writeLine(t("repl.reasoning_usage"));
|
|
38170
39169
|
}
|
|
38171
39170
|
});
|
|
38172
39171
|
ctx.registerCommand({
|
|
38173
39172
|
name: "verbose",
|
|
38174
39173
|
description: t("repl.verbose"),
|
|
38175
39174
|
usage: t("repl.verbose_usage"),
|
|
38176
|
-
|
|
38177
|
-
|
|
39175
|
+
examples: ["/verbose", "/verbose normal"],
|
|
39176
|
+
action: async (args) => {
|
|
38178
39177
|
const level = args[0]?.trim().toLowerCase();
|
|
38179
|
-
if (
|
|
38180
|
-
ctx.output.writeLine(
|
|
39178
|
+
if (!level) {
|
|
39179
|
+
ctx.output.writeLine(t("verbose.status", { level: resolveVerbosity(ctx.config.ui) }));
|
|
38181
39180
|
return;
|
|
38182
39181
|
}
|
|
38183
|
-
const
|
|
38184
|
-
|
|
38185
|
-
|
|
38186
|
-
|
|
38187
|
-
|
|
39182
|
+
const result = await mutateConfig(ctx, "ui.verbosity", level);
|
|
39183
|
+
if (!result.ok) {
|
|
39184
|
+
renderConfigError(ctx, result);
|
|
39185
|
+
return;
|
|
39186
|
+
}
|
|
39187
|
+
ctx.output.writeLine(pc.green(t("repl.verbose_set", { level: result.display })));
|
|
38188
39188
|
}
|
|
38189
39189
|
});
|
|
38190
39190
|
ctx.registerCommand({
|
|
@@ -38194,16 +39194,13 @@ function registerConfigCommands(ctx) {
|
|
|
38194
39194
|
action: () => {
|
|
38195
39195
|
const providers = ctx.agent.listProviders();
|
|
38196
39196
|
const active = providers.find((p) => p.active);
|
|
38197
|
-
|
|
38198
|
-
|
|
38199
|
-
ctx.output.writeLine(`${t("repl.provider")} ${active.label} (${pc.dim(active.type)}) @ ${pc.dim(active.baseUrl)}`);
|
|
38200
|
-
} else {
|
|
38201
|
-
ctx.output.writeLine(`${t("repl.provider")} ${ctx.config.provider.type} @ ${pc.dim(ctx.config.provider.baseUrl)}`);
|
|
38202
|
-
}
|
|
39197
|
+
const providerLabel = active ? active.label : ctx.config.provider.type;
|
|
39198
|
+
const parts = [ctx.config.model, providerLabel];
|
|
38203
39199
|
const meta = ctx.sessionManager?.getActiveMeta();
|
|
38204
|
-
if (meta)
|
|
38205
|
-
|
|
38206
|
-
}
|
|
39200
|
+
if (meta)
|
|
39201
|
+
parts.push(`${meta.name} (${meta.messageCount} ${t("repl.msgs")})`);
|
|
39202
|
+
parts.push(`${ctx.config.contextWindow} tok`);
|
|
39203
|
+
ctx.output.writeLine(parts.join(pc.dim(" · ")));
|
|
38207
39204
|
}
|
|
38208
39205
|
});
|
|
38209
39206
|
ctx.registerCommand({
|
|
@@ -38226,22 +39223,28 @@ function registerConfigCommands(ctx) {
|
|
|
38226
39223
|
ctx.registerCommand({
|
|
38227
39224
|
name: "sysprompt",
|
|
38228
39225
|
description: t("repl.sysprompt_desc"),
|
|
38229
|
-
usage: t("repl.
|
|
38230
|
-
|
|
39226
|
+
usage: t("repl.sysprompt_usage"),
|
|
39227
|
+
examples: ["/sysprompt", "/sysprompt --full"],
|
|
39228
|
+
action: (args) => {
|
|
38231
39229
|
const info = ctx.agent.getSystemPromptInfo();
|
|
39230
|
+
const full = args.includes("--full");
|
|
38232
39231
|
ctx.output.writeLine(pc.bold(t("repl.sysprompt_tokens", { count: String(info.tokenCount) })));
|
|
38233
|
-
ctx.output.writeLine(pc.dim("─".repeat(60)));
|
|
38234
|
-
for (const line of info.text.split(`
|
|
38235
|
-
`)) {
|
|
38236
|
-
ctx.output.writeLine(line);
|
|
38237
|
-
}
|
|
38238
|
-
ctx.output.writeLine(pc.dim("─".repeat(60)));
|
|
38239
39232
|
if (info.excluded.length > 0) {
|
|
38240
39233
|
ctx.output.writeLine(pc.yellow(t("repl.excluded_blocks", { count: String(info.excluded.length) })));
|
|
38241
39234
|
for (const e of info.excluded) {
|
|
38242
39235
|
ctx.output.writeLine(pc.dim(` - ${e.slice(0, 80)}${e.length > 80 ? "..." : ""}`));
|
|
38243
39236
|
}
|
|
38244
39237
|
}
|
|
39238
|
+
if (full) {
|
|
39239
|
+
ctx.output.writeLine(pc.dim("─".repeat(60)));
|
|
39240
|
+
for (const line of info.text.split(`
|
|
39241
|
+
`)) {
|
|
39242
|
+
ctx.output.writeLine(line);
|
|
39243
|
+
}
|
|
39244
|
+
ctx.output.writeLine(pc.dim("─".repeat(60)));
|
|
39245
|
+
} else {
|
|
39246
|
+
ctx.output.writeLine(pc.dim(t("repl.sysprompt_full_hint")));
|
|
39247
|
+
}
|
|
38245
39248
|
}
|
|
38246
39249
|
});
|
|
38247
39250
|
ctx.registerCommand({
|
|
@@ -38281,13 +39284,14 @@ function registerProviderCommands(ctx) {
|
|
|
38281
39284
|
ctx.output.writeLine(t("repl.provider_usage"));
|
|
38282
39285
|
return;
|
|
38283
39286
|
}
|
|
38284
|
-
|
|
38285
|
-
|
|
38286
|
-
ctx
|
|
38287
|
-
|
|
38288
|
-
} catch (e) {
|
|
38289
|
-
ctx.output.writeLine(pc.red(e.message), "stderr");
|
|
39287
|
+
const result = await mutateConfig(ctx, "provider.active", name);
|
|
39288
|
+
if (!result.ok) {
|
|
39289
|
+
renderConfigError(ctx, result);
|
|
39290
|
+
return;
|
|
38290
39291
|
}
|
|
39292
|
+
ctx.refreshModelCache();
|
|
39293
|
+
ctx.output.writeLine(pc.green(t("repl.provider_set", { name })));
|
|
39294
|
+
reportSaved(ctx, result);
|
|
38291
39295
|
};
|
|
38292
39296
|
const add = async (args) => {
|
|
38293
39297
|
const flags = {};
|
|
@@ -38310,6 +39314,13 @@ function registerProviderCommands(ctx) {
|
|
|
38310
39314
|
ctx.output.writeLine(t("repl.provider_usage"));
|
|
38311
39315
|
return;
|
|
38312
39316
|
}
|
|
39317
|
+
for (const flag of ["priority", "context-window", "rpm", "parallel"]) {
|
|
39318
|
+
const v = flags[flag];
|
|
39319
|
+
if (v !== undefined && !Number.isFinite(Number(v))) {
|
|
39320
|
+
ctx.output.writeLine(pc.red(t("repl.provider_add_invalid_number", { flag: `--${flag}`, value: v })), "stderr");
|
|
39321
|
+
return;
|
|
39322
|
+
}
|
|
39323
|
+
}
|
|
38313
39324
|
const entries = Array.isArray(ctx.config.provider.entries) ? ctx.config.provider.entries : [];
|
|
38314
39325
|
if (entries.length === 0) {
|
|
38315
39326
|
entries.push({
|
|
@@ -38340,8 +39351,7 @@ function registerProviderCommands(ctx) {
|
|
|
38340
39351
|
});
|
|
38341
39352
|
ctx.config.provider.entries = entries;
|
|
38342
39353
|
ctx.config.provider.active = ctx.config.provider.active || ctx.config.provider.type;
|
|
38343
|
-
|
|
38344
|
-
saveConfig(ctx.config, configPath, dirname25(configPath));
|
|
39354
|
+
persistConfig(ctx);
|
|
38345
39355
|
await ctx.agent.reconfigure(ctx.config);
|
|
38346
39356
|
ctx.output.writeLine(pc.green(t("cli.provider_added", { name })));
|
|
38347
39357
|
ctx.output.writeLine(t("repl.provider_switch_hint", { name }));
|
|
@@ -38355,10 +39365,12 @@ function registerProviderCommands(ctx) {
|
|
|
38355
39365
|
name: "provider",
|
|
38356
39366
|
description: t("repl.provider_list"),
|
|
38357
39367
|
usage: t("repl.provider_usage"),
|
|
39368
|
+
examples: ["/provider list", "/provider use openrouter", "/provider add openai --key sk-..."],
|
|
38358
39369
|
action: async (args) => {
|
|
38359
39370
|
const subcmd = args[0];
|
|
38360
39371
|
const handler = subcmd ? handlers[subcmd] : handlers.list;
|
|
38361
39372
|
if (!handler) {
|
|
39373
|
+
ctx.output.writeLine(pc.yellow(t("repl.unknown_sub", { cmd: "provider", sub: subcmd })));
|
|
38362
39374
|
ctx.output.writeLine(t("repl.provider_usage"));
|
|
38363
39375
|
return;
|
|
38364
39376
|
}
|
|
@@ -38406,11 +39418,17 @@ function registerProviderCommands(ctx) {
|
|
|
38406
39418
|
ctx.output.writeLine(t("repl.model_usage"));
|
|
38407
39419
|
return;
|
|
38408
39420
|
}
|
|
38409
|
-
ctx
|
|
38410
|
-
|
|
38411
|
-
|
|
38412
|
-
|
|
39421
|
+
const result = await mutateConfig(ctx, "model", name);
|
|
39422
|
+
if (!result.ok) {
|
|
39423
|
+
renderConfigError(ctx, result);
|
|
39424
|
+
return;
|
|
39425
|
+
}
|
|
38413
39426
|
ctx.output.writeLine(pc.green(t("repl.model_set", { name })));
|
|
39427
|
+
const known = ctx.knownModels();
|
|
39428
|
+
if (known.length > 0 && !known.includes(name)) {
|
|
39429
|
+
ctx.output.writeLine(pc.yellow(t("model.not_in_list", { name })));
|
|
39430
|
+
}
|
|
39431
|
+
reportSaved(ctx, result);
|
|
38414
39432
|
};
|
|
38415
39433
|
const modelHandlers = {
|
|
38416
39434
|
list: listModels,
|
|
@@ -38420,10 +39438,12 @@ function registerProviderCommands(ctx) {
|
|
|
38420
39438
|
name: "model",
|
|
38421
39439
|
description: t("repl.model_list"),
|
|
38422
39440
|
usage: t("repl.model_usage"),
|
|
39441
|
+
examples: ["/model list", "/model use qwen/qwen3.5-9b"],
|
|
38423
39442
|
action: async (args) => {
|
|
38424
39443
|
const subcmd = args[0];
|
|
38425
39444
|
const handler = subcmd ? modelHandlers[subcmd] : modelHandlers.list;
|
|
38426
39445
|
if (!handler) {
|
|
39446
|
+
ctx.output.writeLine(pc.yellow(t("repl.unknown_sub", { cmd: "model", sub: subcmd })));
|
|
38427
39447
|
ctx.output.writeLine(t("repl.model_usage"));
|
|
38428
39448
|
return;
|
|
38429
39449
|
}
|
|
@@ -38434,12 +39454,8 @@ function registerProviderCommands(ctx) {
|
|
|
38434
39454
|
name: "context",
|
|
38435
39455
|
description: t("cli.manage_context"),
|
|
38436
39456
|
usage: t("repl.context_usage"),
|
|
39457
|
+
examples: ["/context", "/context 64000", "/context system 10%", "/context reserve 0.2"],
|
|
38437
39458
|
action: async (args) => {
|
|
38438
|
-
const save = async () => {
|
|
38439
|
-
const configPath = join55(ctx.configDir, "config.json");
|
|
38440
|
-
saveConfig(ctx.config, configPath, dirname25(configPath));
|
|
38441
|
-
await ctx.agent.reconfigure(ctx.config);
|
|
38442
|
-
};
|
|
38443
39459
|
if (args.length === 0) {
|
|
38444
39460
|
for (const line of budgetBreakdownLines(ctx.config))
|
|
38445
39461
|
ctx.output.writeLine(line);
|
|
@@ -38447,24 +39463,32 @@ function registerProviderCommands(ctx) {
|
|
|
38447
39463
|
return;
|
|
38448
39464
|
}
|
|
38449
39465
|
if (args[0] === "system" || args[0] === "reserve") {
|
|
38450
|
-
const
|
|
38451
|
-
|
|
38452
|
-
|
|
38453
|
-
ctx.output.writeLine(pc.yellow(t("cli.context_invalid_fraction")));
|
|
39466
|
+
const raw = args[1];
|
|
39467
|
+
if (!raw) {
|
|
39468
|
+
ctx.output.writeLine(t("repl.context_usage"));
|
|
38454
39469
|
return;
|
|
38455
39470
|
}
|
|
38456
|
-
|
|
38457
|
-
ctx
|
|
39471
|
+
const key = args[0] === "system" ? "contextBudget.systemPrompt" : "contextBudget.responseReserve";
|
|
39472
|
+
const result2 = await mutateConfig(ctx, key, raw);
|
|
39473
|
+
if (!result2.ok) {
|
|
39474
|
+
renderConfigError(ctx, result2);
|
|
39475
|
+
return;
|
|
39476
|
+
}
|
|
39477
|
+
ctx.output.writeLine(pc.green(t("cli.context_fraction_set", { key: args[0], value: result2.display })));
|
|
39478
|
+
return;
|
|
39479
|
+
}
|
|
39480
|
+
if (!/^\d+$/.test(args[0])) {
|
|
39481
|
+
ctx.output.writeLine(pc.yellow(t("context.unknown_arg", { arg: args[0] })));
|
|
39482
|
+
ctx.output.writeLine(t("repl.context_usage"));
|
|
38458
39483
|
return;
|
|
38459
39484
|
}
|
|
38460
|
-
const
|
|
38461
|
-
if (
|
|
38462
|
-
ctx
|
|
39485
|
+
const result = await mutateConfig(ctx, "contextWindow", args[0]);
|
|
39486
|
+
if (!result.ok) {
|
|
39487
|
+
renderConfigError(ctx, result);
|
|
38463
39488
|
return;
|
|
38464
39489
|
}
|
|
38465
|
-
ctx.
|
|
38466
|
-
|
|
38467
|
-
ctx.output.writeLine(pc.green(t("cli.context_set", { size })));
|
|
39490
|
+
ctx.output.writeLine(pc.green(t("cli.context_set", { size: String(result.value) })));
|
|
39491
|
+
reportSaved(ctx, result);
|
|
38468
39492
|
}
|
|
38469
39493
|
});
|
|
38470
39494
|
}
|
|
@@ -38523,15 +39547,15 @@ function registerLspCommands(ctx) {
|
|
|
38523
39547
|
name: "lsp",
|
|
38524
39548
|
description: t("repl.lsp"),
|
|
38525
39549
|
usage: t("repl.lsp_usage"),
|
|
39550
|
+
examples: ["/lsp status", "/lsp restart", "/lsp check src/index.ts"],
|
|
38526
39551
|
action: async (args) => {
|
|
38527
|
-
const subcommand = args[0] || "status";
|
|
38528
39552
|
const lspModule = ctx.agent.getModule("lsp");
|
|
38529
39553
|
if (!lspModule) {
|
|
38530
39554
|
ctx.output.writeLine(pc.yellow(t("repl.lsp_not_available")));
|
|
38531
39555
|
return;
|
|
38532
39556
|
}
|
|
38533
|
-
|
|
38534
|
-
|
|
39557
|
+
const handlers = {
|
|
39558
|
+
status: () => {
|
|
38535
39559
|
const disabled = lspModule.getDisabledServers();
|
|
38536
39560
|
const failures = lspModule.getFailureCounts();
|
|
38537
39561
|
const config = ctx.config.lsp;
|
|
@@ -38549,16 +39573,14 @@ function registerLspCommands(ctx) {
|
|
|
38549
39573
|
if (disabled.length === 0 && failures.size === 0) {
|
|
38550
39574
|
ctx.output.writeLine(pc.green(t("repl.lsp_all_ok")));
|
|
38551
39575
|
}
|
|
38552
|
-
|
|
38553
|
-
|
|
38554
|
-
case "restart": {
|
|
39576
|
+
},
|
|
39577
|
+
restart: () => {
|
|
38555
39578
|
ctx.output.writeLine(pc.yellow(t("repl.lsp_restarting")));
|
|
38556
39579
|
lspModule.resetDisabledServers();
|
|
38557
39580
|
ctx.output.writeLine(pc.green(t("repl.lsp_restarted")));
|
|
38558
|
-
|
|
38559
|
-
|
|
38560
|
-
|
|
38561
|
-
const path = args[1];
|
|
39581
|
+
},
|
|
39582
|
+
check: async (rest) => {
|
|
39583
|
+
const path = rest[0];
|
|
38562
39584
|
if (!path) {
|
|
38563
39585
|
ctx.output.writeLine(pc.yellow(t("repl.lsp_check_usage")));
|
|
38564
39586
|
return;
|
|
@@ -38572,13 +39594,16 @@ function registerLspCommands(ctx) {
|
|
|
38572
39594
|
} catch (e) {
|
|
38573
39595
|
ctx.output.writeLine(pc.red(t("repl.lsp_check_error", { error: errMsg(e) })), "stderr");
|
|
38574
39596
|
}
|
|
38575
|
-
break;
|
|
38576
|
-
}
|
|
38577
|
-
default: {
|
|
38578
|
-
ctx.output.writeLine(pc.dim(t("repl.lsp_usage")));
|
|
38579
|
-
break;
|
|
38580
39597
|
}
|
|
39598
|
+
};
|
|
39599
|
+
const subcommand = args[0] || "status";
|
|
39600
|
+
const handler = handlers[subcommand];
|
|
39601
|
+
if (!handler) {
|
|
39602
|
+
ctx.output.writeLine(pc.yellow(t("repl.unknown_sub", { cmd: "lsp", sub: subcommand })));
|
|
39603
|
+
ctx.output.writeLine(pc.dim(t("repl.lsp_usage")));
|
|
39604
|
+
return;
|
|
38581
39605
|
}
|
|
39606
|
+
await handler(args.slice(1));
|
|
38582
39607
|
}
|
|
38583
39608
|
});
|
|
38584
39609
|
}
|
|
@@ -38642,8 +39667,9 @@ function registerSessionCommands(ctx) {
|
|
|
38642
39667
|
ctx.registerCommand({
|
|
38643
39668
|
name: "resume",
|
|
38644
39669
|
description: t("repl.resume"),
|
|
38645
|
-
aliases: ["switch"
|
|
39670
|
+
aliases: ["switch"],
|
|
38646
39671
|
usage: t("repl.resume_usage"),
|
|
39672
|
+
examples: ["/resume", "/resume my-session"],
|
|
38647
39673
|
action: (args) => {
|
|
38648
39674
|
const query = args.join(" ");
|
|
38649
39675
|
const sessions = ctx.sessionManager.list();
|
|
@@ -38730,6 +39756,77 @@ function registerSessionCommands(ctx) {
|
|
|
38730
39756
|
ctx.output.writeLine(`${t("session.deleted", { id: match.id })}: ${match.name}`);
|
|
38731
39757
|
}
|
|
38732
39758
|
});
|
|
39759
|
+
ctx.registerCommand({
|
|
39760
|
+
name: "export",
|
|
39761
|
+
description: t("repl.export"),
|
|
39762
|
+
usage: t("repl.export_usage"),
|
|
39763
|
+
examples: [
|
|
39764
|
+
"/export",
|
|
39765
|
+
"/export my-session --format md",
|
|
39766
|
+
"/export --format json --out -"
|
|
39767
|
+
],
|
|
39768
|
+
action: async (args) => {
|
|
39769
|
+
let format = "md";
|
|
39770
|
+
let out;
|
|
39771
|
+
let redact = true;
|
|
39772
|
+
const positional = [];
|
|
39773
|
+
for (let i = 0;i < args.length; i++) {
|
|
39774
|
+
const a = args[i];
|
|
39775
|
+
if (a === "--format") {
|
|
39776
|
+
const v = args[++i];
|
|
39777
|
+
if (!v) {
|
|
39778
|
+
ctx.output.writeLine(t("export.missing_value", { flag: a }));
|
|
39779
|
+
return;
|
|
39780
|
+
}
|
|
39781
|
+
format = v;
|
|
39782
|
+
} else if (a === "--out") {
|
|
39783
|
+
const v = args[++i];
|
|
39784
|
+
if (v === undefined) {
|
|
39785
|
+
ctx.output.writeLine(t("export.missing_value", { flag: a }));
|
|
39786
|
+
return;
|
|
39787
|
+
}
|
|
39788
|
+
out = v;
|
|
39789
|
+
} else if (a === "--no-redact") {
|
|
39790
|
+
redact = false;
|
|
39791
|
+
} else {
|
|
39792
|
+
positional.push(a);
|
|
39793
|
+
}
|
|
39794
|
+
}
|
|
39795
|
+
if (format !== "md" && format !== "json" && format !== "jsonl") {
|
|
39796
|
+
ctx.output.writeLine(pc.yellow(t("export.invalid_format", { format })), "stderr");
|
|
39797
|
+
return;
|
|
39798
|
+
}
|
|
39799
|
+
const query = positional.join(" ");
|
|
39800
|
+
const sessions = ctx.sessionManager.list();
|
|
39801
|
+
const match = query ? sessions.find((s) => s.id === query || s.id.startsWith(query) || s.name.toLowerCase().includes(query.toLowerCase())) : sessions.find((s) => s.id === ctx.sessionManager.getActive());
|
|
39802
|
+
if (!match) {
|
|
39803
|
+
ctx.output.writeLine(query ? t("session.no_match", { query }) : t("session.no_active"));
|
|
39804
|
+
return;
|
|
39805
|
+
}
|
|
39806
|
+
const messages = ctx.sessionManager.getHistory(match.id);
|
|
39807
|
+
const log2 = ctx.sessionManager.loadSessionLog(match.id);
|
|
39808
|
+
if (format === "jsonl" ? log2.length === 0 : messages.length === 0) {
|
|
39809
|
+
ctx.output.writeLine(pc.yellow(t("export.empty")));
|
|
39810
|
+
return;
|
|
39811
|
+
}
|
|
39812
|
+
const text = redactExport(formatExport({ meta: match, messages, log: log2 }, format), redact);
|
|
39813
|
+
if (out === "-") {
|
|
39814
|
+
ctx.output.writeLine(text);
|
|
39815
|
+
return;
|
|
39816
|
+
}
|
|
39817
|
+
const baseDir = out ? dirname25(out) : join55(homedir18(), ".mma", "exports");
|
|
39818
|
+
const path = out ?? join55(baseDir, `${sanitizeFileName(match.name)}-${match.id.slice(0, 8)}.${extensionFor(format)}`);
|
|
39819
|
+
try {
|
|
39820
|
+
mkdirSync26(baseDir, { recursive: true });
|
|
39821
|
+
writeFileSync25(path, text, "utf-8");
|
|
39822
|
+
} catch (e) {
|
|
39823
|
+
ctx.output.writeLine(pc.red(t("export.write_failed", { error: errMsg(e) })), "stderr");
|
|
39824
|
+
return;
|
|
39825
|
+
}
|
|
39826
|
+
ctx.output.writeLine(pc.green(t("export.written", { path })));
|
|
39827
|
+
ctx.output.writeLine(pc.dim(redact ? t("export.redacted") : t("export.raw")));
|
|
39828
|
+
}
|
|
39829
|
+
});
|
|
38733
39830
|
}
|
|
38734
39831
|
function registerSkillCommands(ctx) {
|
|
38735
39832
|
if (!ctx.skillsModule)
|
|
@@ -38820,7 +39917,7 @@ function registerSkillCommands(ctx) {
|
|
|
38820
39917
|
const subcmd = args[0];
|
|
38821
39918
|
const handler = subcmd ? skillHandlers[subcmd] : skillHandlers.list;
|
|
38822
39919
|
if (!handler) {
|
|
38823
|
-
ctx.output.writeLine(pc.
|
|
39920
|
+
ctx.output.writeLine(pc.yellow(t("repl.unknown_sub", { cmd: "skill", sub: subcmd })));
|
|
38824
39921
|
ctx.output.writeLine(t("repl.skill_usage"));
|
|
38825
39922
|
return;
|
|
38826
39923
|
}
|
|
@@ -38849,9 +39946,10 @@ async function runConfigMigrate(ctx) {
|
|
|
38849
39946
|
const domainFiles = readdirSync20(join55(configDir, "config")).filter((f) => f.endsWith(".json"));
|
|
38850
39947
|
ctx.output.writeLine(pc.green(t("config.migrate_done", { count: String(domainFiles.length) })));
|
|
38851
39948
|
}
|
|
38852
|
-
var version2, COMMAND_GROUPS;
|
|
39949
|
+
var version2, COMMAND_GROUPS, SUGAR_HINTS;
|
|
38853
39950
|
var init_repl_commands = __esm(() => {
|
|
38854
39951
|
init_colors();
|
|
39952
|
+
init_theme();
|
|
38855
39953
|
init_version();
|
|
38856
39954
|
init_table();
|
|
38857
39955
|
init_i18n();
|
|
@@ -38860,6 +39958,8 @@ var init_repl_commands = __esm(() => {
|
|
|
38860
39958
|
init_config2();
|
|
38861
39959
|
init_presets();
|
|
38862
39960
|
init_budget();
|
|
39961
|
+
init_registry2();
|
|
39962
|
+
init_export();
|
|
38863
39963
|
init_token_counter();
|
|
38864
39964
|
init_map_command();
|
|
38865
39965
|
init_utils();
|
|
@@ -38887,9 +39987,20 @@ var init_repl_commands = __esm(() => {
|
|
|
38887
39987
|
resume: "session",
|
|
38888
39988
|
rename: "session",
|
|
38889
39989
|
delete: "session",
|
|
39990
|
+
export: "session",
|
|
38890
39991
|
skill: "skill",
|
|
38891
39992
|
plugins: "agent"
|
|
38892
39993
|
};
|
|
39994
|
+
SUGAR_HINTS = {
|
|
39995
|
+
model: "/model use <name>",
|
|
39996
|
+
"provider.active": "/provider use <name>",
|
|
39997
|
+
contextWindow: "/context <size>",
|
|
39998
|
+
"contextBudget.systemPrompt": "/context system <share>",
|
|
39999
|
+
"contextBudget.responseReserve": "/context reserve <share>",
|
|
40000
|
+
showReasoning: "/reasoning show | hide",
|
|
40001
|
+
"reasoning.mode": "/reasoning level <level>",
|
|
40002
|
+
"ui.verbosity": "/verbose <level>"
|
|
40003
|
+
};
|
|
38893
40004
|
});
|
|
38894
40005
|
|
|
38895
40006
|
// node_modules/commander/esm.mjs
|
|
@@ -38915,9 +40026,10 @@ init_setup();
|
|
|
38915
40026
|
init_setup_order();
|
|
38916
40027
|
init_i18n();
|
|
38917
40028
|
init_colors();
|
|
40029
|
+
init_export();
|
|
38918
40030
|
import { join as join53, dirname as dirname24 } from "path";
|
|
38919
40031
|
import { homedir as homedir17 } from "os";
|
|
38920
|
-
import { existsSync as existsSync59 } from "fs";
|
|
40032
|
+
import { existsSync as existsSync59, mkdirSync as mkdirSync25, writeFileSync as writeFileSync24 } from "fs";
|
|
38921
40033
|
|
|
38922
40034
|
// src/cli/security-commands.ts
|
|
38923
40035
|
init_bootstrap();
|
|
@@ -40182,6 +41294,41 @@ function buildSessionCommands(program2) {
|
|
|
40182
41294
|
}
|
|
40183
41295
|
}
|
|
40184
41296
|
});
|
|
41297
|
+
session2.command("export").argument("<id>", "Session id (or name prefix)").description(t("cli.export_session")).option("--format <format>", t("cli.export_format"), "md").option("--out <path>", t("cli.export_out")).option("--no-redact", t("cli.export_no_redact")).action(async (id, opts) => {
|
|
41298
|
+
const { sessionManager } = await bootstrap();
|
|
41299
|
+
const meta = sessionManager.get(id) ?? sessionManager.list().find((s) => s.id.startsWith(id)) ?? sessionManager.list().find((s) => s.name.toLowerCase().includes(id.toLowerCase()));
|
|
41300
|
+
if (!meta) {
|
|
41301
|
+
getDefaultChannel().writeLine(t("session.not_found", { id }));
|
|
41302
|
+
return;
|
|
41303
|
+
}
|
|
41304
|
+
const format = opts.format;
|
|
41305
|
+
if (format !== "md" && format !== "json" && format !== "jsonl") {
|
|
41306
|
+
getDefaultChannel().writeLine(t("export.invalid_format", { format }));
|
|
41307
|
+
return;
|
|
41308
|
+
}
|
|
41309
|
+
const messages = sessionManager.getHistory(meta.id);
|
|
41310
|
+
const log2 = sessionManager.loadSessionLog(meta.id);
|
|
41311
|
+
if (format === "jsonl" ? log2.length === 0 : messages.length === 0) {
|
|
41312
|
+
getDefaultChannel().writeLine(t("export.empty"));
|
|
41313
|
+
return;
|
|
41314
|
+
}
|
|
41315
|
+
const text = redactExport(formatExport({ meta, messages, log: log2 }, format), opts.redact);
|
|
41316
|
+
if (opts.out === "-") {
|
|
41317
|
+
getDefaultChannel().writeLine(text);
|
|
41318
|
+
return;
|
|
41319
|
+
}
|
|
41320
|
+
const baseDir = opts.out ? dirname24(opts.out) : join53(homedir17(), ".mma", "exports");
|
|
41321
|
+
const path = opts.out ?? join53(baseDir, `${sanitizeFileName(meta.name)}-${meta.id.slice(0, 8)}.${extensionFor(format)}`);
|
|
41322
|
+
try {
|
|
41323
|
+
mkdirSync25(baseDir, { recursive: true });
|
|
41324
|
+
writeFileSync24(path, text, "utf-8");
|
|
41325
|
+
} catch (e) {
|
|
41326
|
+
getDefaultChannel().writeLine(t("export.write_failed", { error: String(e) }));
|
|
41327
|
+
return;
|
|
41328
|
+
}
|
|
41329
|
+
getDefaultChannel().writeLine(t("export.written", { path }));
|
|
41330
|
+
getDefaultChannel().writeLine(t(opts.redact ? "export.redacted" : "export.raw"));
|
|
41331
|
+
});
|
|
40185
41332
|
session2.command("delete").argument("<id>", "Session id").description(t("cli.delete_session")).action(async (id) => {
|
|
40186
41333
|
const { sessionManager } = await bootstrap();
|
|
40187
41334
|
sessionManager.delete(id);
|
|
@@ -41313,11 +42460,13 @@ class LineEditor {
|
|
|
41313
42460
|
}
|
|
41314
42461
|
|
|
41315
42462
|
// src/cli/repl.ts
|
|
41316
|
-
import { existsSync as existsSync61, mkdirSync as
|
|
42463
|
+
import { existsSync as existsSync61, mkdirSync as mkdirSync27, readFileSync as readFileSync42, writeFileSync as writeFileSync26 } from "fs";
|
|
41317
42464
|
import { dirname as dirname26, join as join56 } from "path";
|
|
41318
|
-
import { homedir as
|
|
42465
|
+
import { homedir as homedir19 } from "os";
|
|
41319
42466
|
|
|
41320
42467
|
// src/cli/completer.ts
|
|
42468
|
+
init_registry2();
|
|
42469
|
+
init_i18n();
|
|
41321
42470
|
import { readdirSync as readdirSync19, statSync as statSync11 } from "fs";
|
|
41322
42471
|
import { join as join54 } from "path";
|
|
41323
42472
|
function buildSlashCompletions(commands) {
|
|
@@ -41422,11 +42571,13 @@ class ProviderArgProvider {
|
|
|
41422
42571
|
class SessionNameProvider {
|
|
41423
42572
|
name = "session-names";
|
|
41424
42573
|
getNames;
|
|
41425
|
-
|
|
42574
|
+
commands;
|
|
42575
|
+
constructor(getNames, commands = ["/resume"]) {
|
|
41426
42576
|
this.getNames = getNames;
|
|
42577
|
+
this.commands = commands;
|
|
41427
42578
|
}
|
|
41428
42579
|
match(ctx) {
|
|
41429
|
-
return ctx.tokenIndex >= 1 && ctx.tokens[0]
|
|
42580
|
+
return ctx.tokenIndex >= 1 && this.commands.includes(ctx.tokens[0]);
|
|
41430
42581
|
}
|
|
41431
42582
|
complete(ctx) {
|
|
41432
42583
|
const names = this.getNames();
|
|
@@ -41458,6 +42609,74 @@ class SkillNameProvider {
|
|
|
41458
42609
|
}
|
|
41459
42610
|
}
|
|
41460
42611
|
|
|
42612
|
+
class ConfigKeyProvider {
|
|
42613
|
+
name = "config-keys";
|
|
42614
|
+
match(ctx) {
|
|
42615
|
+
return ctx.tokenIndex === 1 && ctx.tokens[0] === "/config";
|
|
42616
|
+
}
|
|
42617
|
+
complete(ctx) {
|
|
42618
|
+
const partial = ctx.partial;
|
|
42619
|
+
const items = allConfigNames().map(({ name, def, alias }) => ({
|
|
42620
|
+
value: name,
|
|
42621
|
+
description: alias ? `${t("config.alias_label")} ${def.key}` : def.domain
|
|
42622
|
+
}));
|
|
42623
|
+
if (!partial.includes(".")) {
|
|
42624
|
+
const groups = [...new Set(canonicalKeys().filter((k) => k.includes(".")).map((k) => k.split(".")[0]))];
|
|
42625
|
+
const groupItems = groups.map((g) => ({
|
|
42626
|
+
value: g,
|
|
42627
|
+
description: t("config.group_label")
|
|
42628
|
+
}));
|
|
42629
|
+
return [...groupItems, ...items].filter((i) => i.value.startsWith(partial));
|
|
42630
|
+
}
|
|
42631
|
+
return items.filter((i) => i.value.startsWith(partial));
|
|
42632
|
+
}
|
|
42633
|
+
}
|
|
42634
|
+
|
|
42635
|
+
class ConfigValueProvider {
|
|
42636
|
+
name = "config-values";
|
|
42637
|
+
match(ctx) {
|
|
42638
|
+
return ctx.tokenIndex === 2 && ctx.tokens[0] === "/config";
|
|
42639
|
+
}
|
|
42640
|
+
complete(ctx) {
|
|
42641
|
+
const def = resolveConfigKey(ctx.tokens[1]);
|
|
42642
|
+
if (!def?.enumValues)
|
|
42643
|
+
return [];
|
|
42644
|
+
return def.enumValues.filter((v) => v.startsWith(ctx.partial)).map((v) => ({ value: v }));
|
|
42645
|
+
}
|
|
42646
|
+
}
|
|
42647
|
+
|
|
42648
|
+
class FlagProvider {
|
|
42649
|
+
name = "provider-add-flags";
|
|
42650
|
+
match(ctx) {
|
|
42651
|
+
return ctx.tokens[0] === "/provider" && ctx.tokens[1] === "add" && ctx.tokenIndex >= 2;
|
|
42652
|
+
}
|
|
42653
|
+
complete(ctx) {
|
|
42654
|
+
const flags = [
|
|
42655
|
+
{ value: "--url", description: t("repl.provider_flag_url") },
|
|
42656
|
+
{ value: "--key", description: t("repl.provider_flag_key") },
|
|
42657
|
+
{ value: "--priority", description: t("repl.provider_flag_priority") },
|
|
42658
|
+
{ value: "--context-window", description: t("repl.provider_flag_context_window") },
|
|
42659
|
+
{ value: "--rpm", description: t("repl.provider_flag_rpm") },
|
|
42660
|
+
{ value: "--parallel", description: t("repl.provider_flag_parallel") }
|
|
42661
|
+
];
|
|
42662
|
+
return flags.filter((f) => f.value.startsWith(ctx.partial));
|
|
42663
|
+
}
|
|
42664
|
+
}
|
|
42665
|
+
|
|
42666
|
+
class CommandArgProvider {
|
|
42667
|
+
name = "help-command-args";
|
|
42668
|
+
getNames;
|
|
42669
|
+
constructor(getNames) {
|
|
42670
|
+
this.getNames = getNames;
|
|
42671
|
+
}
|
|
42672
|
+
match(ctx) {
|
|
42673
|
+
return ctx.tokenIndex === 1 && ctx.tokens[0] === "/help";
|
|
42674
|
+
}
|
|
42675
|
+
complete(ctx) {
|
|
42676
|
+
return this.getNames().filter((n) => n.startsWith(ctx.partial)).map((n) => ({ value: n }));
|
|
42677
|
+
}
|
|
42678
|
+
}
|
|
42679
|
+
|
|
41461
42680
|
class Completer {
|
|
41462
42681
|
providers = [];
|
|
41463
42682
|
registerProvider(provider) {
|
|
@@ -41492,109 +42711,7 @@ init_colors();
|
|
|
41492
42711
|
init_string_width();
|
|
41493
42712
|
init_i18n();
|
|
41494
42713
|
init_table();
|
|
41495
|
-
|
|
41496
|
-
// src/ui/theme.ts
|
|
41497
|
-
init_colors();
|
|
41498
|
-
var glyph = {
|
|
41499
|
-
action: "◇",
|
|
41500
|
-
success: "✓",
|
|
41501
|
-
failure: "✗",
|
|
41502
|
-
warning: "⚠",
|
|
41503
|
-
thinking: "✦",
|
|
41504
|
-
question: "?",
|
|
41505
|
-
user: "↵",
|
|
41506
|
-
detail: "↳",
|
|
41507
|
-
group: "│",
|
|
41508
|
-
metric: "⟡",
|
|
41509
|
-
compact: "⟳"
|
|
41510
|
-
};
|
|
41511
|
-
function resolveVerbosity(ui) {
|
|
41512
|
-
if (ui?.verbosity)
|
|
41513
|
-
return ui.verbosity;
|
|
41514
|
-
return ui?.verbose ? "verbose" : "quiet";
|
|
41515
|
-
}
|
|
41516
|
-
var CATEGORY_TOOLS = {
|
|
41517
|
-
recon: new Set([
|
|
41518
|
-
"read_file",
|
|
41519
|
-
"list_dir",
|
|
41520
|
-
"glob",
|
|
41521
|
-
"grep",
|
|
41522
|
-
"file_info",
|
|
41523
|
-
"project_map",
|
|
41524
|
-
"chunk_query",
|
|
41525
|
-
"web_search",
|
|
41526
|
-
"web_fetch",
|
|
41527
|
-
"web_browse",
|
|
41528
|
-
"search_history",
|
|
41529
|
-
"recall",
|
|
41530
|
-
"session_info",
|
|
41531
|
-
"process_list",
|
|
41532
|
-
"process_log"
|
|
41533
|
-
]),
|
|
41534
|
-
mutate: new Set([
|
|
41535
|
-
"write_file",
|
|
41536
|
-
"edit_file",
|
|
41537
|
-
"create_dir",
|
|
41538
|
-
"delete_file",
|
|
41539
|
-
"move_file",
|
|
41540
|
-
"attach_image"
|
|
41541
|
-
]),
|
|
41542
|
-
execute: new Set([
|
|
41543
|
-
"bash",
|
|
41544
|
-
"process_kill",
|
|
41545
|
-
"pipeline_run",
|
|
41546
|
-
"browser",
|
|
41547
|
-
"download_file",
|
|
41548
|
-
"subagent",
|
|
41549
|
-
"mcp_call"
|
|
41550
|
-
]),
|
|
41551
|
-
meta: new Set([
|
|
41552
|
-
"plan",
|
|
41553
|
-
"todo",
|
|
41554
|
-
"verify",
|
|
41555
|
-
"lsp_check",
|
|
41556
|
-
"enable_tools",
|
|
41557
|
-
"set_thinking",
|
|
41558
|
-
"load_skill",
|
|
41559
|
-
"remember"
|
|
41560
|
-
])
|
|
41561
|
-
};
|
|
41562
|
-
function toolCategory(tool) {
|
|
41563
|
-
for (const [category, tools] of Object.entries(CATEGORY_TOOLS)) {
|
|
41564
|
-
if (tools.has(tool))
|
|
41565
|
-
return category;
|
|
41566
|
-
}
|
|
41567
|
-
return "meta";
|
|
41568
|
-
}
|
|
41569
|
-
function toolAccent(tool) {
|
|
41570
|
-
switch (toolCategory(tool)) {
|
|
41571
|
-
case "recon":
|
|
41572
|
-
return pc.cyan;
|
|
41573
|
-
case "mutate":
|
|
41574
|
-
return pc.magenta;
|
|
41575
|
-
case "execute":
|
|
41576
|
-
return pc.blue;
|
|
41577
|
-
case "meta":
|
|
41578
|
-
default:
|
|
41579
|
-
return pc.dim;
|
|
41580
|
-
}
|
|
41581
|
-
}
|
|
41582
|
-
function actionMarkFor(tool) {
|
|
41583
|
-
return toolAccent(tool)(glyph.action);
|
|
41584
|
-
}
|
|
41585
|
-
function successMark() {
|
|
41586
|
-
return pc.green(glyph.success);
|
|
41587
|
-
}
|
|
41588
|
-
function failureMark() {
|
|
41589
|
-
return pc.red(glyph.failure);
|
|
41590
|
-
}
|
|
41591
|
-
function formatDuration(ms) {
|
|
41592
|
-
if (ms < 1000)
|
|
41593
|
-
return `${ms}ms`;
|
|
41594
|
-
return `${(ms / 1000).toFixed(1)}s`;
|
|
41595
|
-
}
|
|
41596
|
-
|
|
41597
|
-
// src/ui/md-formatter.ts
|
|
42714
|
+
init_theme();
|
|
41598
42715
|
var KW = /\b(import|export|from|const|let|var|function|return|if|else|for|while|do|switch|case|break|continue|new|class|extends|implements|interface|type|enum|namespace|module|declare|abstract|async|await|yield|throw|try|catch|finally|typeof|instanceof|in|of|as|is|keyof|readonly|static|private|public|protected|get|set|constructor|this|super|void|never|any|unknown|boolean|string|number|symbol|object|true|false|null|undefined|default)\b/g;
|
|
41599
42716
|
var STRING = /('[^']*'|"[^"]*"|`[^`]*`)/g;
|
|
41600
42717
|
var COMMENT = /(\/\/[^\n]*|\/\*[\s\S]*?\*\/|#[^\n]*)/g;
|
|
@@ -41850,6 +42967,7 @@ function formatWarning(text) {
|
|
|
41850
42967
|
|
|
41851
42968
|
// src/ui/renderer.ts
|
|
41852
42969
|
init_spinner();
|
|
42970
|
+
init_theme();
|
|
41853
42971
|
|
|
41854
42972
|
// src/ui/action-log.ts
|
|
41855
42973
|
var last = null;
|
|
@@ -42317,9 +43435,11 @@ ${pc.dim(glyph.metric)} ${model} · ${provider} · ${pc.dim(formatDuration(durat
|
|
|
42317
43435
|
}
|
|
42318
43436
|
|
|
42319
43437
|
// src/cli/repl.ts
|
|
43438
|
+
init_theme();
|
|
42320
43439
|
init_box();
|
|
42321
43440
|
init_i18n();
|
|
42322
43441
|
init_repl_commands();
|
|
43442
|
+
init_registry2();
|
|
42323
43443
|
|
|
42324
43444
|
// src/modules/lsp/probe.ts
|
|
42325
43445
|
init_client2();
|
|
@@ -42403,6 +43523,7 @@ init_session_logger();
|
|
|
42403
43523
|
|
|
42404
43524
|
// src/ui/plan-view.ts
|
|
42405
43525
|
init_colors();
|
|
43526
|
+
init_theme();
|
|
42406
43527
|
init_js_identifiers();
|
|
42407
43528
|
init_i18n();
|
|
42408
43529
|
function currentStepIndex(plan) {
|
|
@@ -42605,6 +43726,7 @@ function createHostBridge(opts) {
|
|
|
42605
43726
|
class Repl {
|
|
42606
43727
|
completer = new Completer;
|
|
42607
43728
|
modelCache = [];
|
|
43729
|
+
configSnapshot = new Map;
|
|
42608
43730
|
running = false;
|
|
42609
43731
|
agentRunning = false;
|
|
42610
43732
|
inputLocked = false;
|
|
@@ -42648,10 +43770,10 @@ class Repl {
|
|
|
42648
43770
|
this.execModule = execModule;
|
|
42649
43771
|
this.slog = new SessionLogger(sessionManager, logger4);
|
|
42650
43772
|
this.bindSessionOutput();
|
|
42651
|
-
this.configDir = configDir || join56(
|
|
43773
|
+
this.configDir = configDir || join56(homedir19(), ".mma");
|
|
42652
43774
|
this.baseDir = baseDir || process.cwd();
|
|
42653
43775
|
this.noAgentsMd = noAgentsMd === true;
|
|
42654
|
-
this.historyPath = historyPath ?? join56(
|
|
43776
|
+
this.historyPath = historyPath ?? join56(homedir19(), ".mma", "repl-history");
|
|
42655
43777
|
this.loadHistory();
|
|
42656
43778
|
const editorCompleter = (line) => {
|
|
42657
43779
|
const [matches, partial] = this.completer.complete(line);
|
|
@@ -42705,6 +43827,7 @@ class Repl {
|
|
|
42705
43827
|
});
|
|
42706
43828
|
this.agent.setPromptIO?.(this.promptIO);
|
|
42707
43829
|
registerAllCommands(this);
|
|
43830
|
+
this.configSnapshot = captureConfigSnapshot(this.config);
|
|
42708
43831
|
this.setupCompleter();
|
|
42709
43832
|
this.setupListeners();
|
|
42710
43833
|
if (pluginManager) {
|
|
@@ -42765,9 +43888,9 @@ class Repl {
|
|
|
42765
43888
|
}
|
|
42766
43889
|
saveHistory() {
|
|
42767
43890
|
try {
|
|
42768
|
-
|
|
43891
|
+
mkdirSync27(dirname26(this.historyPath), { recursive: true });
|
|
42769
43892
|
const allHistory = this.history.slice(-this.maxHistory);
|
|
42770
|
-
|
|
43893
|
+
writeFileSync26(this.historyPath, allHistory.join(`
|
|
42771
43894
|
`), "utf-8");
|
|
42772
43895
|
} catch (e) {
|
|
42773
43896
|
this.logger?.debug(`Failed to save REPL history: ${e.message}`);
|
|
@@ -42778,14 +43901,59 @@ class Repl {
|
|
|
42778
43901
|
const slashCommands = buildSlashCompletions(this.commands);
|
|
42779
43902
|
this.completer.registerProvider(new SlashCommandProvider(slashCommands));
|
|
42780
43903
|
if (this.sessionManager) {
|
|
42781
|
-
this.completer.registerProvider(new SessionNameProvider(() => this.sessionManager.list().map((s) => s.name)
|
|
43904
|
+
this.completer.registerProvider(new SessionNameProvider(() => this.sessionManager.list().map((s) => s.name), [
|
|
43905
|
+
"/resume",
|
|
43906
|
+
"/delete",
|
|
43907
|
+
"/export"
|
|
43908
|
+
]));
|
|
42782
43909
|
}
|
|
42783
43910
|
if (this.skillsModule) {
|
|
42784
|
-
this.completer.registerProvider(new SubcommandProvider("skill", [
|
|
43911
|
+
this.completer.registerProvider(new SubcommandProvider("skill", [
|
|
43912
|
+
{ name: "list", description: t("skill.sub_list") },
|
|
43913
|
+
{ name: "loaded", description: t("skill.sub_loaded") },
|
|
43914
|
+
{ name: "load", description: t("skill.sub_load") },
|
|
43915
|
+
{ name: "unload", description: t("skill.sub_unload") },
|
|
43916
|
+
{ name: "search", description: t("skill.sub_search") }
|
|
43917
|
+
]));
|
|
42785
43918
|
this.completer.registerProvider(new SkillNameProvider(this.skillsModule));
|
|
42786
43919
|
}
|
|
42787
|
-
this.completer.registerProvider(new SubcommandProvider("provider", [
|
|
42788
|
-
|
|
43920
|
+
this.completer.registerProvider(new SubcommandProvider("provider", [
|
|
43921
|
+
{ name: "list", description: t("provider.sub_list") },
|
|
43922
|
+
{ name: "use", description: t("provider.sub_use") },
|
|
43923
|
+
{ name: "add", description: t("provider.sub_add") }
|
|
43924
|
+
]));
|
|
43925
|
+
this.completer.registerProvider(new SubcommandProvider("model", [
|
|
43926
|
+
{ name: "list", description: t("model.sub_list") },
|
|
43927
|
+
{ name: "use", description: t("model.sub_use") }
|
|
43928
|
+
]));
|
|
43929
|
+
this.completer.registerProvider(new SubcommandProvider("map", [
|
|
43930
|
+
{ name: "summary", description: t("map.sub_summary") },
|
|
43931
|
+
{ name: "refresh", description: t("map.sub_refresh") },
|
|
43932
|
+
{ name: "find", description: t("map.sub_find") }
|
|
43933
|
+
]));
|
|
43934
|
+
this.completer.registerProvider(new SubcommandProvider("context", [
|
|
43935
|
+
{ name: "system", description: t("context.sub_system") },
|
|
43936
|
+
{ name: "reserve", description: t("context.sub_reserve") }
|
|
43937
|
+
]));
|
|
43938
|
+
this.completer.registerProvider(new SubcommandProvider("lsp", [
|
|
43939
|
+
{ name: "status", description: t("lsp.sub_status") },
|
|
43940
|
+
{ name: "restart", description: t("lsp.sub_restart") },
|
|
43941
|
+
{ name: "check", description: t("lsp.sub_check") }
|
|
43942
|
+
]));
|
|
43943
|
+
this.completer.registerProvider(new SubcommandProvider("reasoning", [
|
|
43944
|
+
{ name: "show", description: t("reasoning.sub_show") },
|
|
43945
|
+
{ name: "hide", description: t("reasoning.sub_hide") },
|
|
43946
|
+
{ name: "level", description: t("reasoning.sub_level") }
|
|
43947
|
+
]));
|
|
43948
|
+
this.completer.registerProvider(new SubcommandProvider("verbose", [
|
|
43949
|
+
{ name: "quiet", description: t("verbose.sub_quiet") },
|
|
43950
|
+
{ name: "normal", description: t("verbose.sub_normal") },
|
|
43951
|
+
{ name: "verbose", description: t("verbose.sub_verbose") }
|
|
43952
|
+
]));
|
|
43953
|
+
this.completer.registerProvider(new ConfigKeyProvider);
|
|
43954
|
+
this.completer.registerProvider(new ConfigValueProvider);
|
|
43955
|
+
this.completer.registerProvider(new FlagProvider);
|
|
43956
|
+
this.completer.registerProvider(new CommandArgProvider(() => Array.from(this.commands.entries()).filter(([key, cmd]) => key === cmd.name).map(([, cmd]) => cmd.name)));
|
|
42789
43957
|
const entryLabels = this.config.provider?.entries?.map((e) => e.label || e.type) ?? [];
|
|
42790
43958
|
if (entryLabels.length > 0) {
|
|
42791
43959
|
this.completer.registerProvider(new ProviderArgProvider(entryLabels));
|
|
@@ -42794,6 +43962,17 @@ class Repl {
|
|
|
42794
43962
|
this.completer.registerProvider(new FilePathProvider(this.baseDir));
|
|
42795
43963
|
this.refreshModelCache();
|
|
42796
43964
|
}
|
|
43965
|
+
reregisterCommands() {
|
|
43966
|
+
this.commands.clear();
|
|
43967
|
+
registerAllCommands(this);
|
|
43968
|
+
this.setupCompleter();
|
|
43969
|
+
}
|
|
43970
|
+
getConfigSnapshot() {
|
|
43971
|
+
return this.configSnapshot;
|
|
43972
|
+
}
|
|
43973
|
+
knownModels() {
|
|
43974
|
+
return this.modelCache;
|
|
43975
|
+
}
|
|
42797
43976
|
refreshModelCache() {
|
|
42798
43977
|
(async () => {
|
|
42799
43978
|
try {
|
|
@@ -43140,7 +44319,13 @@ ${divider()}`);
|
|
|
43140
44319
|
this.runHandledPrompt = false;
|
|
43141
44320
|
const cmd = this.commands.get(name);
|
|
43142
44321
|
if (!cmd) {
|
|
43143
|
-
|
|
44322
|
+
const formerAliases = { use: "resume" };
|
|
44323
|
+
const suggestion = formerAliases[name];
|
|
44324
|
+
if (suggestion) {
|
|
44325
|
+
this.output.writeLine(pc.red(t("cli.unknown_command", { input: `/${name}`, suggestion: `/${suggestion}` })));
|
|
44326
|
+
} else {
|
|
44327
|
+
this.output.writeLine(`${pc.red(t("cli.unknown_cmd", { name }))} ${t("cli.help_hint")}`);
|
|
44328
|
+
}
|
|
43144
44329
|
return;
|
|
43145
44330
|
}
|
|
43146
44331
|
try {
|
|
@@ -43151,8 +44336,29 @@ ${divider()}`);
|
|
|
43151
44336
|
})), "stderr");
|
|
43152
44337
|
}
|
|
43153
44338
|
}
|
|
43154
|
-
showHelp() {
|
|
44339
|
+
showHelp(command) {
|
|
43155
44340
|
const { COMMAND_GROUPS: COMMAND_GROUPS2 } = (init_repl_commands(), __toCommonJS(exports_repl_commands));
|
|
44341
|
+
if (command) {
|
|
44342
|
+
const name = command.replace(/^\//, "");
|
|
44343
|
+
const cmd = this.commands.get(name);
|
|
44344
|
+
if (!cmd) {
|
|
44345
|
+
this.output.writeLine(pc.red(t("repl.help_unknown", { name })));
|
|
44346
|
+
return;
|
|
44347
|
+
}
|
|
44348
|
+
this.output.writeLine(pc.bold(pc.cyan("/" + cmd.name)));
|
|
44349
|
+
this.output.writeLine(` ${cmd.description}`);
|
|
44350
|
+
if (cmd.usage)
|
|
44351
|
+
this.output.writeLine(` ${pc.dim(cmd.usage)}`);
|
|
44352
|
+
if (cmd.aliases?.length) {
|
|
44353
|
+
this.output.writeLine(pc.dim(` ${t("repl.help_aliases", { names: cmd.aliases.join(", ") })}`));
|
|
44354
|
+
}
|
|
44355
|
+
if (cmd.examples?.length) {
|
|
44356
|
+
this.output.writeLine(pc.dim(` ${t("repl.help_examples")}`));
|
|
44357
|
+
for (const ex of cmd.examples)
|
|
44358
|
+
this.output.writeLine(pc.dim(` ${ex}`));
|
|
44359
|
+
}
|
|
44360
|
+
return;
|
|
44361
|
+
}
|
|
43156
44362
|
const order = ["general", "agent", "session", "skill"];
|
|
43157
44363
|
const seen = new Set;
|
|
43158
44364
|
for (const groupKey of order) {
|
|
@@ -43363,6 +44569,9 @@ ${line}`);
|
|
|
43363
44569
|
}
|
|
43364
44570
|
}
|
|
43365
44571
|
|
|
44572
|
+
// src/cli/main.ts
|
|
44573
|
+
init_theme();
|
|
44574
|
+
|
|
43366
44575
|
// src/cli/run-result.ts
|
|
43367
44576
|
init_i18n();
|
|
43368
44577
|
init_colors();
|
|
@@ -43456,7 +44665,7 @@ init_i18n();
|
|
|
43456
44665
|
init_colors();
|
|
43457
44666
|
import { existsSync as existsSync62 } from "fs";
|
|
43458
44667
|
import { join as join58, dirname as dirname27 } from "path";
|
|
43459
|
-
import { homedir as
|
|
44668
|
+
import { homedir as homedir21 } from "os";
|
|
43460
44669
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
43461
44670
|
|
|
43462
44671
|
// src/modules/updater/index.ts
|
|
@@ -43576,10 +44785,10 @@ init_environment();
|
|
|
43576
44785
|
init_data_sanitizer();
|
|
43577
44786
|
init_i18n();
|
|
43578
44787
|
init_utils();
|
|
43579
|
-
import { appendFileSync as appendFileSync8, mkdirSync as
|
|
44788
|
+
import { appendFileSync as appendFileSync8, mkdirSync as mkdirSync28 } from "fs";
|
|
43580
44789
|
import { join as join57 } from "path";
|
|
43581
|
-
import { homedir as
|
|
43582
|
-
var CRASH_LOG_DIR = join57(
|
|
44790
|
+
import { homedir as homedir20 } from "os";
|
|
44791
|
+
var CRASH_LOG_DIR = join57(homedir20(), ".mma", "logs");
|
|
43583
44792
|
var CRASH_LOG_FILE = "crash.jsonl";
|
|
43584
44793
|
function formatCrashEntry(type2, err) {
|
|
43585
44794
|
const message = errMsg(err);
|
|
@@ -43589,12 +44798,12 @@ function formatCrashEntry(type2, err) {
|
|
|
43589
44798
|
type: type2,
|
|
43590
44799
|
message: sanitizeLogMessage(message),
|
|
43591
44800
|
stack: sanitizeLogMessage(stack),
|
|
43592
|
-
environment: collectEnvironment({ configDir:
|
|
44801
|
+
environment: collectEnvironment({ configDir: homedir20(), scanTools: false })
|
|
43593
44802
|
};
|
|
43594
44803
|
}
|
|
43595
44804
|
function writeCrashEntry(dir, entry) {
|
|
43596
44805
|
try {
|
|
43597
|
-
|
|
44806
|
+
mkdirSync28(dir, { recursive: true });
|
|
43598
44807
|
appendFileSync8(join57(dir, CRASH_LOG_FILE), JSON.stringify(entry) + `
|
|
43599
44808
|
`, "utf-8");
|
|
43600
44809
|
} catch {}
|
|
@@ -43723,7 +44932,7 @@ async function main() {
|
|
|
43723
44932
|
}
|
|
43724
44933
|
const jsonSink = jsonOpt ? new JsonOutputSink(defaultOutputBus) : undefined;
|
|
43725
44934
|
const prompt = program2.args.join(" ");
|
|
43726
|
-
const mmaDir = process.env.MMA_CONFIG_DIR || join58(
|
|
44935
|
+
const mmaDir = process.env.MMA_CONFIG_DIR || join58(homedir21(), ".mma");
|
|
43727
44936
|
const { hasDomainFiles: hasDomainFiles2 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
43728
44937
|
const virgin = !existsSync62(join58(mmaDir, "config.json")) && !hasDomainFiles2(mmaDir);
|
|
43729
44938
|
const { agent, config, baseDir, legacyDetected, contextProbe } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete, reasoningLevel, contextLog);
|
|
@@ -43811,7 +45020,7 @@ async function main() {
|
|
|
43811
45020
|
await updater?.waitForIdle();
|
|
43812
45021
|
process.exit(exitCode);
|
|
43813
45022
|
} else {
|
|
43814
|
-
const mmaDir = process.env.MMA_CONFIG_DIR || join58(
|
|
45023
|
+
const mmaDir = process.env.MMA_CONFIG_DIR || join58(homedir21(), ".mma");
|
|
43815
45024
|
const legacyConfigPath = join58(mmaDir, "config.json");
|
|
43816
45025
|
let hasAnyConfig = existsSync62(legacyConfigPath);
|
|
43817
45026
|
if (!hasAnyConfig) {
|