micro-models-agent 1.5.0 → 1.6.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 +18 -0
- package/dist/i18n/en.json +3 -2
- package/dist/i18n/ru.json +3 -2
- package/dist/main.js +370 -179
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,24 @@ All notable changes to Micro Models Agent (MMA) will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [1.6.0] - 2026-09-22
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Tab completion descriptions & navigation** (`src/cli/completer.ts`, `src/ui/line-editor.ts`): completions carry descriptions, file-path completion is registered in the REPL, arrow keys/Tab cycle candidates, Esc restores.
|
|
12
|
+
- **`redactConfigSecrets`** (`src/config/redact.ts`): deep secret redaction for config display.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **Security-paths wizard answer** (`src/cli/setup.ts`, `src/cli/setup-order.ts`): the question was inverted and a no-op; reworded to restrict semantics and `security.paths.enabled` is now applied.
|
|
17
|
+
- **First-run wizard suppression** (`src/config/config.ts`, `src/cli/main.ts`): `loadConfig` no longer persists default config on first load; one-shot runs warn instead of silently using defaults.
|
|
18
|
+
- **`/wizard` dropped security answers and ignored `provider.entries[]`** (`src/cli/repl-commands.ts`, `src/cli/setup-order.ts`): applies answers centrally and updates the active entry.
|
|
19
|
+
- **`mma config show` leaked secrets** (`src/cli/commands.ts`): secrets redacted by default, `--show-secrets` opts out.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **Chat UI: tool-label accent & separators** (`src/ui/theme.ts`, `src/ui/renderer.ts`, `docs/design/ui/STYLE.md`): the action glyph and the localized tool label now share the category color (`toolAccent`), and a dim `·` separates a status label from its content (reasoning label from reasoning text, tool label from arguments) — the rotating status verb no longer blurs into the model's own words. `Ctrl+O` reprint follows the same accent.
|
|
24
|
+
|
|
7
25
|
## [1.5.0] - 2026-09-21
|
|
8
26
|
|
|
9
27
|
### Added
|
package/dist/i18n/en.json
CHANGED
|
@@ -273,7 +273,7 @@
|
|
|
273
273
|
"cli.config_key": "Config key (e.g., model, provider.baseUrl)",
|
|
274
274
|
"cli.set_value": "Set a config value",
|
|
275
275
|
"cli.set_done": "Set {key}={value}",
|
|
276
|
-
"cli.show_config": "Show
|
|
276
|
+
"cli.show_config": "Show the effective configuration (secrets redacted; use --show-secrets to reveal)",
|
|
277
277
|
"cli.migrate_config": "Migrate legacy config.json to domain format",
|
|
278
278
|
"cli.manage_models": "Manage models",
|
|
279
279
|
"cli.list_models": "List available models",
|
|
@@ -348,6 +348,7 @@
|
|
|
348
348
|
"cli.show_details": "Show session details",
|
|
349
349
|
"cli.delete_session": "Delete a session",
|
|
350
350
|
"cli.first_run": "First run detected. Running setup wizard...",
|
|
351
|
+
"cli.first_run_oneshot": "No configuration found — running with defaults. Run `mma` (no arguments) once to set up the wizard.",
|
|
351
352
|
"cli.setup_saved_restart": "Settings saved. Restarting with the new configuration...",
|
|
352
353
|
"cli.unknown_cmd": "Unknown command: {name}.",
|
|
353
354
|
"cli.unknown_command": "Unknown command \"{input}\". Did you mean \"{suggestion}\"?",
|
|
@@ -558,7 +559,7 @@
|
|
|
558
559
|
"setup.security_configure": " Configure security? (y/N)",
|
|
559
560
|
"setup.security_bash_block": " Block dangerous commands (rm, sudo, ssh, etc.)? (y/N)",
|
|
560
561
|
"setup.security_flags_block": " Block dangerous flags (--force, -rf, etc.)? (y/N)",
|
|
561
|
-
"setup.
|
|
562
|
+
"setup.security_paths_restrict": " Restrict access to .git/, .env, node_modules/? (Y/n)",
|
|
562
563
|
"skill.already_loaded": "Skill \"{name}\" is already loaded",
|
|
563
564
|
"skill.not_found": "Skill \"{name}\" not found in any source directory",
|
|
564
565
|
"skill.no_match": "No skills match for: {task}",
|
package/dist/i18n/ru.json
CHANGED
|
@@ -271,7 +271,7 @@
|
|
|
271
271
|
"cli.config_key": "Ключ конфига (напр., model, provider.baseUrl)",
|
|
272
272
|
"cli.set_value": "Установить значение",
|
|
273
273
|
"cli.set_done": "Установлено {key}={value}",
|
|
274
|
-
"cli.show_config": "Показать
|
|
274
|
+
"cli.show_config": "Показать действующую конфигурацию (секреты скрыты; используйте --show-secrets)",
|
|
275
275
|
"cli.migrate_config": "Мигрировать legacy config.json в domain-формат",
|
|
276
276
|
"cli.manage_models": "Управление моделями",
|
|
277
277
|
"cli.list_models": "Список доступных моделей",
|
|
@@ -342,6 +342,7 @@
|
|
|
342
342
|
"cli.show_details": "Показать детали сессии",
|
|
343
343
|
"cli.delete_session": "Удалить сессию",
|
|
344
344
|
"cli.first_run": "Первый запуск. Запускаем мастер настройки...",
|
|
345
|
+
"cli.first_run_oneshot": "Конфигурация не найдена — запуск с настройками по умолчанию. Запустите `mma` без аргументов один раз для настройки.",
|
|
345
346
|
"cli.setup_saved_restart": "Настройки сохранены. Перезапуск с новой конфигурацией...",
|
|
346
347
|
"cli.unknown_cmd": "Неизвестная команда: {name}.",
|
|
347
348
|
"cli.unknown_command": "Неизвестная команда \"{input}\". Возможно, вы имели в виду \"{suggestion}\"?",
|
|
@@ -556,7 +557,7 @@
|
|
|
556
557
|
"setup.security_configure": " Настроить безопасность? (y/N)",
|
|
557
558
|
"setup.security_bash_block": " Блокировать опасные команды (rm, sudo, ssh и т.д.)? (y/N)",
|
|
558
559
|
"setup.security_flags_block": " Блокировать опасные флаги (--force, -rf и т.д.)? (y/N)",
|
|
559
|
-
"setup.
|
|
560
|
+
"setup.security_paths_restrict": " Ограничить доступ к .git/, .env, node_modules/? (Y/n)",
|
|
560
561
|
"skill.already_loaded": "Скилл \"{name}\" уже загружен",
|
|
561
562
|
"skill.not_found": "Скилл \"{name}\" не найден ни в одном каталоге",
|
|
562
563
|
"skill.no_match": "Нет скиллов подходящих для: {task}",
|
package/dist/main.js
CHANGED
|
@@ -2729,7 +2729,7 @@ Fix the error and re-edit the file (a clean write clears the failure), or mark t
|
|
|
2729
2729
|
"cli.config_key": "Config key (e.g., model, provider.baseUrl)",
|
|
2730
2730
|
"cli.set_value": "Set a config value",
|
|
2731
2731
|
"cli.set_done": "Set {key}={value}",
|
|
2732
|
-
"cli.show_config": "Show
|
|
2732
|
+
"cli.show_config": "Show the effective configuration (secrets redacted; use --show-secrets to reveal)",
|
|
2733
2733
|
"cli.migrate_config": "Migrate legacy config.json to domain format",
|
|
2734
2734
|
"cli.manage_models": "Manage models",
|
|
2735
2735
|
"cli.list_models": "List available models",
|
|
@@ -2804,6 +2804,7 @@ Fix the error and re-edit the file (a clean write clears the failure), or mark t
|
|
|
2804
2804
|
"cli.show_details": "Show session details",
|
|
2805
2805
|
"cli.delete_session": "Delete a session",
|
|
2806
2806
|
"cli.first_run": "First run detected. Running setup wizard...",
|
|
2807
|
+
"cli.first_run_oneshot": "No configuration found — running with defaults. Run `mma` (no arguments) once to set up the wizard.",
|
|
2807
2808
|
"cli.setup_saved_restart": "Settings saved. Restarting with the new configuration...",
|
|
2808
2809
|
"cli.unknown_cmd": "Unknown command: {name}.",
|
|
2809
2810
|
"cli.unknown_command": 'Unknown command "{input}". Did you mean "{suggestion}"?',
|
|
@@ -3028,7 +3029,7 @@ Excluded blocks: {count}`,
|
|
|
3028
3029
|
"setup.security_configure": " Configure security? (y/N)",
|
|
3029
3030
|
"setup.security_bash_block": " Block dangerous commands (rm, sudo, ssh, etc.)? (y/N)",
|
|
3030
3031
|
"setup.security_flags_block": " Block dangerous flags (--force, -rf, etc.)? (y/N)",
|
|
3031
|
-
"setup.
|
|
3032
|
+
"setup.security_paths_restrict": " Restrict access to .git/, .env, node_modules/? (Y/n)",
|
|
3032
3033
|
"skill.already_loaded": 'Skill "{name}" is already loaded',
|
|
3033
3034
|
"skill.not_found": 'Skill "{name}" not found in any source directory',
|
|
3034
3035
|
"skill.no_match": "No skills match for: {task}",
|
|
@@ -3605,7 +3606,7 @@ var init_ru = __esm(() => {
|
|
|
3605
3606
|
"cli.config_key": "Ключ конфига (напр., model, provider.baseUrl)",
|
|
3606
3607
|
"cli.set_value": "Установить значение",
|
|
3607
3608
|
"cli.set_done": "Установлено {key}={value}",
|
|
3608
|
-
"cli.show_config": "Показать
|
|
3609
|
+
"cli.show_config": "Показать действующую конфигурацию (секреты скрыты; используйте --show-secrets)",
|
|
3609
3610
|
"cli.migrate_config": "Мигрировать legacy config.json в domain-формат",
|
|
3610
3611
|
"cli.manage_models": "Управление моделями",
|
|
3611
3612
|
"cli.list_models": "Список доступных моделей",
|
|
@@ -3676,6 +3677,7 @@ var init_ru = __esm(() => {
|
|
|
3676
3677
|
"cli.show_details": "Показать детали сессии",
|
|
3677
3678
|
"cli.delete_session": "Удалить сессию",
|
|
3678
3679
|
"cli.first_run": "Первый запуск. Запускаем мастер настройки...",
|
|
3680
|
+
"cli.first_run_oneshot": "Конфигурация не найдена — запуск с настройками по умолчанию. Запустите `mma` без аргументов один раз для настройки.",
|
|
3679
3681
|
"cli.setup_saved_restart": "Настройки сохранены. Перезапуск с новой конфигурацией...",
|
|
3680
3682
|
"cli.unknown_cmd": "Неизвестная команда: {name}.",
|
|
3681
3683
|
"cli.unknown_command": 'Неизвестная команда "{input}". Возможно, вы имели в виду "{suggestion}"?',
|
|
@@ -3904,7 +3906,7 @@ var init_ru = __esm(() => {
|
|
|
3904
3906
|
"setup.security_configure": " Настроить безопасность? (y/N)",
|
|
3905
3907
|
"setup.security_bash_block": " Блокировать опасные команды (rm, sudo, ssh и т.д.)? (y/N)",
|
|
3906
3908
|
"setup.security_flags_block": " Блокировать опасные флаги (--force, -rf и т.д.)? (y/N)",
|
|
3907
|
-
"setup.
|
|
3909
|
+
"setup.security_paths_restrict": " Ограничить доступ к .git/, .env, node_modules/? (Y/n)",
|
|
3908
3910
|
"skill.already_loaded": 'Скилл "{name}" уже загружен',
|
|
3909
3911
|
"skill.not_found": 'Скилл "{name}" не найден ни в одном каталоге',
|
|
3910
3912
|
"skill.no_match": "Нет скиллов подходящих для: {task}",
|
|
@@ -5324,9 +5326,6 @@ function loadConfig(options) {
|
|
|
5324
5326
|
config = deepMerge(config, domainConfig);
|
|
5325
5327
|
legacyDetected = false;
|
|
5326
5328
|
}
|
|
5327
|
-
if (!globalData && !domainConfig) {
|
|
5328
|
-
saveDomainFiles(config, options.configDir);
|
|
5329
|
-
}
|
|
5330
5329
|
const projectData = loadJSON(options.projectConfigPath);
|
|
5331
5330
|
if (projectData) {
|
|
5332
5331
|
config = deepMerge(config, projectData);
|
|
@@ -29592,11 +29591,12 @@ async function runSetup(externalRl) {
|
|
|
29592
29591
|
const configureSecurity = await ask(rl, t("setup.security_configure"), "n");
|
|
29593
29592
|
let securityBashBlock = false;
|
|
29594
29593
|
let securityFlagsBlock = false;
|
|
29595
|
-
let
|
|
29594
|
+
let securityPathsRestrict = false;
|
|
29596
29595
|
if (configureSecurity.toLowerCase() === "y" || configureSecurity.toLowerCase() === "yes") {
|
|
29597
29596
|
securityBashBlock = (await ask(rl, t("setup.security_bash_block"), "n")).toLowerCase() === "y";
|
|
29598
29597
|
securityFlagsBlock = (await ask(rl, t("setup.security_flags_block"), "n")).toLowerCase() === "y";
|
|
29599
|
-
|
|
29598
|
+
const pathsAnswer = (await ask(rl, t("setup.security_paths_restrict"), "Y")).toLowerCase();
|
|
29599
|
+
securityPathsRestrict = pathsAnswer !== "n" && pathsAnswer !== "no";
|
|
29600
29600
|
}
|
|
29601
29601
|
if (ownRl) {
|
|
29602
29602
|
rl.close();
|
|
@@ -29611,7 +29611,7 @@ async function runSetup(externalRl) {
|
|
|
29611
29611
|
locale,
|
|
29612
29612
|
securityBashBlock,
|
|
29613
29613
|
securityFlagsBlock,
|
|
29614
|
-
|
|
29614
|
+
securityPathsRestrict
|
|
29615
29615
|
};
|
|
29616
29616
|
getDefaultChannel().writeLine(pc.green(pc.bold(t("setup.complete"))));
|
|
29617
29617
|
const summary = [
|
|
@@ -29652,6 +29652,73 @@ var init_setup = __esm(() => {
|
|
|
29652
29652
|
];
|
|
29653
29653
|
});
|
|
29654
29654
|
|
|
29655
|
+
// src/cli/setup-order.ts
|
|
29656
|
+
function applyAnswersToConfig(config, a) {
|
|
29657
|
+
config.provider = {
|
|
29658
|
+
...config.provider,
|
|
29659
|
+
type: a.provider,
|
|
29660
|
+
baseUrl: a.apiBase,
|
|
29661
|
+
apiKey: a.apiKey
|
|
29662
|
+
};
|
|
29663
|
+
config.model = a.model;
|
|
29664
|
+
config.contextWindow = a.contextWindow;
|
|
29665
|
+
config.maxToolIterations = a.maxToolIterations;
|
|
29666
|
+
config.locale = a.locale;
|
|
29667
|
+
if ((config.provider.entries?.length ?? 0) > 0) {
|
|
29668
|
+
const entries = config.provider.entries ?? [];
|
|
29669
|
+
const activeName = config.provider.active || entries[0]?.label || entries[0]?.type;
|
|
29670
|
+
const idx = entries.findIndex((e) => e.label === activeName || e.type === activeName);
|
|
29671
|
+
const target = idx >= 0 ? idx : 0;
|
|
29672
|
+
const current = entries[target];
|
|
29673
|
+
const keepLabel = Boolean(current.label && current.label !== current.type);
|
|
29674
|
+
const updated = {
|
|
29675
|
+
...current,
|
|
29676
|
+
type: a.provider,
|
|
29677
|
+
baseUrl: a.apiBase,
|
|
29678
|
+
apiKey: a.apiKey,
|
|
29679
|
+
contextWindow: a.contextWindow,
|
|
29680
|
+
...keepLabel ? {} : { label: a.provider }
|
|
29681
|
+
};
|
|
29682
|
+
const next = entries.slice();
|
|
29683
|
+
next[target] = updated;
|
|
29684
|
+
config.provider.entries = next;
|
|
29685
|
+
config.provider.active = updated.label || updated.type;
|
|
29686
|
+
}
|
|
29687
|
+
if (config.security) {
|
|
29688
|
+
config.security.enabled = true;
|
|
29689
|
+
config.security.bash.enabled = true;
|
|
29690
|
+
config.security.bash.blockDangerousFlags = a.securityFlagsBlock || config.security.bash.blockDangerousFlags;
|
|
29691
|
+
if (a.securityBashBlock) {
|
|
29692
|
+
config.security.bash.blacklist = [
|
|
29693
|
+
...new Set([...config.security.bash.blacklist, ...SECURITY_BASH_BLOCKLIST])
|
|
29694
|
+
];
|
|
29695
|
+
}
|
|
29696
|
+
config.security.paths.enabled = a.securityPathsRestrict;
|
|
29697
|
+
}
|
|
29698
|
+
return config;
|
|
29699
|
+
}
|
|
29700
|
+
var SECURITY_BASH_BLOCKLIST;
|
|
29701
|
+
var init_setup_order = __esm(() => {
|
|
29702
|
+
SECURITY_BASH_BLOCKLIST = [
|
|
29703
|
+
"rm",
|
|
29704
|
+
"dd",
|
|
29705
|
+
"chmod",
|
|
29706
|
+
"wget",
|
|
29707
|
+
"curl",
|
|
29708
|
+
"scp",
|
|
29709
|
+
"ssh",
|
|
29710
|
+
"nc",
|
|
29711
|
+
"netcat",
|
|
29712
|
+
"sudo",
|
|
29713
|
+
"su",
|
|
29714
|
+
"kill",
|
|
29715
|
+
"pkill",
|
|
29716
|
+
"killall",
|
|
29717
|
+
"shutdown",
|
|
29718
|
+
"reboot"
|
|
29719
|
+
];
|
|
29720
|
+
});
|
|
29721
|
+
|
|
29655
29722
|
// src/modules/indexer/map-command.ts
|
|
29656
29723
|
async function runMapAction(module, action, query) {
|
|
29657
29724
|
const summary = async () => {
|
|
@@ -37947,7 +38014,7 @@ __export(exports_repl_commands, {
|
|
|
37947
38014
|
registerAllCommands: () => registerAllCommands,
|
|
37948
38015
|
COMMAND_GROUPS: () => COMMAND_GROUPS
|
|
37949
38016
|
});
|
|
37950
|
-
import { join as
|
|
38017
|
+
import { join as join55, dirname as dirname25 } from "path";
|
|
37951
38018
|
import { existsSync as existsSync60 } from "fs";
|
|
37952
38019
|
function registerAllCommands(ctx) {
|
|
37953
38020
|
registerBuiltinCommands(ctx);
|
|
@@ -38148,14 +38215,8 @@ function registerConfigCommands(ctx) {
|
|
|
38148
38215
|
ctx.output.writeLine(pc.yellow(t("repl.wizard_running")));
|
|
38149
38216
|
await ctx.withExclusiveInput(async () => {
|
|
38150
38217
|
const answers = await runSetup(ctx.rl);
|
|
38151
|
-
const configPath =
|
|
38152
|
-
ctx.config
|
|
38153
|
-
ctx.config.provider.baseUrl = answers.apiBase;
|
|
38154
|
-
ctx.config.provider.apiKey = answers.apiKey;
|
|
38155
|
-
ctx.config.model = answers.model;
|
|
38156
|
-
ctx.config.contextWindow = answers.contextWindow;
|
|
38157
|
-
ctx.config.maxToolIterations = answers.maxToolIterations;
|
|
38158
|
-
ctx.config.locale = answers.locale;
|
|
38218
|
+
const configPath = join55(ctx.configDir, "config.json");
|
|
38219
|
+
applyAnswersToConfig(ctx.config, answers);
|
|
38159
38220
|
saveConfig(ctx.config, configPath, dirname25(configPath));
|
|
38160
38221
|
await ctx.agent.reconfigure(ctx.config);
|
|
38161
38222
|
ctx.output.writeLine(pc.green(t("cli.config_saved")));
|
|
@@ -38279,7 +38340,7 @@ function registerProviderCommands(ctx) {
|
|
|
38279
38340
|
});
|
|
38280
38341
|
ctx.config.provider.entries = entries;
|
|
38281
38342
|
ctx.config.provider.active = ctx.config.provider.active || ctx.config.provider.type;
|
|
38282
|
-
const configPath =
|
|
38343
|
+
const configPath = join55(ctx.configDir, "config.json");
|
|
38283
38344
|
saveConfig(ctx.config, configPath, dirname25(configPath));
|
|
38284
38345
|
await ctx.agent.reconfigure(ctx.config);
|
|
38285
38346
|
ctx.output.writeLine(pc.green(t("cli.provider_added", { name })));
|
|
@@ -38346,7 +38407,7 @@ function registerProviderCommands(ctx) {
|
|
|
38346
38407
|
return;
|
|
38347
38408
|
}
|
|
38348
38409
|
ctx.config.model = name;
|
|
38349
|
-
const configPath =
|
|
38410
|
+
const configPath = join55(ctx.configDir, "config.json");
|
|
38350
38411
|
saveConfig(ctx.config, configPath, dirname25(configPath));
|
|
38351
38412
|
await ctx.agent.reconfigure(ctx.config);
|
|
38352
38413
|
ctx.output.writeLine(pc.green(t("repl.model_set", { name })));
|
|
@@ -38375,7 +38436,7 @@ function registerProviderCommands(ctx) {
|
|
|
38375
38436
|
usage: t("repl.context_usage"),
|
|
38376
38437
|
action: async (args) => {
|
|
38377
38438
|
const save = async () => {
|
|
38378
|
-
const configPath =
|
|
38439
|
+
const configPath = join55(ctx.configDir, "config.json");
|
|
38379
38440
|
saveConfig(ctx.config, configPath, dirname25(configPath));
|
|
38380
38441
|
await ctx.agent.reconfigure(ctx.config);
|
|
38381
38442
|
};
|
|
@@ -38768,11 +38829,11 @@ function registerSkillCommands(ctx) {
|
|
|
38768
38829
|
});
|
|
38769
38830
|
}
|
|
38770
38831
|
async function runConfigMigrate(ctx) {
|
|
38771
|
-
const { hasDomainFiles:
|
|
38832
|
+
const { hasDomainFiles: hasDomainFiles2 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
38772
38833
|
const { loadConfig: loadCfg } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
38773
38834
|
const configDir = ctx.configDir;
|
|
38774
|
-
const configPath =
|
|
38775
|
-
if (
|
|
38835
|
+
const configPath = join55(configDir, "config.json");
|
|
38836
|
+
if (hasDomainFiles2(configDir)) {
|
|
38776
38837
|
ctx.output.writeLine(pc.yellow(t("config.migrate_no_legacy")));
|
|
38777
38838
|
return;
|
|
38778
38839
|
}
|
|
@@ -38781,11 +38842,11 @@ async function runConfigMigrate(ctx) {
|
|
|
38781
38842
|
return;
|
|
38782
38843
|
}
|
|
38783
38844
|
ctx.output.writeLine(t("config.migrate_start"));
|
|
38784
|
-
const { config } = loadCfg({ configDir, projectConfigPath:
|
|
38845
|
+
const { config } = loadCfg({ configDir, projectConfigPath: join55(configDir, ".mmrc") });
|
|
38785
38846
|
saveConfig(config, configPath, configDir);
|
|
38786
|
-
const { renameSync: renameSync4, readdirSync:
|
|
38847
|
+
const { renameSync: renameSync4, readdirSync: readdirSync20 } = await import("fs");
|
|
38787
38848
|
renameSync4(configPath, configPath + ".bak");
|
|
38788
|
-
const domainFiles =
|
|
38849
|
+
const domainFiles = readdirSync20(join55(configDir, "config")).filter((f) => f.endsWith(".json"));
|
|
38789
38850
|
ctx.output.writeLine(pc.green(t("config.migrate_done", { count: String(domainFiles.length) })));
|
|
38790
38851
|
}
|
|
38791
38852
|
var version2, COMMAND_GROUPS;
|
|
@@ -38795,6 +38856,7 @@ var init_repl_commands = __esm(() => {
|
|
|
38795
38856
|
init_table();
|
|
38796
38857
|
init_i18n();
|
|
38797
38858
|
init_setup();
|
|
38859
|
+
init_setup_order();
|
|
38798
38860
|
init_config2();
|
|
38799
38861
|
init_presets();
|
|
38800
38862
|
init_budget();
|
|
@@ -38850,6 +38912,7 @@ var {
|
|
|
38850
38912
|
init_bootstrap();
|
|
38851
38913
|
init_config2();
|
|
38852
38914
|
init_setup();
|
|
38915
|
+
init_setup_order();
|
|
38853
38916
|
init_i18n();
|
|
38854
38917
|
init_colors();
|
|
38855
38918
|
import { join as join53, dirname as dirname24 } from "path";
|
|
@@ -39363,7 +39426,7 @@ function createSecurityCommand(program2) {
|
|
|
39363
39426
|
const auditNotifier = security.auditNotifier || {};
|
|
39364
39427
|
getDefaultChannel().writeLine(t("cli.security.current_policy"));
|
|
39365
39428
|
getDefaultChannel().writeLine(` ${t("cli.security.bash_enabled")}: ${bash.blacklist?.length > 0 ? t("cli.yes") : t("cli.no")}`);
|
|
39366
|
-
getDefaultChannel().writeLine(` ${t("cli.security.path_validation")}: ${paths.
|
|
39429
|
+
getDefaultChannel().writeLine(` ${t("cli.security.path_validation")}: ${paths.enabled ? t("cli.yes") : t("cli.no")}`);
|
|
39367
39430
|
getDefaultChannel().writeLine(` ${t("cli.security.network_validation")}: ${network.deniedDomains?.length > 0 || network.allowedDomains?.length > 0 ? t("cli.yes") : t("cli.no")}`);
|
|
39368
39431
|
getDefaultChannel().writeLine(` ${t("cli.security.content_scanning")}: ${contentScan.enabled ? t("cli.yes") : t("cli.no")}`);
|
|
39369
39432
|
getDefaultChannel().writeLine(` ${t("cli.security.max_recursion")}: ${security.maxRecursionDepth ?? 3}`);
|
|
@@ -39671,50 +39734,60 @@ function extractLatestChangelog(changelog) {
|
|
|
39671
39734
|
|
|
39672
39735
|
// src/cli/commands.ts
|
|
39673
39736
|
init_output();
|
|
39737
|
+
|
|
39738
|
+
// src/config/redact.ts
|
|
39739
|
+
var SECRET_KEYS = new Set([
|
|
39740
|
+
"apiKey",
|
|
39741
|
+
"api_key",
|
|
39742
|
+
"apikey",
|
|
39743
|
+
"token",
|
|
39744
|
+
"tokens",
|
|
39745
|
+
"secret",
|
|
39746
|
+
"password",
|
|
39747
|
+
"authorization",
|
|
39748
|
+
"webhookUrl"
|
|
39749
|
+
]);
|
|
39750
|
+
var SECRET_MAPS = new Set(["headers", "env"]);
|
|
39751
|
+
var MASK = "***";
|
|
39752
|
+
function walk(value, parentKey, depth = 0) {
|
|
39753
|
+
if (depth > 100)
|
|
39754
|
+
return value;
|
|
39755
|
+
if (typeof value === "string") {
|
|
39756
|
+
return parentKey && SECRET_KEYS.has(parentKey) ? MASK : value;
|
|
39757
|
+
}
|
|
39758
|
+
if (Array.isArray(value)) {
|
|
39759
|
+
return value.map((v) => walk(v, parentKey, depth + 1));
|
|
39760
|
+
}
|
|
39761
|
+
if (value && typeof value === "object" && !(value instanceof RegExp)) {
|
|
39762
|
+
if (parentKey && SECRET_MAPS.has(parentKey)) {
|
|
39763
|
+
const masked = {};
|
|
39764
|
+
for (const k of Object.keys(value))
|
|
39765
|
+
masked[k] = MASK;
|
|
39766
|
+
return masked;
|
|
39767
|
+
}
|
|
39768
|
+
const out = {};
|
|
39769
|
+
for (const [k, v] of Object.entries(value)) {
|
|
39770
|
+
out[k] = walk(v, k, depth + 1);
|
|
39771
|
+
}
|
|
39772
|
+
return out;
|
|
39773
|
+
}
|
|
39774
|
+
return value;
|
|
39775
|
+
}
|
|
39776
|
+
function redactConfigSecrets(config) {
|
|
39777
|
+
return walk(config);
|
|
39778
|
+
}
|
|
39779
|
+
|
|
39780
|
+
// src/cli/commands.ts
|
|
39674
39781
|
var version = readMmaVersion();
|
|
39782
|
+
function configForDisplay(config, showSecrets) {
|
|
39783
|
+
return showSecrets ? config : redactConfigSecrets(config);
|
|
39784
|
+
}
|
|
39675
39785
|
function buildInitCommand(program2) {
|
|
39676
39786
|
program2.command("init").description(t("cli.init")).action(async () => {
|
|
39677
39787
|
const answers = await runSetup();
|
|
39678
39788
|
const configPath = join53(homedir17(), ".mma", "config.json");
|
|
39679
39789
|
const { config } = await bootstrap();
|
|
39680
|
-
config
|
|
39681
|
-
config.provider.baseUrl = answers.apiBase;
|
|
39682
|
-
config.provider.apiKey = answers.apiKey;
|
|
39683
|
-
config.model = answers.model;
|
|
39684
|
-
config.contextWindow = answers.contextWindow;
|
|
39685
|
-
config.maxToolIterations = answers.maxToolIterations;
|
|
39686
|
-
config.locale = answers.locale;
|
|
39687
|
-
if (config.security) {
|
|
39688
|
-
config.security.enabled = true;
|
|
39689
|
-
config.security.bash.enabled = true;
|
|
39690
|
-
config.security.bash.blockDangerousFlags = answers.securityFlagsBlock || config.security.bash.blockDangerousFlags;
|
|
39691
|
-
if (answers.securityBashBlock) {
|
|
39692
|
-
config.security.bash.blacklist = [
|
|
39693
|
-
...new Set([
|
|
39694
|
-
...config.security.bash.blacklist,
|
|
39695
|
-
"rm",
|
|
39696
|
-
"dd",
|
|
39697
|
-
"chmod",
|
|
39698
|
-
"wget",
|
|
39699
|
-
"curl",
|
|
39700
|
-
"scp",
|
|
39701
|
-
"ssh",
|
|
39702
|
-
"nc",
|
|
39703
|
-
"netcat",
|
|
39704
|
-
"sudo",
|
|
39705
|
-
"su",
|
|
39706
|
-
"kill",
|
|
39707
|
-
"pkill",
|
|
39708
|
-
"killall",
|
|
39709
|
-
"shutdown",
|
|
39710
|
-
"reboot"
|
|
39711
|
-
])
|
|
39712
|
-
];
|
|
39713
|
-
}
|
|
39714
|
-
if (!answers.securityPathsDeny) {
|
|
39715
|
-
config.security.paths.denied = [];
|
|
39716
|
-
}
|
|
39717
|
-
}
|
|
39790
|
+
applyAnswersToConfig(config, answers);
|
|
39718
39791
|
saveConfig(config, configPath, dirname24(configPath));
|
|
39719
39792
|
getDefaultChannel().writeLine(t("cli.config_saved"));
|
|
39720
39793
|
});
|
|
@@ -39745,16 +39818,16 @@ function buildConfigCommands(program2) {
|
|
|
39745
39818
|
saveConfig(config, configPath, dirname24(configPath));
|
|
39746
39819
|
getDefaultChannel().writeLine(t("cli.set_done", { key, value }));
|
|
39747
39820
|
});
|
|
39748
|
-
configCmd.command("show").description(t("cli.show_config")).action(async () => {
|
|
39821
|
+
configCmd.command("show").description(t("cli.show_config")).option("--show-secrets", "Print secrets (API keys, tokens) unredacted").action(async (opts) => {
|
|
39749
39822
|
const { config } = await bootstrap();
|
|
39750
|
-
writeMachineJson(config);
|
|
39823
|
+
writeMachineJson(configForDisplay(config, opts.showSecrets));
|
|
39751
39824
|
});
|
|
39752
39825
|
configCmd.command("migrate").description(t("cli.migrate_config")).action(async () => {
|
|
39753
39826
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
39754
|
-
const { hasDomainFiles:
|
|
39827
|
+
const { hasDomainFiles: hasDomainFiles2 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
39755
39828
|
const configDir = join53(homedir17(), ".mma");
|
|
39756
39829
|
const configPath = join53(configDir, "config.json");
|
|
39757
|
-
if (
|
|
39830
|
+
if (hasDomainFiles2(configDir)) {
|
|
39758
39831
|
getDefaultChannel().writeLine(pc.yellow(t("config.migrate_no_legacy")));
|
|
39759
39832
|
return;
|
|
39760
39833
|
}
|
|
@@ -40176,6 +40249,7 @@ import * as readline2 from "readline";
|
|
|
40176
40249
|
|
|
40177
40250
|
// src/ui/line-editor.ts
|
|
40178
40251
|
init_string_width();
|
|
40252
|
+
init_colors();
|
|
40179
40253
|
import * as readline from "readline";
|
|
40180
40254
|
|
|
40181
40255
|
// src/ui/line-math.ts
|
|
@@ -40288,6 +40362,7 @@ class LineEditor {
|
|
|
40288
40362
|
pasteLastWasCR = false;
|
|
40289
40363
|
lastWasCR = false;
|
|
40290
40364
|
questionCb = null;
|
|
40365
|
+
completionSession = null;
|
|
40291
40366
|
rawMode = false;
|
|
40292
40367
|
listeners = {};
|
|
40293
40368
|
dsrDataHandler;
|
|
@@ -40421,6 +40496,7 @@ class LineEditor {
|
|
|
40421
40496
|
this.col = 0;
|
|
40422
40497
|
this.historyIndex = -1;
|
|
40423
40498
|
this.stash = null;
|
|
40499
|
+
this.completionSession = null;
|
|
40424
40500
|
this.invalidateAnchor();
|
|
40425
40501
|
if (this.input.isTTY)
|
|
40426
40502
|
this.render();
|
|
@@ -40431,6 +40507,7 @@ class LineEditor {
|
|
|
40431
40507
|
this.lines = [""];
|
|
40432
40508
|
this.row = 0;
|
|
40433
40509
|
this.col = 0;
|
|
40510
|
+
this.completionSession = null;
|
|
40434
40511
|
this.invalidateAnchor();
|
|
40435
40512
|
if (this.input.isTTY)
|
|
40436
40513
|
this.render();
|
|
@@ -40496,6 +40573,27 @@ class LineEditor {
|
|
|
40496
40573
|
}
|
|
40497
40574
|
return;
|
|
40498
40575
|
}
|
|
40576
|
+
if (this.completionSession) {
|
|
40577
|
+
const ck = key;
|
|
40578
|
+
const plain = !ck.ctrl && !ck.meta;
|
|
40579
|
+
if (ck?.name === "down" && plain) {
|
|
40580
|
+
this.cycleCompletion(1);
|
|
40581
|
+
return;
|
|
40582
|
+
}
|
|
40583
|
+
if (ck?.name === "up" && plain) {
|
|
40584
|
+
this.cycleCompletion(-1);
|
|
40585
|
+
return;
|
|
40586
|
+
}
|
|
40587
|
+
if (ck?.name === "tab") {
|
|
40588
|
+
this.cycleCompletion(1);
|
|
40589
|
+
return;
|
|
40590
|
+
}
|
|
40591
|
+
if (ck?.name === "escape") {
|
|
40592
|
+
this.cancelCompletion();
|
|
40593
|
+
return;
|
|
40594
|
+
}
|
|
40595
|
+
this.completionSession = null;
|
|
40596
|
+
}
|
|
40499
40597
|
if (this.onKeyInput && this.onKeyInput(str, key))
|
|
40500
40598
|
return;
|
|
40501
40599
|
const k = key;
|
|
@@ -40674,6 +40772,7 @@ class LineEditor {
|
|
|
40674
40772
|
}
|
|
40675
40773
|
}
|
|
40676
40774
|
submit() {
|
|
40775
|
+
this.completionSession = null;
|
|
40677
40776
|
if (this.questionCb) {
|
|
40678
40777
|
const cb = this.questionCb;
|
|
40679
40778
|
this.questionCb = null;
|
|
@@ -40729,6 +40828,7 @@ class LineEditor {
|
|
|
40729
40828
|
this.lines = [""];
|
|
40730
40829
|
this.row = 0;
|
|
40731
40830
|
this.col = 0;
|
|
40831
|
+
this.completionSession = null;
|
|
40732
40832
|
this.invalidateAnchor();
|
|
40733
40833
|
this.render();
|
|
40734
40834
|
if (this.onInterrupt) {
|
|
@@ -40753,6 +40853,7 @@ class LineEditor {
|
|
|
40753
40853
|
this.lines[this.row] = chars.join("");
|
|
40754
40854
|
}
|
|
40755
40855
|
insertText(text) {
|
|
40856
|
+
this.completionSession = null;
|
|
40756
40857
|
const sanitized = text.replace(/\r\n/g, `
|
|
40757
40858
|
`).replace(/\r/g, "");
|
|
40758
40859
|
const chars = this.currentChars();
|
|
@@ -40967,6 +41068,7 @@ class LineEditor {
|
|
|
40967
41068
|
}
|
|
40968
41069
|
}
|
|
40969
41070
|
applyHistoryEntry() {
|
|
41071
|
+
this.completionSession = null;
|
|
40970
41072
|
const entry = this.history[this.history.length - 1 - this.historyIndex];
|
|
40971
41073
|
this.lines = entry.split(`
|
|
40972
41074
|
`);
|
|
@@ -40976,6 +41078,49 @@ class LineEditor {
|
|
|
40976
41078
|
this.col = charLen(this.lines[this.row]);
|
|
40977
41079
|
this.render();
|
|
40978
41080
|
}
|
|
41081
|
+
replaceCompletionToken(from, removeText, insertText) {
|
|
41082
|
+
const line = this.lines[this.row];
|
|
41083
|
+
const head = line.slice(0, from);
|
|
41084
|
+
const tail = line.slice(from + removeText.length);
|
|
41085
|
+
this.lines[this.row] = head + insertText + tail;
|
|
41086
|
+
this.col = charLen(head) + charLen(insertText);
|
|
41087
|
+
}
|
|
41088
|
+
partialStart(line, partial) {
|
|
41089
|
+
const chars = Array.from(line);
|
|
41090
|
+
const beforeCursor = chars.slice(0, this.col).join("");
|
|
41091
|
+
let from = beforeCursor.lastIndexOf(partial);
|
|
41092
|
+
if (from === -1)
|
|
41093
|
+
from = line.lastIndexOf(partial);
|
|
41094
|
+
return from;
|
|
41095
|
+
}
|
|
41096
|
+
applyCompletionCandidate(index) {
|
|
41097
|
+
const s = this.completionSession;
|
|
41098
|
+
if (!s)
|
|
41099
|
+
return;
|
|
41100
|
+
const chosen = s.items[index].value;
|
|
41101
|
+
this.replaceCompletionToken(s.from, s.inserted, chosen);
|
|
41102
|
+
s.index = index;
|
|
41103
|
+
s.inserted = chosen;
|
|
41104
|
+
this.render();
|
|
41105
|
+
}
|
|
41106
|
+
cycleCompletion(delta) {
|
|
41107
|
+
const s = this.completionSession;
|
|
41108
|
+
if (!s)
|
|
41109
|
+
return;
|
|
41110
|
+
const n = s.items.length;
|
|
41111
|
+
if (n === 0)
|
|
41112
|
+
return;
|
|
41113
|
+
const next = (s.index + delta + n) % n;
|
|
41114
|
+
this.applyCompletionCandidate(next);
|
|
41115
|
+
}
|
|
41116
|
+
cancelCompletion() {
|
|
41117
|
+
const s = this.completionSession;
|
|
41118
|
+
if (!s)
|
|
41119
|
+
return;
|
|
41120
|
+
this.replaceCompletionToken(s.from, s.inserted, s.original);
|
|
41121
|
+
this.completionSession = null;
|
|
41122
|
+
this.render();
|
|
41123
|
+
}
|
|
40979
41124
|
tabComplete() {
|
|
40980
41125
|
if (!this.completer)
|
|
40981
41126
|
return;
|
|
@@ -40986,28 +41131,53 @@ class LineEditor {
|
|
|
40986
41131
|
return;
|
|
40987
41132
|
}
|
|
40988
41133
|
if (matches.length === 1) {
|
|
40989
|
-
const
|
|
40990
|
-
|
|
40991
|
-
let from = beforeCursor.lastIndexOf(partial);
|
|
40992
|
-
if (from === -1)
|
|
40993
|
-
from = line.lastIndexOf(partial);
|
|
40994
|
-
if (from === -1) {
|
|
41134
|
+
const from2 = this.partialStart(line, partial);
|
|
41135
|
+
if (from2 === -1) {
|
|
40995
41136
|
this.output.write("\x07");
|
|
40996
41137
|
return;
|
|
40997
41138
|
}
|
|
40998
|
-
|
|
40999
|
-
const tail = line.slice(from + partial.length);
|
|
41000
|
-
this.lines[this.row] = head + matches[0] + tail;
|
|
41001
|
-
this.col = charLen(head) + charLen(matches[0]);
|
|
41139
|
+
this.replaceCompletionToken(from2, partial, matches[0].value);
|
|
41002
41140
|
this.render();
|
|
41003
41141
|
return;
|
|
41004
41142
|
}
|
|
41005
|
-
const
|
|
41143
|
+
const from = this.partialStart(line, partial);
|
|
41144
|
+
if (from === -1) {
|
|
41145
|
+
this.output.write("\x07");
|
|
41146
|
+
return;
|
|
41147
|
+
}
|
|
41148
|
+
const width = this.columns();
|
|
41149
|
+
const limit = width - 1;
|
|
41150
|
+
const rows = matches.map((m) => {
|
|
41151
|
+
const plain = m.description ? ` ${m.value} ${m.description}` : ` ${m.value}`;
|
|
41152
|
+
if (limit <= 0)
|
|
41153
|
+
return "";
|
|
41154
|
+
if (stringWidth(plain) <= limit) {
|
|
41155
|
+
return m.description ? ` ${m.value} ${pc.dim(m.description)}` : ` ${m.value}`;
|
|
41156
|
+
}
|
|
41157
|
+
let acc = "";
|
|
41158
|
+
let w = 0;
|
|
41159
|
+
for (const ch of plain) {
|
|
41160
|
+
const cw = stringWidth(ch);
|
|
41161
|
+
if (w + cw > limit - 1)
|
|
41162
|
+
break;
|
|
41163
|
+
acc += ch;
|
|
41164
|
+
w += cw;
|
|
41165
|
+
}
|
|
41166
|
+
return acc + "…";
|
|
41167
|
+
});
|
|
41006
41168
|
this.output.write(`\r
|
|
41007
41169
|
` + rows.join(`\r
|
|
41008
41170
|
`) + `\r
|
|
41009
41171
|
`);
|
|
41010
41172
|
this.prevCursorRow += rows.length + 1;
|
|
41173
|
+
this.completionSession = {
|
|
41174
|
+
items: matches,
|
|
41175
|
+
index: 0,
|
|
41176
|
+
from,
|
|
41177
|
+
original: partial,
|
|
41178
|
+
inserted: matches[0].value
|
|
41179
|
+
};
|
|
41180
|
+
this.replaceCompletionToken(from, partial, matches[0].value);
|
|
41011
41181
|
this.render();
|
|
41012
41182
|
}
|
|
41013
41183
|
clearScreen() {
|
|
@@ -41144,10 +41314,19 @@ class LineEditor {
|
|
|
41144
41314
|
|
|
41145
41315
|
// src/cli/repl.ts
|
|
41146
41316
|
import { existsSync as existsSync61, mkdirSync as mkdirSync25, readFileSync as readFileSync42, writeFileSync as writeFileSync24 } from "fs";
|
|
41147
|
-
import { dirname as dirname26, join as
|
|
41317
|
+
import { dirname as dirname26, join as join56 } from "path";
|
|
41148
41318
|
import { homedir as homedir18 } from "os";
|
|
41149
41319
|
|
|
41150
41320
|
// src/cli/completer.ts
|
|
41321
|
+
import { readdirSync as readdirSync19, statSync as statSync11 } from "fs";
|
|
41322
|
+
import { join as join54 } from "path";
|
|
41323
|
+
function buildSlashCompletions(commands) {
|
|
41324
|
+
return Array.from(commands.entries()).map(([name, cmd]) => ({
|
|
41325
|
+
name,
|
|
41326
|
+
description: cmd.description
|
|
41327
|
+
}));
|
|
41328
|
+
}
|
|
41329
|
+
|
|
41151
41330
|
class SlashCommandProvider {
|
|
41152
41331
|
name = "slash-commands";
|
|
41153
41332
|
commands;
|
|
@@ -41158,7 +41337,7 @@ class SlashCommandProvider {
|
|
|
41158
41337
|
return ctx.tokenIndex === 0 && ctx.line.startsWith("/");
|
|
41159
41338
|
}
|
|
41160
41339
|
complete(ctx) {
|
|
41161
|
-
return this.commands.filter((c) => c.startsWith(ctx.partial.slice(1))).map((c) => `/${c}
|
|
41340
|
+
return this.commands.filter((c) => c.name.startsWith(ctx.partial.slice(1))).map((c) => ({ value: `/${c.name}`, description: c.description }));
|
|
41162
41341
|
}
|
|
41163
41342
|
}
|
|
41164
41343
|
|
|
@@ -41168,13 +41347,13 @@ class SubcommandProvider {
|
|
|
41168
41347
|
subcommands;
|
|
41169
41348
|
constructor(command, subcommands) {
|
|
41170
41349
|
this.command = command;
|
|
41171
|
-
this.subcommands = subcommands;
|
|
41350
|
+
this.subcommands = subcommands.map((s) => typeof s === "string" ? { name: s } : s);
|
|
41172
41351
|
}
|
|
41173
41352
|
match(ctx) {
|
|
41174
41353
|
return ctx.tokenIndex === 1 && ctx.tokens[0] === `/${this.command}`;
|
|
41175
41354
|
}
|
|
41176
41355
|
complete(ctx) {
|
|
41177
|
-
return this.subcommands.filter((s) => s.startsWith(ctx.partial));
|
|
41356
|
+
return this.subcommands.filter((s) => s.name.startsWith(ctx.partial)).map((s) => ({ value: s.name, description: s.description }));
|
|
41178
41357
|
}
|
|
41179
41358
|
}
|
|
41180
41359
|
|
|
@@ -41188,9 +41367,44 @@ class ModelArgProvider {
|
|
|
41188
41367
|
return ctx.tokenIndex === 2 && ctx.tokens[0] === "/model" && ctx.tokens[1] === "use";
|
|
41189
41368
|
}
|
|
41190
41369
|
complete(ctx) {
|
|
41191
|
-
return this.getModels().filter((m) => m.startsWith(ctx.partial));
|
|
41370
|
+
return this.getModels().filter((m) => m.startsWith(ctx.partial)).map((m) => ({ value: m }));
|
|
41192
41371
|
}
|
|
41193
41372
|
}
|
|
41373
|
+
|
|
41374
|
+
class FilePathProvider {
|
|
41375
|
+
name = "file-paths";
|
|
41376
|
+
root;
|
|
41377
|
+
constructor(root) {
|
|
41378
|
+
this.root = root;
|
|
41379
|
+
}
|
|
41380
|
+
match(ctx) {
|
|
41381
|
+
return ctx.tokenIndex >= 1 && (ctx.partial.includes("/") || ctx.partial.includes("\\"));
|
|
41382
|
+
}
|
|
41383
|
+
complete(ctx) {
|
|
41384
|
+
try {
|
|
41385
|
+
const cwd = this.root ?? process.cwd();
|
|
41386
|
+
const partialPath = ctx.partial;
|
|
41387
|
+
const lastSlash = Math.max(partialPath.lastIndexOf("/"), partialPath.lastIndexOf("\\"));
|
|
41388
|
+
const dirPath = lastSlash > 0 ? partialPath.slice(0, lastSlash) : ".";
|
|
41389
|
+
const prefix = lastSlash > 0 ? partialPath.slice(0, lastSlash + 1) : "";
|
|
41390
|
+
const fullPath = join54(cwd, dirPath);
|
|
41391
|
+
const entries = readdirSync19(fullPath);
|
|
41392
|
+
const matches = [];
|
|
41393
|
+
for (const entry of entries) {
|
|
41394
|
+
const entryPath = join54(fullPath, entry);
|
|
41395
|
+
const stat2 = statSync11(entryPath);
|
|
41396
|
+
const completion = prefix + entry + (stat2.isDirectory() ? "/" : "");
|
|
41397
|
+
if (completion.startsWith(ctx.partial)) {
|
|
41398
|
+
matches.push(completion);
|
|
41399
|
+
}
|
|
41400
|
+
}
|
|
41401
|
+
return matches.slice(0, 20).map((m) => ({ value: m }));
|
|
41402
|
+
} catch {
|
|
41403
|
+
return [];
|
|
41404
|
+
}
|
|
41405
|
+
}
|
|
41406
|
+
}
|
|
41407
|
+
|
|
41194
41408
|
class ProviderArgProvider {
|
|
41195
41409
|
name = "provider-args";
|
|
41196
41410
|
providers;
|
|
@@ -41201,7 +41415,7 @@ class ProviderArgProvider {
|
|
|
41201
41415
|
return ctx.tokenIndex === 2 && ctx.tokens[0] === "/provider" && ctx.tokens[1] === "use";
|
|
41202
41416
|
}
|
|
41203
41417
|
complete(ctx) {
|
|
41204
|
-
return this.providers.filter((p) => p.startsWith(ctx.partial));
|
|
41418
|
+
return this.providers.filter((p) => p.startsWith(ctx.partial)).map((p) => ({ value: p }));
|
|
41205
41419
|
}
|
|
41206
41420
|
}
|
|
41207
41421
|
|
|
@@ -41216,9 +41430,8 @@ class SessionNameProvider {
|
|
|
41216
41430
|
}
|
|
41217
41431
|
complete(ctx) {
|
|
41218
41432
|
const names = this.getNames();
|
|
41219
|
-
|
|
41220
|
-
|
|
41221
|
-
return names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
|
|
41433
|
+
const filtered = !ctx.partial ? names : names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
|
|
41434
|
+
return filtered.map((n) => ({ value: n }));
|
|
41222
41435
|
}
|
|
41223
41436
|
}
|
|
41224
41437
|
|
|
@@ -41240,9 +41453,8 @@ class SkillNameProvider {
|
|
|
41240
41453
|
if (!source)
|
|
41241
41454
|
return [];
|
|
41242
41455
|
const names = source();
|
|
41243
|
-
|
|
41244
|
-
|
|
41245
|
-
return names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
|
|
41456
|
+
const filtered = !ctx.partial ? names : names.filter((n) => n.toLowerCase().includes(ctx.partial.toLowerCase()));
|
|
41457
|
+
return filtered.map((n) => ({ value: n }));
|
|
41246
41458
|
}
|
|
41247
41459
|
}
|
|
41248
41460
|
|
|
@@ -41354,19 +41566,22 @@ function toolCategory(tool) {
|
|
|
41354
41566
|
}
|
|
41355
41567
|
return "meta";
|
|
41356
41568
|
}
|
|
41357
|
-
function
|
|
41569
|
+
function toolAccent(tool) {
|
|
41358
41570
|
switch (toolCategory(tool)) {
|
|
41359
41571
|
case "recon":
|
|
41360
|
-
return pc.cyan
|
|
41572
|
+
return pc.cyan;
|
|
41361
41573
|
case "mutate":
|
|
41362
|
-
return pc.magenta
|
|
41574
|
+
return pc.magenta;
|
|
41363
41575
|
case "execute":
|
|
41364
|
-
return pc.blue
|
|
41576
|
+
return pc.blue;
|
|
41365
41577
|
case "meta":
|
|
41366
41578
|
default:
|
|
41367
|
-
return pc.dim
|
|
41579
|
+
return pc.dim;
|
|
41368
41580
|
}
|
|
41369
41581
|
}
|
|
41582
|
+
function actionMarkFor(tool) {
|
|
41583
|
+
return toolAccent(tool)(glyph.action);
|
|
41584
|
+
}
|
|
41370
41585
|
function successMark() {
|
|
41371
41586
|
return pc.green(glyph.success);
|
|
41372
41587
|
}
|
|
@@ -41861,11 +42076,7 @@ class Renderer {
|
|
|
41861
42076
|
meta(chunk) {
|
|
41862
42077
|
this.spinner.stop();
|
|
41863
42078
|
if (this.thoughtStarted) {
|
|
41864
|
-
|
|
41865
|
-
this.channel.writeRaw(`
|
|
41866
|
-
${pc.magenta(glyph.thinking)} ${pc.dim(this.thinkingLabel)} `);
|
|
41867
|
-
this.thoughtHeaderPrinted = true;
|
|
41868
|
-
}
|
|
42079
|
+
this.writeThoughtHeader();
|
|
41869
42080
|
this.channel.writeRaw(pc.dim(chunk));
|
|
41870
42081
|
} else if (this.card) {
|
|
41871
42082
|
this.writeInlineBody(chunk);
|
|
@@ -41901,13 +42112,16 @@ ${pc.magenta(glyph.thinking)} ${pc.dim(this.thinkingLabel)} `);
|
|
|
41901
42112
|
reasoning(chunk) {
|
|
41902
42113
|
this.spinner.stop();
|
|
41903
42114
|
this.flushRecon();
|
|
41904
|
-
|
|
41905
|
-
this.channel.writeRaw(`
|
|
41906
|
-
${pc.magenta(glyph.thinking)} ${pc.dim(this.thinkingLabel)} `);
|
|
41907
|
-
this.thoughtHeaderPrinted = true;
|
|
41908
|
-
}
|
|
42115
|
+
this.writeThoughtHeader();
|
|
41909
42116
|
this.channel.writeRaw(pc.dim(chunk));
|
|
41910
42117
|
}
|
|
42118
|
+
writeThoughtHeader() {
|
|
42119
|
+
if (!this.thoughtStarted || this.thoughtHeaderPrinted)
|
|
42120
|
+
return;
|
|
42121
|
+
this.channel.writeRaw(`
|
|
42122
|
+
${pc.magenta(glyph.thinking)} ${pc.magenta(this.thinkingLabel)} ${pc.dim("·")} `);
|
|
42123
|
+
this.thoughtHeaderPrinted = true;
|
|
42124
|
+
}
|
|
41911
42125
|
thinkingStart() {
|
|
41912
42126
|
this.flushRecon();
|
|
41913
42127
|
this.thoughtStarted = true;
|
|
@@ -41946,6 +42160,7 @@ ${pc.magenta(glyph.thinking)} ${pc.dim(this.thinkingLabel)} `);
|
|
|
41946
42160
|
const summary = humanArgs(tool, displayArgs);
|
|
41947
42161
|
const label = friendlyTool(tool);
|
|
41948
42162
|
const mark = actionMarkFor(tool);
|
|
42163
|
+
const accent = toolAccent(tool);
|
|
41949
42164
|
const deferred = this.verbosity === "quiet";
|
|
41950
42165
|
this.card = {
|
|
41951
42166
|
tool,
|
|
@@ -41964,7 +42179,7 @@ ${pc.dim(glyph.detail)} ${pc.cyan(stepContext)}
|
|
|
41964
42179
|
`);
|
|
41965
42180
|
}
|
|
41966
42181
|
if (!deferred) {
|
|
41967
|
-
this.channel.writeRaw(`${mark} ${label}${summary ? ` ${pc.dim(summary)}` : ""}
|
|
42182
|
+
this.channel.writeRaw(`${mark} ${accent(label)}${summary ? ` ${pc.dim("·")} ${pc.dim(summary)}` : ""}
|
|
41968
42183
|
`);
|
|
41969
42184
|
}
|
|
41970
42185
|
if (!SPINNERLESS_TOOLS.has(tool)) {
|
|
@@ -41981,7 +42196,8 @@ ${pc.dim(glyph.detail)} ${pc.cyan(stepContext)}
|
|
|
41981
42196
|
this.reconBuffer = [];
|
|
41982
42197
|
if (items.length === 1) {
|
|
41983
42198
|
const it = items[0];
|
|
41984
|
-
const
|
|
42199
|
+
const accent = toolAccent(it.tool);
|
|
42200
|
+
const head = `${it.mark} ${accent(it.label)}${it.summary ? ` ${pc.dim("·")} ${pc.dim(it.summary)}` : ""}`;
|
|
41985
42201
|
this.channel.writeRaw(`${head} ${successMark()} ${pc.dim(formatDuration(it.duration))}
|
|
41986
42202
|
`);
|
|
41987
42203
|
return;
|
|
@@ -42018,13 +42234,19 @@ ${pc.dim(glyph.detail)} ${pc.cyan(stepContext)}
|
|
|
42018
42234
|
}
|
|
42019
42235
|
if (deferred) {
|
|
42020
42236
|
if (!error && RECON_TOOLS.has(this.card.tool)) {
|
|
42021
|
-
this.reconBuffer.push({
|
|
42237
|
+
this.reconBuffer.push({
|
|
42238
|
+
tool: this.card.tool,
|
|
42239
|
+
mark: leadMark,
|
|
42240
|
+
label,
|
|
42241
|
+
summary,
|
|
42242
|
+
duration
|
|
42243
|
+
});
|
|
42022
42244
|
this.recordLast(label, summary, error, duration);
|
|
42023
42245
|
this.card = null;
|
|
42024
42246
|
return;
|
|
42025
42247
|
}
|
|
42026
42248
|
this.flushRecon();
|
|
42027
|
-
const head = `${leadMark} ${label}${summary ? ` ${pc.dim(summary)}` : ""}`;
|
|
42249
|
+
const head = `${leadMark} ${toolAccent(this.card.tool)(label)}${summary ? ` ${pc.dim("·")} ${pc.dim(summary)}` : ""}`;
|
|
42028
42250
|
this.channel.writeRaw(`${head} ${tail}
|
|
42029
42251
|
`);
|
|
42030
42252
|
if (error && firstBody) {
|
|
@@ -42049,6 +42271,7 @@ ${pc.dim(glyph.detail)} ${pc.cyan(stepContext)}
|
|
|
42049
42271
|
const firstBody = this.card?.firstBody ?? "";
|
|
42050
42272
|
const status = !error ? "ok" : firstBody.startsWith("⚠") ? "warn" : "error";
|
|
42051
42273
|
recordLastAction({
|
|
42274
|
+
tool: this.card?.tool ?? "",
|
|
42052
42275
|
label,
|
|
42053
42276
|
args: summary,
|
|
42054
42277
|
status,
|
|
@@ -42425,10 +42648,10 @@ class Repl {
|
|
|
42425
42648
|
this.execModule = execModule;
|
|
42426
42649
|
this.slog = new SessionLogger(sessionManager, logger4);
|
|
42427
42650
|
this.bindSessionOutput();
|
|
42428
|
-
this.configDir = configDir ||
|
|
42651
|
+
this.configDir = configDir || join56(homedir18(), ".mma");
|
|
42429
42652
|
this.baseDir = baseDir || process.cwd();
|
|
42430
42653
|
this.noAgentsMd = noAgentsMd === true;
|
|
42431
|
-
this.historyPath = historyPath ??
|
|
42654
|
+
this.historyPath = historyPath ?? join56(homedir18(), ".mma", "repl-history");
|
|
42432
42655
|
this.loadHistory();
|
|
42433
42656
|
const editorCompleter = (line) => {
|
|
42434
42657
|
const [matches, partial] = this.completer.complete(line);
|
|
@@ -42436,6 +42659,10 @@ class Repl {
|
|
|
42436
42659
|
return [matches, partial];
|
|
42437
42660
|
return [[], line];
|
|
42438
42661
|
};
|
|
42662
|
+
const readlineCompleter = (line) => {
|
|
42663
|
+
const [items, partial] = editorCompleter(line);
|
|
42664
|
+
return [items.map((i) => i.value), partial];
|
|
42665
|
+
};
|
|
42439
42666
|
if (process.stdin.isTTY) {
|
|
42440
42667
|
this.rl = new LineEditor({
|
|
42441
42668
|
input: process.stdin,
|
|
@@ -42453,7 +42680,7 @@ class Repl {
|
|
|
42453
42680
|
history: this.history,
|
|
42454
42681
|
historySize: this.maxHistory,
|
|
42455
42682
|
tabSize: 2,
|
|
42456
|
-
completer:
|
|
42683
|
+
completer: readlineCompleter
|
|
42457
42684
|
});
|
|
42458
42685
|
}
|
|
42459
42686
|
this.output = output ?? getDefaultChannel();
|
|
@@ -42508,7 +42735,7 @@ class Repl {
|
|
|
42508
42735
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
42509
42736
|
const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
|
|
42510
42737
|
this.agent.shutdown();
|
|
42511
|
-
const projectConfigPath =
|
|
42738
|
+
const projectConfigPath = join56(this.baseDir, ".mmrc");
|
|
42512
42739
|
const { config: freshConfig } = loadConfig2({
|
|
42513
42740
|
configDir: this.configDir,
|
|
42514
42741
|
projectConfigPath
|
|
@@ -42548,7 +42775,7 @@ class Repl {
|
|
|
42548
42775
|
}
|
|
42549
42776
|
setupCompleter() {
|
|
42550
42777
|
this.completer.reset();
|
|
42551
|
-
const slashCommands =
|
|
42778
|
+
const slashCommands = buildSlashCompletions(this.commands);
|
|
42552
42779
|
this.completer.registerProvider(new SlashCommandProvider(slashCommands));
|
|
42553
42780
|
if (this.sessionManager) {
|
|
42554
42781
|
this.completer.registerProvider(new SessionNameProvider(() => this.sessionManager.list().map((s) => s.name)));
|
|
@@ -42564,6 +42791,7 @@ class Repl {
|
|
|
42564
42791
|
this.completer.registerProvider(new ProviderArgProvider(entryLabels));
|
|
42565
42792
|
}
|
|
42566
42793
|
this.completer.registerProvider(new ModelArgProvider(() => this.modelCache));
|
|
42794
|
+
this.completer.registerProvider(new FilePathProvider(this.baseDir));
|
|
42567
42795
|
this.refreshModelCache();
|
|
42568
42796
|
}
|
|
42569
42797
|
refreshModelCache() {
|
|
@@ -42744,7 +42972,8 @@ ${t("repl.interrupt")}`));
|
|
|
42744
42972
|
return;
|
|
42745
42973
|
}
|
|
42746
42974
|
const mark = last2.status === "error" ? pc.red(glyph.failure) : last2.status === "warn" ? pc.yellow(glyph.warning) : pc.green(glyph.success);
|
|
42747
|
-
const
|
|
42975
|
+
const accent = toolAccent(last2.tool);
|
|
42976
|
+
const head = `${accent(glyph.action)} ${accent(last2.label)}${last2.args ? ` ${pc.dim("·")} ${pc.dim(last2.args)}` : ""} ${mark} ${pc.dim(`${last2.durationMs}ms`)}`;
|
|
42748
42977
|
const lines = [head, ...last2.body.map((l) => ` ${l}`)];
|
|
42749
42978
|
this.output.writeLine(`
|
|
42750
42979
|
${lines.join(`
|
|
@@ -43022,9 +43251,9 @@ ${divider()}`);
|
|
|
43022
43251
|
row(t("repl.agents_label"), pc.red(t("repl.disabled")));
|
|
43023
43252
|
} else {
|
|
43024
43253
|
const agentsMdCandidates = [
|
|
43025
|
-
|
|
43026
|
-
|
|
43027
|
-
|
|
43254
|
+
join56(this.baseDir, "AGENTS.md"),
|
|
43255
|
+
join56(this.baseDir, ".mma", "AGENTS.md"),
|
|
43256
|
+
join56(this.configDir, "AGENTS.md")
|
|
43028
43257
|
];
|
|
43029
43258
|
const foundAgents = agentsMdCandidates.filter((p) => existsSync61(p));
|
|
43030
43259
|
if (foundAgents.length > 0) {
|
|
@@ -43037,7 +43266,7 @@ ${divider()}`);
|
|
|
43037
43266
|
}
|
|
43038
43267
|
const meta = this.sessionManager?.getActiveMeta();
|
|
43039
43268
|
if (meta) {
|
|
43040
|
-
const sessionPath =
|
|
43269
|
+
const sessionPath = join56(this.configDir, "sessions", meta.id);
|
|
43041
43270
|
row(t("repl.session_label"), `${pc.cyan(meta.name)} ${pc.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc.dim(sessionPath)}`);
|
|
43042
43271
|
}
|
|
43043
43272
|
const isTty2 = process.stdout.isTTY === true;
|
|
@@ -43049,9 +43278,9 @@ ${divider()}`);
|
|
|
43049
43278
|
try {
|
|
43050
43279
|
const { existsSync: exists } = await import("fs");
|
|
43051
43280
|
const { join: pathJoin } = await import("path");
|
|
43052
|
-
const { hasDomainFiles:
|
|
43281
|
+
const { hasDomainFiles: hasDomainFiles2 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
43053
43282
|
const legacyPath = pathJoin(this.configDir, "config.json");
|
|
43054
|
-
if (exists(legacyPath) && !
|
|
43283
|
+
if (exists(legacyPath) && !hasDomainFiles2(this.configDir)) {
|
|
43055
43284
|
this.output.writeLine(pc.yellow(` ${t("config.legacy_hint")}`));
|
|
43056
43285
|
this.output.writeLine("");
|
|
43057
43286
|
}
|
|
@@ -43166,51 +43395,7 @@ function printRunResult(result, flush, channel = getDefaultChannel()) {
|
|
|
43166
43395
|
|
|
43167
43396
|
// src/cli/main.ts
|
|
43168
43397
|
init_setup();
|
|
43169
|
-
|
|
43170
|
-
// src/cli/setup-order.ts
|
|
43171
|
-
var SECURITY_BASH_BLOCKLIST = [
|
|
43172
|
-
"rm",
|
|
43173
|
-
"dd",
|
|
43174
|
-
"chmod",
|
|
43175
|
-
"wget",
|
|
43176
|
-
"curl",
|
|
43177
|
-
"scp",
|
|
43178
|
-
"ssh",
|
|
43179
|
-
"nc",
|
|
43180
|
-
"netcat",
|
|
43181
|
-
"sudo",
|
|
43182
|
-
"su",
|
|
43183
|
-
"kill",
|
|
43184
|
-
"pkill",
|
|
43185
|
-
"killall",
|
|
43186
|
-
"shutdown",
|
|
43187
|
-
"reboot"
|
|
43188
|
-
];
|
|
43189
|
-
function applyAnswersToConfig(config, a) {
|
|
43190
|
-
config.provider = {
|
|
43191
|
-
...config.provider,
|
|
43192
|
-
type: a.provider,
|
|
43193
|
-
baseUrl: a.apiBase,
|
|
43194
|
-
apiKey: a.apiKey
|
|
43195
|
-
};
|
|
43196
|
-
config.model = a.model;
|
|
43197
|
-
config.contextWindow = a.contextWindow;
|
|
43198
|
-
config.maxToolIterations = a.maxToolIterations;
|
|
43199
|
-
config.locale = a.locale;
|
|
43200
|
-
if (config.security) {
|
|
43201
|
-
config.security.enabled = true;
|
|
43202
|
-
config.security.bash.enabled = true;
|
|
43203
|
-
config.security.bash.blockDangerousFlags = a.securityFlagsBlock || config.security.bash.blockDangerousFlags;
|
|
43204
|
-
if (a.securityBashBlock) {
|
|
43205
|
-
config.security.bash.blacklist = [
|
|
43206
|
-
...new Set([...config.security.bash.blacklist, ...SECURITY_BASH_BLOCKLIST])
|
|
43207
|
-
];
|
|
43208
|
-
}
|
|
43209
|
-
if (!a.securityPathsDeny)
|
|
43210
|
-
config.security.paths.denied = [];
|
|
43211
|
-
}
|
|
43212
|
-
return config;
|
|
43213
|
-
}
|
|
43398
|
+
init_setup_order();
|
|
43214
43399
|
|
|
43215
43400
|
// src/cli/relaunch.ts
|
|
43216
43401
|
init_output();
|
|
@@ -43270,7 +43455,7 @@ init_config2();
|
|
|
43270
43455
|
init_i18n();
|
|
43271
43456
|
init_colors();
|
|
43272
43457
|
import { existsSync as existsSync62 } from "fs";
|
|
43273
|
-
import { join as
|
|
43458
|
+
import { join as join58, dirname as dirname27 } from "path";
|
|
43274
43459
|
import { homedir as homedir20 } from "os";
|
|
43275
43460
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
43276
43461
|
|
|
@@ -43392,9 +43577,9 @@ init_data_sanitizer();
|
|
|
43392
43577
|
init_i18n();
|
|
43393
43578
|
init_utils();
|
|
43394
43579
|
import { appendFileSync as appendFileSync8, mkdirSync as mkdirSync26 } from "fs";
|
|
43395
|
-
import { join as
|
|
43580
|
+
import { join as join57 } from "path";
|
|
43396
43581
|
import { homedir as homedir19 } from "os";
|
|
43397
|
-
var CRASH_LOG_DIR =
|
|
43582
|
+
var CRASH_LOG_DIR = join57(homedir19(), ".mma", "logs");
|
|
43398
43583
|
var CRASH_LOG_FILE = "crash.jsonl";
|
|
43399
43584
|
function formatCrashEntry(type2, err) {
|
|
43400
43585
|
const message = errMsg(err);
|
|
@@ -43410,7 +43595,7 @@ function formatCrashEntry(type2, err) {
|
|
|
43410
43595
|
function writeCrashEntry(dir, entry) {
|
|
43411
43596
|
try {
|
|
43412
43597
|
mkdirSync26(dir, { recursive: true });
|
|
43413
|
-
appendFileSync8(
|
|
43598
|
+
appendFileSync8(join57(dir, CRASH_LOG_FILE), JSON.stringify(entry) + `
|
|
43414
43599
|
`, "utf-8");
|
|
43415
43600
|
} catch {}
|
|
43416
43601
|
}
|
|
@@ -43538,6 +43723,9 @@ async function main() {
|
|
|
43538
43723
|
}
|
|
43539
43724
|
const jsonSink = jsonOpt ? new JsonOutputSink(defaultOutputBus) : undefined;
|
|
43540
43725
|
const prompt = program2.args.join(" ");
|
|
43726
|
+
const mmaDir = process.env.MMA_CONFIG_DIR || join58(homedir20(), ".mma");
|
|
43727
|
+
const { hasDomainFiles: hasDomainFiles2 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
43728
|
+
const virgin = !existsSync62(join58(mmaDir, "config.json")) && !hasDomainFiles2(mmaDir);
|
|
43541
43729
|
const { agent, config, baseDir, legacyDetected, contextProbe } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete, reasoningLevel, contextLog);
|
|
43542
43730
|
if (verboseOpt)
|
|
43543
43731
|
config.ui.verbosity = "verbose";
|
|
@@ -43545,6 +43733,9 @@ async function main() {
|
|
|
43545
43733
|
if (legacyDetected) {
|
|
43546
43734
|
getDefaultChannel().writeLine(pc.yellow(` ${t("config.legacy_hint")}`), "stderr");
|
|
43547
43735
|
}
|
|
43736
|
+
if (virgin && !jsonOpt) {
|
|
43737
|
+
getDefaultChannel().writeLine(pc.yellow(` ${t("cli.first_run_oneshot")}`), "stderr");
|
|
43738
|
+
}
|
|
43548
43739
|
if (contextProbe && !jsonOpt) {
|
|
43549
43740
|
try {
|
|
43550
43741
|
const probe = await contextProbe;
|
|
@@ -43620,16 +43811,16 @@ async function main() {
|
|
|
43620
43811
|
await updater?.waitForIdle();
|
|
43621
43812
|
process.exit(exitCode);
|
|
43622
43813
|
} else {
|
|
43623
|
-
const mmaDir = process.env.MMA_CONFIG_DIR ||
|
|
43624
|
-
const legacyConfigPath =
|
|
43814
|
+
const mmaDir = process.env.MMA_CONFIG_DIR || join58(homedir20(), ".mma");
|
|
43815
|
+
const legacyConfigPath = join58(mmaDir, "config.json");
|
|
43625
43816
|
let hasAnyConfig = existsSync62(legacyConfigPath);
|
|
43626
43817
|
if (!hasAnyConfig) {
|
|
43627
43818
|
try {
|
|
43628
|
-
const { hasDomainFiles:
|
|
43629
|
-
hasAnyConfig =
|
|
43819
|
+
const { hasDomainFiles: hasDomainFiles2 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
|
|
43820
|
+
hasAnyConfig = hasDomainFiles2(mmaDir);
|
|
43630
43821
|
} catch {}
|
|
43631
43822
|
}
|
|
43632
|
-
const projectConfigPath = projectDir ?
|
|
43823
|
+
const projectConfigPath = projectDir ? join58(projectDir, ".mmrc") : join58(process.cwd(), ".mmrc");
|
|
43633
43824
|
if (!hasAnyConfig && !exitOnComplete && process.env.MMA_POST_SETUP !== "1") {
|
|
43634
43825
|
getDefaultChannel().writeLine(`
|
|
43635
43826
|
` + t("cli.first_run") + `
|