micro-models-agent 0.39.0 → 0.40.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/bin/mma.mjs +41 -41
- package/dist/cli/commands.js +116 -3
- package/dist/cli/main.js +35 -8
- package/dist/cli/repl-commands.js +633 -0
- package/dist/cli/repl.js +110 -611
- package/dist/cli/setup.js +32 -12
- package/dist/config/config.js +46 -30
- package/dist/config/defaults.js +10 -1
- package/dist/config/security.js +15 -8
- package/dist/core/agent-moe.js +24 -12
- package/dist/core/agent.js +281 -47
- package/dist/core/bootstrap.js +52 -36
- package/dist/core/session-logger.js +35 -2
- package/dist/core/workspace.js +76 -0
- package/dist/i18n/en.json +79 -15
- package/dist/i18n/index.js +12 -9
- package/dist/i18n/ru.json +79 -15
- package/dist/index.js +13 -13
- package/dist/llm/openai-compat.js +39 -10
- package/dist/logger/app-logger.js +83 -16
- package/dist/logger/file-log.js +151 -0
- package/dist/main.js +537 -284
- package/dist/modules/browser/bridge-server.mjs +113 -105
- package/dist/modules/browser/session.js +108 -60
- package/dist/modules/certification/cli.js +176 -0
- package/dist/modules/certification/fact-checker.js +84 -0
- package/dist/modules/certification/loader.js +111 -0
- package/dist/modules/certification/manifest.js +50 -0
- package/dist/modules/certification/runner.js +162 -0
- package/dist/modules/certification/scenarios.js +124 -0
- package/dist/modules/certification/types.js +1 -0
- package/dist/modules/context/manager.js +119 -10
- package/dist/modules/execution/auditor.js +33 -39
- package/dist/modules/execution/index.js +8 -6
- package/dist/modules/execution/module.js +474 -32
- package/dist/modules/execution/moe-executor.js +97 -40
- package/dist/modules/execution/plan-coverage.js +68 -0
- package/dist/modules/execution/plan-persister.js +46 -0
- package/dist/modules/execution/plan-store.js +159 -0
- package/dist/modules/execution/planner.js +63 -13
- package/dist/modules/execution/stuck-detector.js +252 -39
- package/dist/modules/execution/tracker.js +21 -7
- package/dist/modules/execution/verifier.js +46 -17
- package/dist/modules/hallucination/confidence.js +7 -2
- package/dist/modules/hallucination/consistency.js +8 -42
- package/dist/modules/hallucination/detector.js +26 -21
- package/dist/modules/hallucination/factual.js +170 -150
- package/dist/modules/hallucination/index.js +5 -4
- package/dist/modules/hallucination/js-identifiers.js +72 -0
- package/dist/modules/hallucination/llm-judge.js +103 -0
- package/dist/modules/index.js +5 -5
- package/dist/modules/lsp/client.js +235 -0
- package/dist/modules/lsp/config.js +81 -0
- package/dist/modules/lsp/index.js +3 -0
- package/dist/modules/lsp/module.js +68 -0
- package/dist/modules/lsp/types.js +1 -0
- package/dist/modules/mcp/client.js +8 -2
- package/dist/modules/memory/store.js +4 -0
- package/dist/modules/plugins/builtin/lint-on-write.js +143 -38
- package/dist/modules/processes/index.js +1 -2
- package/dist/modules/processes/registry.js +125 -35
- package/dist/modules/processes/runner.js +9 -110
- package/dist/modules/security/audit-log.js +30 -10
- package/dist/modules/security/command-validator.js +42 -16
- package/dist/modules/security/content-scanner.js +9 -8
- package/dist/modules/security/network-validator.js +2 -2
- package/dist/modules/security/path-validator.js +64 -10
- package/dist/modules/security/security-policies.js +221 -67
- package/dist/modules/security/session-encryption.js +42 -25
- package/dist/modules/session/manager.js +15 -10
- package/dist/modules/session/store.js +62 -8
- package/dist/modules/skills/index.js +2 -3
- package/dist/modules/skills/module.js +10 -23
- package/dist/tools/bash.js +287 -90
- package/dist/tools/create-dir.js +0 -1
- package/dist/tools/delete-file.js +0 -1
- package/dist/tools/edit-file.js +10 -8
- package/dist/tools/executor.js +57 -7
- package/dist/tools/grep-tool.js +51 -29
- package/dist/tools/index.js +55 -40
- package/dist/tools/load-skill.js +14 -18
- package/dist/tools/move-file.js +3 -2
- package/dist/tools/pipeline-run.js +1 -1
- package/dist/tools/read-file.js +15 -5
- package/dist/tools/search-history.js +42 -22
- package/dist/tools/subagent.js +21 -12
- package/dist/tools/web-browse.js +54 -25
- package/dist/tools/web-fetch.js +60 -34
- package/dist/tools/web-search.js +39 -20
- package/dist/tools/write-file.js +13 -10
- package/dist/ui/diff.js +9 -16
- package/dist/ui/renderer.js +69 -6
- package/package.json +48 -45
- package/dist/modules/context/history.js +0 -15
- package/dist/modules/processes/detect.js +0 -34
- package/dist/modules/skills/matcher.js +0 -27
package/dist/main.js
CHANGED
|
@@ -2064,12 +2064,7 @@ var init_security = __esm(() => {
|
|
|
2064
2064
|
auditNotifier: {
|
|
2065
2065
|
enabled: false,
|
|
2066
2066
|
minSeverity: "medium",
|
|
2067
|
-
eventTypes: [
|
|
2068
|
-
"security_block",
|
|
2069
|
-
"bash_command",
|
|
2070
|
-
"file_operation",
|
|
2071
|
-
"network_request"
|
|
2072
|
-
],
|
|
2067
|
+
eventTypes: ["security_block", "bash_command", "file_operation", "network_request"],
|
|
2073
2068
|
maxRetries: 3,
|
|
2074
2069
|
webhookTimeout: 5000
|
|
2075
2070
|
}
|
|
@@ -2151,8 +2146,12 @@ var init_config = __esm(() => {
|
|
|
2151
2146
|
LANGUAGE_MAP = {
|
|
2152
2147
|
ts: "typescript",
|
|
2153
2148
|
tsx: "typescript",
|
|
2149
|
+
mts: "typescript",
|
|
2150
|
+
cts: "typescript",
|
|
2154
2151
|
js: "javascript",
|
|
2155
2152
|
jsx: "javascript",
|
|
2153
|
+
mjs: "javascript",
|
|
2154
|
+
cjs: "javascript",
|
|
2156
2155
|
py: "python",
|
|
2157
2156
|
rs: "rust",
|
|
2158
2157
|
go: "go",
|
|
@@ -2183,13 +2182,21 @@ var init_defaults = __esm(() => {
|
|
|
2183
2182
|
moe: {
|
|
2184
2183
|
enabled: false
|
|
2185
2184
|
},
|
|
2185
|
+
tools: {
|
|
2186
|
+
defaultTags: ["file", "code"],
|
|
2187
|
+
enableOnDemand: true
|
|
2188
|
+
},
|
|
2186
2189
|
experts: {
|
|
2187
2190
|
code: {
|
|
2188
2191
|
model: "qwen/qwen3.5-9b",
|
|
2189
2192
|
tool_tags: ["file", "code", "shell"],
|
|
2190
2193
|
max_attempts: 3
|
|
2191
2194
|
},
|
|
2192
|
-
research: {
|
|
2195
|
+
research: {
|
|
2196
|
+
model: "qwen/qwen3.5-9b",
|
|
2197
|
+
tool_tags: ["research"],
|
|
2198
|
+
max_attempts: 3
|
|
2199
|
+
},
|
|
2193
2200
|
browser: {
|
|
2194
2201
|
model: "qwen/qwen3.5-9b",
|
|
2195
2202
|
tool_tags: ["browser", "vision"],
|
|
@@ -2509,6 +2516,7 @@ Command: {command}`,
|
|
|
2509
2516
|
"lsp.check_notfound": "Path not found: {path}",
|
|
2510
2517
|
"lsp.check_unsupported": "No LSP server configured for: {path}",
|
|
2511
2518
|
"lsp.check_clean": "No errors or warnings detected ({count} file(s) checked).",
|
|
2519
|
+
"lsp.startup_header": "[Existing project errors (checked at session start) — fix these before continuing]:",
|
|
2512
2520
|
"cli.description": "Micro Models Agent — AI coding agent for small models",
|
|
2513
2521
|
"cli.init": "Run interactive setup wizard",
|
|
2514
2522
|
"cli.config_saved": "Configuration saved to ~/.mma/config.json",
|
|
@@ -2643,6 +2651,8 @@ Available commands:`,
|
|
|
2643
2651
|
"repl.reasoning_usage": "Usage: /reasoning",
|
|
2644
2652
|
"repl.status": "Show agent status",
|
|
2645
2653
|
"repl.status_usage": "Usage: /status",
|
|
2654
|
+
"repl.plugins": "List loaded plugins",
|
|
2655
|
+
"repl.plugins_usage": "Usage: /plugins [--all]",
|
|
2646
2656
|
"repl.sessions": "List all sessions (* active)",
|
|
2647
2657
|
"repl.sessions_usage": "Usage: /sessions",
|
|
2648
2658
|
"repl.new": "Create a new session",
|
|
@@ -2899,7 +2909,13 @@ Use this knowledge to answer the user's question.`,
|
|
|
2899
2909
|
"updater.available": "[updater] Update available: {current} → {latest}. Run `npm install -g micro-models-agent` to upgrade.",
|
|
2900
2910
|
"updater.installing": "[updater] Installing {latest} globally (current: {current})…",
|
|
2901
2911
|
"updater.installed": "[updater] Installed {latest}. Restart MMA to use it (was {current}).",
|
|
2902
|
-
"updater.install_failed": "[updater] Failed to install {latest}: {error}. Update manually with `npm install -g micro-models-agent`."
|
|
2912
|
+
"updater.install_failed": "[updater] Failed to install {latest}: {error}. Update manually with `npm install -g micro-models-agent`.",
|
|
2913
|
+
"tools.enable_no_tags": 'enable_tools requires at least one tag in the "tags" array.',
|
|
2914
|
+
"tools.enable_no_executor": "Tool executor is not available — cannot enumerate enabled tools.",
|
|
2915
|
+
"tools.enable_already_active": "Tool tags already active: {tags}.",
|
|
2916
|
+
"tools.enable_added": "Enabled tool tags: {tags}. Available tools now: {tools}",
|
|
2917
|
+
"tools.hidden_header": "Additional tools (enable on demand via enable_tools or route to subagent tool_tags):",
|
|
2918
|
+
"tool.friendly.enable_tools": "Enable tools"
|
|
2903
2919
|
};
|
|
2904
2920
|
});
|
|
2905
2921
|
|
|
@@ -3126,6 +3142,7 @@ var init_ru = __esm(() => {
|
|
|
3126
3142
|
"lsp.check_notfound": "Путь не найден: {path}",
|
|
3127
3143
|
"lsp.check_unsupported": "Для файла не настроен LSP-сервер: {path}",
|
|
3128
3144
|
"lsp.check_clean": "Ошибок и предупреждений не обнаружено (проверено файлов: {count}).",
|
|
3145
|
+
"lsp.startup_header": "[Существующие ошибки проекта (проверено при старте сессии) — исправьте их перед продолжением]:",
|
|
3129
3146
|
"cli.description": "Micro Models Agent — ИИ-агент для кодинга на малых моделях",
|
|
3130
3147
|
"cli.init": "Запустить мастер настройки",
|
|
3131
3148
|
"cli.config_saved": "Конфигурация сохранена в ~/.mma/config.json",
|
|
@@ -3256,6 +3273,8 @@ var init_ru = __esm(() => {
|
|
|
3256
3273
|
"repl.reasoning_usage": "Использование: /reasoning",
|
|
3257
3274
|
"repl.status": "Показать статус агента",
|
|
3258
3275
|
"repl.status_usage": "Использование: /status",
|
|
3276
|
+
"repl.plugins": "Список загруженных плагинов",
|
|
3277
|
+
"repl.plugins_usage": "Использование: /plugins [--all]",
|
|
3259
3278
|
"repl.sessions": "Список всех сессий (* активная)",
|
|
3260
3279
|
"repl.sessions_usage": "Использование: /sessions",
|
|
3261
3280
|
"repl.new": "Создать новую сессию",
|
|
@@ -3518,7 +3537,13 @@ var init_ru = __esm(() => {
|
|
|
3518
3537
|
"updater.available": "[updater] Доступно обновление: {current} → {latest}. Выполните `npm install -g micro-models-agent` для обновления.",
|
|
3519
3538
|
"updater.installing": "[updater] Установка {latest} глобально (текущая: {current})…",
|
|
3520
3539
|
"updater.installed": "[updater] Установлена {latest}. Перезапустите MMA для применения (была {current}).",
|
|
3521
|
-
"updater.install_failed": "[updater] Не удалось установить {latest}: {error}. Обновите вручную: `npm install -g micro-models-agent`."
|
|
3540
|
+
"updater.install_failed": "[updater] Не удалось установить {latest}: {error}. Обновите вручную: `npm install -g micro-models-agent`.",
|
|
3541
|
+
"tools.enable_no_tags": 'enable_tools требует хотя бы один тег в массиве "tags".',
|
|
3542
|
+
"tools.enable_no_executor": "Исполнитель тулов недоступен — невозможно перечислить включённые тулы.",
|
|
3543
|
+
"tools.enable_already_active": "Теги тулов уже активны: {tags}.",
|
|
3544
|
+
"tools.enable_added": "Включены теги тулов: {tags}. Теперь доступны тулы: {tools}",
|
|
3545
|
+
"tools.hidden_header": "Дополнительные тулы (включите по требованию через enable_tools или маршрутизируйте через subagent tool_tags):",
|
|
3546
|
+
"tool.friendly.enable_tools": "Включить тулы"
|
|
3522
3547
|
};
|
|
3523
3548
|
});
|
|
3524
3549
|
|
|
@@ -3868,13 +3893,7 @@ __export(exports_config, {
|
|
|
3868
3893
|
saveConfig: () => saveConfig,
|
|
3869
3894
|
loadConfig: () => loadConfig
|
|
3870
3895
|
});
|
|
3871
|
-
import {
|
|
3872
|
-
existsSync as existsSync4,
|
|
3873
|
-
readFileSync as readFileSync3,
|
|
3874
|
-
unlinkSync,
|
|
3875
|
-
writeFileSync as writeFileSync3,
|
|
3876
|
-
mkdirSync as mkdirSync2
|
|
3877
|
-
} from "fs";
|
|
3896
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, unlinkSync, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
3878
3897
|
import { join as join4, dirname } from "path";
|
|
3879
3898
|
function restoreDangerousPatterns(patterns, defaults) {
|
|
3880
3899
|
const fallback = Array.isArray(defaults) ? defaults : [];
|
|
@@ -4011,6 +4030,12 @@ function loadConfig(options) {
|
|
|
4011
4030
|
}
|
|
4012
4031
|
function validateConfig(config, allToolTags) {
|
|
4013
4032
|
const errors = validateExpertConfig(config, allToolTags);
|
|
4033
|
+
const knownTags = new Set(allToolTags);
|
|
4034
|
+
for (const tag of config.tools?.defaultTags ?? []) {
|
|
4035
|
+
if (!knownTags.has(tag)) {
|
|
4036
|
+
errors.push(`tools.defaultTags references unknown tag "${tag}". Known tags: ${Array.from(knownTags).join(", ")}`);
|
|
4037
|
+
}
|
|
4038
|
+
}
|
|
4014
4039
|
if (errors.length > 0) {
|
|
4015
4040
|
throw new Error(`Config validation failed:
|
|
4016
4041
|
${errors.join(`
|
|
@@ -5409,8 +5434,10 @@ class ToolRegistry {
|
|
|
5409
5434
|
});
|
|
5410
5435
|
}
|
|
5411
5436
|
getAllForLLM(tags) {
|
|
5412
|
-
const
|
|
5413
|
-
|
|
5437
|
+
const all = this.getAll();
|
|
5438
|
+
const tagSet = new Set(tags ?? []);
|
|
5439
|
+
const selected = tagSet.size === 0 ? all : all.filter((t2) => t2.alwaysOn || t2.tags && t2.tags.some((tag) => tagSet.has(tag)));
|
|
5440
|
+
return selected.map((t2) => ({
|
|
5414
5441
|
name: t2.name,
|
|
5415
5442
|
description: t2.description,
|
|
5416
5443
|
parameters: t2.parameters,
|
|
@@ -7882,7 +7909,10 @@ var init_process_log = __esm(() => {
|
|
|
7882
7909
|
type: "object",
|
|
7883
7910
|
properties: {
|
|
7884
7911
|
id: { type: "string", description: "Process id from bash output or process_list" },
|
|
7885
|
-
tail: {
|
|
7912
|
+
tail: {
|
|
7913
|
+
type: "number",
|
|
7914
|
+
description: `Number of trailing lines to show (default: ${DEFAULT_TAIL}, max 300)`
|
|
7915
|
+
}
|
|
7886
7916
|
},
|
|
7887
7917
|
required: ["id"]
|
|
7888
7918
|
},
|
|
@@ -9333,6 +9363,8 @@ function filterToolsByTags(tools, toolTags) {
|
|
|
9333
9363
|
return tools;
|
|
9334
9364
|
const tagSet = new Set(toolTags);
|
|
9335
9365
|
return tools.filter((t2) => {
|
|
9366
|
+
if (t2.alwaysOn)
|
|
9367
|
+
return true;
|
|
9336
9368
|
if (!t2.tags || t2.tags.length === 0)
|
|
9337
9369
|
return false;
|
|
9338
9370
|
return t2.tags.some((tag) => tagSet.has(tag));
|
|
@@ -10142,7 +10174,10 @@ class StepVerifier {
|
|
|
10142
10174
|
await this.runAsync(`bun run ${scriptName}`, this.baseDir, 60000);
|
|
10143
10175
|
return { passed: true, message: t("verify.script_passed", { script: scriptName }) };
|
|
10144
10176
|
} catch (e) {
|
|
10145
|
-
return {
|
|
10177
|
+
return {
|
|
10178
|
+
passed: false,
|
|
10179
|
+
message: t("verify.script_failed", { script: scriptName, message: e.message })
|
|
10180
|
+
};
|
|
10146
10181
|
}
|
|
10147
10182
|
}
|
|
10148
10183
|
async runTypeCheck() {
|
|
@@ -10159,10 +10194,7 @@ class StepVerifier {
|
|
|
10159
10194
|
}
|
|
10160
10195
|
}
|
|
10161
10196
|
async runTypeCheckForFile(filePath) {
|
|
10162
|
-
const projectRoot = findProjectRoot(filePath, this.baseDir, [
|
|
10163
|
-
"tsconfig.json",
|
|
10164
|
-
"package.json"
|
|
10165
|
-
]);
|
|
10197
|
+
const projectRoot = findProjectRoot(filePath, this.baseDir, ["tsconfig.json", "package.json"]);
|
|
10166
10198
|
const tsconfigPath = join11(projectRoot, "tsconfig.json");
|
|
10167
10199
|
if (!existsSync20(tsconfigPath)) {
|
|
10168
10200
|
return { passed: true, message: "No tsconfig.json found — skipping type check" };
|
|
@@ -10244,7 +10276,7 @@ class StepVerifier {
|
|
|
10244
10276
|
}
|
|
10245
10277
|
async validateSyntax(filePath) {
|
|
10246
10278
|
const ext = extname2(filePath);
|
|
10247
|
-
if (ext === ".ts" || ext === ".tsx") {
|
|
10279
|
+
if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
|
|
10248
10280
|
try {
|
|
10249
10281
|
await this.runAsync(`npx tsc --noEmit --skipLibCheck ${filePath}`, this.baseDir, 1e4);
|
|
10250
10282
|
return true;
|
|
@@ -10259,7 +10291,7 @@ class StepVerifier {
|
|
|
10259
10291
|
return true;
|
|
10260
10292
|
}
|
|
10261
10293
|
}
|
|
10262
|
-
if (ext === ".js" || ext === ".jsx") {
|
|
10294
|
+
if (ext === ".js" || ext === ".jsx" || ext === ".cjs" || ext === ".mjs") {
|
|
10263
10295
|
try {
|
|
10264
10296
|
await this.runAsync(`node --check ${filePath}`, this.baseDir, 5000);
|
|
10265
10297
|
return true;
|
|
@@ -10366,15 +10398,7 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
|
|
|
10366
10398
|
onMeta?.(`✅ Execution complete: ${planResults.results.filter((r) => r.success).length}/${planResults.results.length} succeeded
|
|
10367
10399
|
`);
|
|
10368
10400
|
const verifier = new StepVerifier(baseDir);
|
|
10369
|
-
const knownTags = [
|
|
10370
|
-
"file",
|
|
10371
|
-
"code",
|
|
10372
|
-
"shell",
|
|
10373
|
-
"research",
|
|
10374
|
-
"browser",
|
|
10375
|
-
"vision",
|
|
10376
|
-
"core"
|
|
10377
|
-
];
|
|
10401
|
+
const knownTags = ["file", "code", "shell", "research", "browser", "vision", "core"];
|
|
10378
10402
|
const verification = await verifier.verifyMoEManifest(plan, config, knownTags);
|
|
10379
10403
|
onPhase?.("thinking");
|
|
10380
10404
|
let verifyResult;
|
|
@@ -10654,13 +10678,17 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
10654
10678
|
let suppressRepetitionRetry = false;
|
|
10655
10679
|
let repeatedToolCount = 0;
|
|
10656
10680
|
const MAX_REPEATED_TOOL_CALLS = 2;
|
|
10657
|
-
|
|
10658
|
-
|
|
10659
|
-
|
|
10681
|
+
let allToolsForBudget = toolExecutor.getToolDefinitions(this.deps.toolTags);
|
|
10682
|
+
let boundedToolNames = new Set(allToolsForBudget.filter((t2) => t2.boundedOutput).map((t2) => t2.name));
|
|
10683
|
+
let toolTokenEstimate = allToolsForBudget.reduce((sum, t2) => sum + Math.ceil((t2.description.length + JSON.stringify(t2.parameters).length) / 4), 0);
|
|
10660
10684
|
contextManager.setToolTokens(toolTokenEstimate);
|
|
10661
10685
|
while (iteration < config.maxToolIterations && !this.shutdownRequested) {
|
|
10662
10686
|
iteration++;
|
|
10663
10687
|
contextManager.noteIteration();
|
|
10688
|
+
allToolsForBudget = toolExecutor.getToolDefinitions(this.deps.toolTags);
|
|
10689
|
+
boundedToolNames = new Set(allToolsForBudget.filter((t2) => t2.boundedOutput).map((t2) => t2.name));
|
|
10690
|
+
toolTokenEstimate = allToolsForBudget.reduce((sum, t2) => sum + Math.ceil((t2.description.length + JSON.stringify(t2.parameters).length) / 4), 0);
|
|
10691
|
+
contextManager.setToolTokens(toolTokenEstimate);
|
|
10664
10692
|
pluginManager.runOnBeforeThink({
|
|
10665
10693
|
iteration,
|
|
10666
10694
|
logger,
|
|
@@ -11248,9 +11276,7 @@ class FactExtractor {
|
|
|
11248
11276
|
new RegExp(`Deleted ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi"),
|
|
11249
11277
|
new RegExp(`(?:Удалён|Файл удалён):? ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi")
|
|
11250
11278
|
];
|
|
11251
|
-
const readPatterns = [
|
|
11252
|
-
new RegExp(`── (${DRIVE}[\\w./\\\\-]+\\.[a-z]+) \\(`, "gi")
|
|
11253
|
-
];
|
|
11279
|
+
const readPatterns = [new RegExp(`── (${DRIVE}[\\w./\\\\-]+\\.[a-z]+) \\(`, "gi")];
|
|
11254
11280
|
const newFiles = [];
|
|
11255
11281
|
const newDeleted = [];
|
|
11256
11282
|
const newDecisions = [];
|
|
@@ -11613,11 +11639,7 @@ ${lines.join(`
|
|
|
11613
11639
|
const text = getMessageText(m.content);
|
|
11614
11640
|
return !text.startsWith("<system-summary>");
|
|
11615
11641
|
});
|
|
11616
|
-
this.messages = [
|
|
11617
|
-
...firstSystem ? [firstSystem] : [],
|
|
11618
|
-
summary,
|
|
11619
|
-
...freshRecent
|
|
11620
|
-
];
|
|
11642
|
+
this.messages = [...firstSystem ? [firstSystem] : [], summary, ...freshRecent];
|
|
11621
11643
|
this.iterationsSinceCompaction = 0;
|
|
11622
11644
|
if (this.onCompact) {
|
|
11623
11645
|
this.onCompact(summary);
|
|
@@ -12311,7 +12333,11 @@ class Updater {
|
|
|
12311
12333
|
signal: AbortSignal.timeout(5000)
|
|
12312
12334
|
});
|
|
12313
12335
|
if (!response.ok) {
|
|
12314
|
-
return {
|
|
12336
|
+
return {
|
|
12337
|
+
updateAvailable: false,
|
|
12338
|
+
current: this.currentVersion,
|
|
12339
|
+
error: `HTTP ${response.status}`
|
|
12340
|
+
};
|
|
12315
12341
|
}
|
|
12316
12342
|
const data = await response.json();
|
|
12317
12343
|
const latest = data["dist-tags"]?.latest;
|
|
@@ -12635,7 +12661,7 @@ var init_subagent = __esm(() => {
|
|
|
12635
12661
|
};
|
|
12636
12662
|
}
|
|
12637
12663
|
if (toolTags && toolTags.length > 0) {
|
|
12638
|
-
const matched = ctx.toolExecutor.
|
|
12664
|
+
const matched = ctx.toolExecutor.getRegistry().getByTags(toolTags);
|
|
12639
12665
|
if (matched.length === 0) {
|
|
12640
12666
|
return {
|
|
12641
12667
|
success: false,
|
|
@@ -12984,15 +13010,7 @@ function isUrlAllowed(url, securityConfig) {
|
|
|
12984
13010
|
function sanitizeUrl(url) {
|
|
12985
13011
|
try {
|
|
12986
13012
|
const urlObj = new URL(url);
|
|
12987
|
-
const sensitiveKeys = [
|
|
12988
|
-
"api_key",
|
|
12989
|
-
"token",
|
|
12990
|
-
"password",
|
|
12991
|
-
"secret",
|
|
12992
|
-
"access_token",
|
|
12993
|
-
"auth",
|
|
12994
|
-
"key"
|
|
12995
|
-
];
|
|
13013
|
+
const sensitiveKeys = ["api_key", "token", "password", "secret", "access_token", "auth", "key"];
|
|
12996
13014
|
const sanitizedParams = new URLSearchParams(urlObj.search);
|
|
12997
13015
|
for (const key of sensitiveKeys) {
|
|
12998
13016
|
if (sanitizedParams.has(key)) {
|
|
@@ -14567,8 +14585,11 @@ var init_recall = __esm(() => {
|
|
|
14567
14585
|
if (results2.length === 0) {
|
|
14568
14586
|
return { success: true, output: t("tool.recall.empty", { query }) };
|
|
14569
14587
|
}
|
|
14570
|
-
return {
|
|
14571
|
-
|
|
14588
|
+
return {
|
|
14589
|
+
success: true,
|
|
14590
|
+
output: t("tool.recall.search_results", { category, results: results2.join(`
|
|
14591
|
+
`) })
|
|
14592
|
+
};
|
|
14572
14593
|
}
|
|
14573
14594
|
const results = store.search(query);
|
|
14574
14595
|
if (results.length === 0) {
|
|
@@ -14576,7 +14597,10 @@ var init_recall = __esm(() => {
|
|
|
14576
14597
|
}
|
|
14577
14598
|
const formatted = results.map((r) => `[${r.file}] ${r.match}`).join(`
|
|
14578
14599
|
`);
|
|
14579
|
-
return {
|
|
14600
|
+
return {
|
|
14601
|
+
success: true,
|
|
14602
|
+
output: t("tool.recall.search_results", { category: "all", results: formatted })
|
|
14603
|
+
};
|
|
14580
14604
|
} catch (err) {
|
|
14581
14605
|
return { success: true, output: t("tool.memory_error", { error: String(err) }) };
|
|
14582
14606
|
}
|
|
@@ -14998,13 +15022,7 @@ function extractInteractiveElements(html, maxElements = 30) {
|
|
|
14998
15022
|
if (tag === "input" && attrs["type"] === "hidden")
|
|
14999
15023
|
continue;
|
|
15000
15024
|
const role = attrs["role"] || inferRole(tag, attrs["type"]);
|
|
15001
|
-
const isInteractive = [
|
|
15002
|
-
"a",
|
|
15003
|
-
"button",
|
|
15004
|
-
"input",
|
|
15005
|
-
"textarea",
|
|
15006
|
-
"select"
|
|
15007
|
-
].includes(tag) || attrs["role"] !== undefined;
|
|
15025
|
+
const isInteractive = ["a", "button", "input", "textarea", "select"].includes(tag) || attrs["role"] !== undefined;
|
|
15008
15026
|
if (!isInteractive)
|
|
15009
15027
|
continue;
|
|
15010
15028
|
if (tag === "a" && !attrs["href"])
|
|
@@ -15577,7 +15595,18 @@ function createBrowserTool() {
|
|
|
15577
15595
|
properties: {
|
|
15578
15596
|
action: {
|
|
15579
15597
|
type: "string",
|
|
15580
|
-
enum: [
|
|
15598
|
+
enum: [
|
|
15599
|
+
"open",
|
|
15600
|
+
"click",
|
|
15601
|
+
"type",
|
|
15602
|
+
"scroll",
|
|
15603
|
+
"back",
|
|
15604
|
+
"forward",
|
|
15605
|
+
"screenshot",
|
|
15606
|
+
"snapshot",
|
|
15607
|
+
"close",
|
|
15608
|
+
"wait"
|
|
15609
|
+
],
|
|
15581
15610
|
description: "Browser action to perform"
|
|
15582
15611
|
},
|
|
15583
15612
|
url: {
|
|
@@ -15670,7 +15699,9 @@ async function readClipboardFallback() {
|
|
|
15670
15699
|
const tmpPath = join22(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
15671
15700
|
try {
|
|
15672
15701
|
if (platform5() === "linux") {
|
|
15673
|
-
execSync(`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`, {
|
|
15702
|
+
execSync(`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`, {
|
|
15703
|
+
timeout: 5000
|
|
15704
|
+
});
|
|
15674
15705
|
} else {
|
|
15675
15706
|
return null;
|
|
15676
15707
|
}
|
|
@@ -15833,8 +15864,63 @@ var init_attach_image = __esm(() => {
|
|
|
15833
15864
|
};
|
|
15834
15865
|
});
|
|
15835
15866
|
|
|
15867
|
+
// src/tools/enable-tools.ts
|
|
15868
|
+
var enableToolsTool;
|
|
15869
|
+
var init_enable_tools = __esm(() => {
|
|
15870
|
+
init_i18n();
|
|
15871
|
+
enableToolsTool = {
|
|
15872
|
+
name: "enable_tools",
|
|
15873
|
+
description: "Enable hidden tool categories for the current session. Only the essential tools (file/code/shell) are active by default. Call this with the tags you need and they become available from the next turn. Available tags: file, code, shell, research, browser, vision, image, memory, core. Returns the newly available tools. To run a task in a separate context instead, use subagent with tool_tags.",
|
|
15874
|
+
alwaysOn: true,
|
|
15875
|
+
parameters: {
|
|
15876
|
+
type: "object",
|
|
15877
|
+
properties: {
|
|
15878
|
+
tags: {
|
|
15879
|
+
type: "array",
|
|
15880
|
+
items: { type: "string" },
|
|
15881
|
+
description: 'Tool tags to enable (e.g. ["research"] for web_search/web_fetch, ["browser"] for the browser, ["memory"] for remember/recall, ["shell"] for process management).'
|
|
15882
|
+
}
|
|
15883
|
+
},
|
|
15884
|
+
required: ["tags"]
|
|
15885
|
+
},
|
|
15886
|
+
handler: async (ctx, args) => {
|
|
15887
|
+
const requested = Array.isArray(args.tags) ? args.tags.map(String).filter(Boolean) : [];
|
|
15888
|
+
if (requested.length === 0) {
|
|
15889
|
+
return { success: false, output: t("tools.enable_no_tags") };
|
|
15890
|
+
}
|
|
15891
|
+
const active = ctx.activeToolTags ?? [];
|
|
15892
|
+
const added = [];
|
|
15893
|
+
for (const tag of requested) {
|
|
15894
|
+
if (!active.includes(tag)) {
|
|
15895
|
+
active.push(tag);
|
|
15896
|
+
added.push(tag);
|
|
15897
|
+
}
|
|
15898
|
+
}
|
|
15899
|
+
if (!ctx.toolExecutor) {
|
|
15900
|
+
return { success: false, output: t("tools.enable_no_executor") };
|
|
15901
|
+
}
|
|
15902
|
+
const nowVisible = ctx.toolExecutor.getToolDefinitions([...active]).map((t2) => t2.name);
|
|
15903
|
+
if (added.length === 0) {
|
|
15904
|
+
return {
|
|
15905
|
+
success: true,
|
|
15906
|
+
output: t("tools.enable_already_active", {
|
|
15907
|
+
tags: requested.join(", ")
|
|
15908
|
+
})
|
|
15909
|
+
};
|
|
15910
|
+
}
|
|
15911
|
+
return {
|
|
15912
|
+
success: true,
|
|
15913
|
+
output: t("tools.enable_added", {
|
|
15914
|
+
tags: added.join(", "),
|
|
15915
|
+
tools: nowVisible.join(", ")
|
|
15916
|
+
})
|
|
15917
|
+
};
|
|
15918
|
+
}
|
|
15919
|
+
};
|
|
15920
|
+
});
|
|
15921
|
+
|
|
15836
15922
|
// src/tools/index.ts
|
|
15837
|
-
function registerAllTools(registry2, skillsModule) {
|
|
15923
|
+
function registerAllTools(registry2, skillsModule, opts) {
|
|
15838
15924
|
const tools = [
|
|
15839
15925
|
readFileTool,
|
|
15840
15926
|
writeFileTool,
|
|
@@ -15861,6 +15947,9 @@ function registerAllTools(registry2, skillsModule) {
|
|
|
15861
15947
|
searchHistoryTool,
|
|
15862
15948
|
attachImageTool
|
|
15863
15949
|
];
|
|
15950
|
+
if (opts?.enableOnDemand !== false) {
|
|
15951
|
+
tools.push(enableToolsTool);
|
|
15952
|
+
}
|
|
15864
15953
|
if (skillsModule) {
|
|
15865
15954
|
tools.push(createLoadSkillTool(skillsModule));
|
|
15866
15955
|
}
|
|
@@ -15898,6 +15987,42 @@ var init_tools = __esm(() => {
|
|
|
15898
15987
|
init_recall();
|
|
15899
15988
|
init_browser();
|
|
15900
15989
|
init_attach_image();
|
|
15990
|
+
init_enable_tools();
|
|
15991
|
+
});
|
|
15992
|
+
|
|
15993
|
+
// src/tools/hidden-tools-block.ts
|
|
15994
|
+
function buildHiddenToolsBlock(allTools, activeTags) {
|
|
15995
|
+
if (!allTools.length)
|
|
15996
|
+
return "";
|
|
15997
|
+
const activeSet = new Set(activeTags);
|
|
15998
|
+
const visible = new Set;
|
|
15999
|
+
for (const tool of allTools) {
|
|
16000
|
+
if (tool.alwaysOn || tool.tags && tool.tags.some((tag) => activeSet.has(tag))) {
|
|
16001
|
+
visible.add(tool.name);
|
|
16002
|
+
}
|
|
16003
|
+
}
|
|
16004
|
+
const hidden = allTools.filter((tool) => !visible.has(tool.name));
|
|
16005
|
+
if (hidden.length === 0)
|
|
16006
|
+
return "";
|
|
16007
|
+
const byTag = new Map;
|
|
16008
|
+
for (const tool of hidden) {
|
|
16009
|
+
const tags = tool.tags && tool.tags.length > 0 ? tool.tags : ["other"];
|
|
16010
|
+
for (const tag of tags) {
|
|
16011
|
+
if (!byTag.has(tag))
|
|
16012
|
+
byTag.set(tag, []);
|
|
16013
|
+
byTag.get(tag).push(tool);
|
|
16014
|
+
}
|
|
16015
|
+
}
|
|
16016
|
+
const lines = [t("tools.hidden_header")];
|
|
16017
|
+
for (const [tag, tools] of [...byTag.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
|
|
16018
|
+
const names = [...new Set(tools.map((tool) => tool.name))].sort().join(", ");
|
|
16019
|
+
lines.push(`- [${tag}] ${names}`);
|
|
16020
|
+
}
|
|
16021
|
+
return lines.join(`
|
|
16022
|
+
`);
|
|
16023
|
+
}
|
|
16024
|
+
var init_hidden_tools_block = __esm(() => {
|
|
16025
|
+
init_i18n();
|
|
15901
16026
|
});
|
|
15902
16027
|
|
|
15903
16028
|
// src/modules/registry.ts
|
|
@@ -16080,7 +16205,7 @@ class LintOnWritePlugin {
|
|
|
16080
16205
|
await this.runProjectTypeCheck(fullPath, ctx.baseDir, result);
|
|
16081
16206
|
}
|
|
16082
16207
|
async checkSyntax(filePath, ext, baseDir) {
|
|
16083
|
-
if (ext === ".ts" || ext === ".tsx") {
|
|
16208
|
+
if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
|
|
16084
16209
|
let content = "";
|
|
16085
16210
|
try {
|
|
16086
16211
|
content = readFileSync15(filePath, "utf-8");
|
|
@@ -16107,7 +16232,7 @@ class LintOnWritePlugin {
|
|
|
16107
16232
|
return firstError.trim();
|
|
16108
16233
|
}
|
|
16109
16234
|
}
|
|
16110
|
-
if (ext === ".js" || ext === ".jsx") {
|
|
16235
|
+
if (ext === ".js" || ext === ".jsx" || ext === ".cjs" || ext === ".mjs") {
|
|
16111
16236
|
try {
|
|
16112
16237
|
await runAsync(`node --check "${filePath}"`, baseDir, 5000);
|
|
16113
16238
|
return null;
|
|
@@ -16142,10 +16267,7 @@ class LintOnWritePlugin {
|
|
|
16142
16267
|
}
|
|
16143
16268
|
}
|
|
16144
16269
|
async runProjectTypeCheck(filePath, baseDir, result) {
|
|
16145
|
-
const projectRoot = findProjectRoot(filePath, baseDir, [
|
|
16146
|
-
"tsconfig.json",
|
|
16147
|
-
"package.json"
|
|
16148
|
-
]);
|
|
16270
|
+
const projectRoot = findProjectRoot(filePath, baseDir, ["tsconfig.json", "package.json"]);
|
|
16149
16271
|
const tsconfigPath = join23(projectRoot, "tsconfig.json");
|
|
16150
16272
|
if (!existsSync29(tsconfigPath)) {
|
|
16151
16273
|
return;
|
|
@@ -16904,6 +17026,7 @@ function createPlanToolDefinitions(deps) {
|
|
|
16904
17026
|
return [
|
|
16905
17027
|
{
|
|
16906
17028
|
name: "plan",
|
|
17029
|
+
alwaysOn: true,
|
|
16907
17030
|
description: `Create, update, show, abort, list, switch, or re-plan multi-step plans.
|
|
16908
17031
|
|
|
16909
17032
|
Actions:
|
|
@@ -16928,15 +17051,7 @@ Write CONCRETE steps with exact file paths and commands:
|
|
|
16928
17051
|
properties: {
|
|
16929
17052
|
action: {
|
|
16930
17053
|
type: "string",
|
|
16931
|
-
enum: [
|
|
16932
|
-
"create",
|
|
16933
|
-
"update",
|
|
16934
|
-
"show",
|
|
16935
|
-
"abort",
|
|
16936
|
-
"list",
|
|
16937
|
-
"switch",
|
|
16938
|
-
"re-plan"
|
|
16939
|
-
]
|
|
17054
|
+
enum: ["create", "update", "show", "abort", "list", "switch", "re-plan"]
|
|
16940
17055
|
},
|
|
16941
17056
|
title: { type: "string" },
|
|
16942
17057
|
steps: { type: "array", items: { type: "string" } },
|
|
@@ -17229,6 +17344,7 @@ ${progress}`,
|
|
|
17229
17344
|
},
|
|
17230
17345
|
{
|
|
17231
17346
|
name: "todo",
|
|
17347
|
+
alwaysOn: true,
|
|
17232
17348
|
description: "Manage sub-tasks within current plan step. Use to break down complex steps into smaller tasks.",
|
|
17233
17349
|
parameters: {
|
|
17234
17350
|
type: "object",
|
|
@@ -17324,6 +17440,7 @@ ${lines.join(`
|
|
|
17324
17440
|
},
|
|
17325
17441
|
{
|
|
17326
17442
|
name: "verify",
|
|
17443
|
+
alwaysOn: true,
|
|
17327
17444
|
description: "Run verification for the current step. Checks files mentioned in the step description.",
|
|
17328
17445
|
parameters: {
|
|
17329
17446
|
type: "object",
|
|
@@ -17935,13 +18052,7 @@ var init_module = __esm(() => {
|
|
|
17935
18052
|
});
|
|
17936
18053
|
|
|
17937
18054
|
// src/modules/security/session-encryption.ts
|
|
17938
|
-
import {
|
|
17939
|
-
readFileSync as readFileSync18,
|
|
17940
|
-
writeFileSync as writeFileSync11,
|
|
17941
|
-
existsSync as existsSync34,
|
|
17942
|
-
readdirSync as readdirSync11,
|
|
17943
|
-
unlinkSync as unlinkSync4
|
|
17944
|
-
} from "fs";
|
|
18055
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync11, existsSync as existsSync34, readdirSync as readdirSync11, unlinkSync as unlinkSync4 } from "fs";
|
|
17945
18056
|
import { join as join27 } from "path";
|
|
17946
18057
|
import { homedir as homedir8 } from "os";
|
|
17947
18058
|
|
|
@@ -19043,8 +19154,12 @@ class LspClient {
|
|
|
19043
19154
|
const map = {
|
|
19044
19155
|
ts: "typescript",
|
|
19045
19156
|
tsx: "typescriptreact",
|
|
19157
|
+
mts: "typescript",
|
|
19158
|
+
cts: "typescript",
|
|
19046
19159
|
js: "javascript",
|
|
19047
19160
|
jsx: "javascriptreact",
|
|
19161
|
+
mjs: "javascript",
|
|
19162
|
+
cjs: "javascript",
|
|
19048
19163
|
py: "python",
|
|
19049
19164
|
go: "go",
|
|
19050
19165
|
rs: "rust",
|
|
@@ -19210,6 +19325,7 @@ ${items}`;
|
|
|
19210
19325
|
name: "lsp_check",
|
|
19211
19326
|
description: 'Run static checks (LSP diagnostics) on a file or directory. For "check for errors" tasks: pass a file to check it, or a directory to check its source files (capped at 15). Returns [LSP errors] / [LSP warnings] for files with a configured LSP server.',
|
|
19212
19327
|
tags: ["code", "check"],
|
|
19328
|
+
alwaysOn: true,
|
|
19213
19329
|
boundedOutput: true,
|
|
19214
19330
|
timeoutMs: 90000,
|
|
19215
19331
|
parameters: {
|
|
@@ -19337,9 +19453,133 @@ var init_lsp = __esm(() => {
|
|
|
19337
19453
|
init_config();
|
|
19338
19454
|
});
|
|
19339
19455
|
|
|
19456
|
+
// src/modules/lsp/startup-check.ts
|
|
19457
|
+
import { existsSync as existsSync39 } from "fs";
|
|
19458
|
+
import { join as join31 } from "path";
|
|
19459
|
+
import { spawn as spawn7 } from "child_process";
|
|
19460
|
+
async function runStartupHealthCheck(config, baseDir, deps = {}) {
|
|
19461
|
+
if (!config.enabled)
|
|
19462
|
+
return null;
|
|
19463
|
+
try {
|
|
19464
|
+
const result = await Promise.race([
|
|
19465
|
+
runCheck(config, baseDir, deps),
|
|
19466
|
+
new Promise((resolve23) => setTimeout(() => resolve23(null), STARTUP_CHECK_TIMEOUT_MS))
|
|
19467
|
+
]);
|
|
19468
|
+
if (!result || result.lines.length === 0)
|
|
19469
|
+
return null;
|
|
19470
|
+
const content = `${t("lsp.startup_header")}
|
|
19471
|
+
${result.lines.join(`
|
|
19472
|
+
`)}`;
|
|
19473
|
+
return {
|
|
19474
|
+
content,
|
|
19475
|
+
priority: "high",
|
|
19476
|
+
essential: false,
|
|
19477
|
+
estimatedTokens: Math.ceil(content.length / 4)
|
|
19478
|
+
};
|
|
19479
|
+
} catch {
|
|
19480
|
+
return null;
|
|
19481
|
+
}
|
|
19482
|
+
}
|
|
19483
|
+
async function runCheck(config, baseDir, deps) {
|
|
19484
|
+
const projectRoot = findProjectRoot(baseDir, baseDir, ["tsconfig.json", "package.json"]);
|
|
19485
|
+
if (existsSync39(join31(projectRoot, "tsconfig.json"))) {
|
|
19486
|
+
const runTsc = deps.runTsc ?? runTscDefault;
|
|
19487
|
+
const errors = await runTsc(projectRoot, STARTUP_CHECK_TIMEOUT_MS);
|
|
19488
|
+
if (errors.length === 0)
|
|
19489
|
+
return null;
|
|
19490
|
+
return { lines: errors.slice(0, STARTUP_CHECK_ERROR_CAP) };
|
|
19491
|
+
}
|
|
19492
|
+
const client = deps.client ?? new LspClient;
|
|
19493
|
+
const files = await collectCheckFiles(baseDir, config);
|
|
19494
|
+
const lines = [];
|
|
19495
|
+
let checked = 0;
|
|
19496
|
+
for (const file of files.slice(0, STARTUP_CHECK_FILE_CAP)) {
|
|
19497
|
+
const serverConfig = getServerForFile(file, config);
|
|
19498
|
+
if (!serverConfig)
|
|
19499
|
+
continue;
|
|
19500
|
+
const fileRoot = findProjectRoot(file, baseDir, serverConfig.workspaceMarkers ?? []);
|
|
19501
|
+
try {
|
|
19502
|
+
const diags = await client.checkFile(file, baseDir, serverConfig, fileRoot);
|
|
19503
|
+
checked++;
|
|
19504
|
+
for (const d of diags) {
|
|
19505
|
+
if (d.severity === 1) {
|
|
19506
|
+
lines.push(formatStartupError(file, baseDir, d));
|
|
19507
|
+
}
|
|
19508
|
+
}
|
|
19509
|
+
} catch {}
|
|
19510
|
+
}
|
|
19511
|
+
if (checked === 0 || lines.length === 0)
|
|
19512
|
+
return null;
|
|
19513
|
+
return { lines: lines.slice(0, STARTUP_CHECK_ERROR_CAP) };
|
|
19514
|
+
}
|
|
19515
|
+
async function runTscDefault(projectRoot, timeoutMs) {
|
|
19516
|
+
return new Promise((resolve23) => {
|
|
19517
|
+
const child = spawn7("npx", ["tsc", "--noEmit", "--skipLibCheck"], {
|
|
19518
|
+
cwd: projectRoot,
|
|
19519
|
+
shell: true,
|
|
19520
|
+
windowsHide: true,
|
|
19521
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
19522
|
+
});
|
|
19523
|
+
let out = "";
|
|
19524
|
+
child.stdout?.on("data", (d) => {
|
|
19525
|
+
out += d.toString();
|
|
19526
|
+
});
|
|
19527
|
+
child.stderr?.on("data", (d) => {
|
|
19528
|
+
out += d.toString();
|
|
19529
|
+
});
|
|
19530
|
+
const timer = setTimeout(() => {
|
|
19531
|
+
child.kill();
|
|
19532
|
+
resolve23([]);
|
|
19533
|
+
}, timeoutMs);
|
|
19534
|
+
child.on("error", () => {
|
|
19535
|
+
clearTimeout(timer);
|
|
19536
|
+
resolve23([]);
|
|
19537
|
+
});
|
|
19538
|
+
child.on("close", () => {
|
|
19539
|
+
clearTimeout(timer);
|
|
19540
|
+
resolve23(parseTscErrors(out));
|
|
19541
|
+
});
|
|
19542
|
+
});
|
|
19543
|
+
}
|
|
19544
|
+
function parseTscErrors(output) {
|
|
19545
|
+
const lines = [];
|
|
19546
|
+
for (const raw of output.split(`
|
|
19547
|
+
`)) {
|
|
19548
|
+
const line = raw.replace(/^[a-zA-Z]:/, "").trim();
|
|
19549
|
+
if (line.includes("error TS"))
|
|
19550
|
+
lines.push(line);
|
|
19551
|
+
}
|
|
19552
|
+
return dedupe(lines);
|
|
19553
|
+
}
|
|
19554
|
+
function formatStartupError(file, baseDir, d) {
|
|
19555
|
+
const rel = file.replace(baseDir.replace(/[\\/]$/, ""), "").replace(/^[\\/]/, "");
|
|
19556
|
+
const line = d.range.start.line + 1;
|
|
19557
|
+
const col = d.range.start.character + 1;
|
|
19558
|
+
return ` ${rel || file}(${line},${col}): error: ${d.message}`;
|
|
19559
|
+
}
|
|
19560
|
+
function dedupe(lines) {
|
|
19561
|
+
const seen = new Set;
|
|
19562
|
+
const out = [];
|
|
19563
|
+
for (const line of lines) {
|
|
19564
|
+
if (!seen.has(line)) {
|
|
19565
|
+
seen.add(line);
|
|
19566
|
+
out.push(line);
|
|
19567
|
+
}
|
|
19568
|
+
}
|
|
19569
|
+
return out;
|
|
19570
|
+
}
|
|
19571
|
+
var STARTUP_CHECK_FILE_CAP = 5, STARTUP_CHECK_TIMEOUT_MS = 60000, STARTUP_CHECK_ERROR_CAP = 20;
|
|
19572
|
+
var init_startup_check = __esm(() => {
|
|
19573
|
+
init_i18n();
|
|
19574
|
+
init_client2();
|
|
19575
|
+
init_check_tool();
|
|
19576
|
+
init_config();
|
|
19577
|
+
init_project_root();
|
|
19578
|
+
});
|
|
19579
|
+
|
|
19340
19580
|
// src/modules/indexer/walker.ts
|
|
19341
|
-
import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as
|
|
19342
|
-
import { join as
|
|
19581
|
+
import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync40, watch } from "fs";
|
|
19582
|
+
import { join as join32, relative as relative3, extname as extname5 } from "path";
|
|
19343
19583
|
|
|
19344
19584
|
class Indexer {
|
|
19345
19585
|
baseDir;
|
|
@@ -19366,7 +19606,7 @@ class Indexer {
|
|
|
19366
19606
|
let totalSize = 0;
|
|
19367
19607
|
let count = 0;
|
|
19368
19608
|
const walkDir2 = (dir) => {
|
|
19369
|
-
if (!
|
|
19609
|
+
if (!existsSync40(dir))
|
|
19370
19610
|
return;
|
|
19371
19611
|
let entries;
|
|
19372
19612
|
try {
|
|
@@ -19377,7 +19617,7 @@ class Indexer {
|
|
|
19377
19617
|
for (const entry of entries) {
|
|
19378
19618
|
if (count >= this.MAX_FILES)
|
|
19379
19619
|
return;
|
|
19380
|
-
const fullPath =
|
|
19620
|
+
const fullPath = join32(dir, entry);
|
|
19381
19621
|
const relPath = relative3(this.baseDir, fullPath);
|
|
19382
19622
|
const stat2 = statSync7(fullPath);
|
|
19383
19623
|
if (stat2.isDirectory()) {
|
|
@@ -19440,19 +19680,19 @@ var init_walker = __esm(() => {
|
|
|
19440
19680
|
});
|
|
19441
19681
|
|
|
19442
19682
|
// src/modules/indexer/cache.ts
|
|
19443
|
-
import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as
|
|
19444
|
-
import { join as
|
|
19683
|
+
import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as existsSync41, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
|
|
19684
|
+
import { join as join33 } from "path";
|
|
19445
19685
|
|
|
19446
19686
|
class IndexCache {
|
|
19447
19687
|
cachePath;
|
|
19448
19688
|
cache = null;
|
|
19449
19689
|
constructor(cacheDir) {
|
|
19450
|
-
this.cachePath =
|
|
19690
|
+
this.cachePath = join33(cacheDir, "index-cache.json");
|
|
19451
19691
|
}
|
|
19452
19692
|
load() {
|
|
19453
19693
|
if (this.cache)
|
|
19454
19694
|
return this.cache;
|
|
19455
|
-
if (!
|
|
19695
|
+
if (!existsSync41(this.cachePath))
|
|
19456
19696
|
return null;
|
|
19457
19697
|
try {
|
|
19458
19698
|
this.cache = JSON.parse(readFileSync23(this.cachePath, "utf-8"));
|
|
@@ -19463,14 +19703,14 @@ class IndexCache {
|
|
|
19463
19703
|
}
|
|
19464
19704
|
save(result) {
|
|
19465
19705
|
this.cache = result;
|
|
19466
|
-
const dir =
|
|
19467
|
-
if (!
|
|
19706
|
+
const dir = join33(this.cachePath, "..");
|
|
19707
|
+
if (!existsSync41(dir))
|
|
19468
19708
|
mkdirSync17(dir, { recursive: true });
|
|
19469
19709
|
writeFileSync14(this.cachePath, JSON.stringify(result), "utf-8");
|
|
19470
19710
|
}
|
|
19471
19711
|
invalidate() {
|
|
19472
19712
|
this.cache = null;
|
|
19473
|
-
if (
|
|
19713
|
+
if (existsSync41(this.cachePath)) {
|
|
19474
19714
|
try {
|
|
19475
19715
|
rmSync3(this.cachePath);
|
|
19476
19716
|
} catch {}
|
|
@@ -19480,11 +19720,11 @@ class IndexCache {
|
|
|
19480
19720
|
var init_cache = () => {};
|
|
19481
19721
|
|
|
19482
19722
|
// src/modules/indexer/project-profile.ts
|
|
19483
|
-
import { readFileSync as readFileSync24, existsSync as
|
|
19484
|
-
import { join as
|
|
19723
|
+
import { readFileSync as readFileSync24, existsSync as existsSync42 } from "fs";
|
|
19724
|
+
import { join as join34 } from "path";
|
|
19485
19725
|
function detectManifest(baseDir) {
|
|
19486
19726
|
for (const manifest of MANIFEST_ORDER) {
|
|
19487
|
-
if (
|
|
19727
|
+
if (existsSync42(join34(baseDir, manifest)))
|
|
19488
19728
|
return manifest;
|
|
19489
19729
|
}
|
|
19490
19730
|
return null;
|
|
@@ -19501,7 +19741,7 @@ function cleanDependency(entry) {
|
|
|
19501
19741
|
}
|
|
19502
19742
|
function readPackageJson(baseDir) {
|
|
19503
19743
|
try {
|
|
19504
|
-
const raw = JSON.parse(readFileSync24(
|
|
19744
|
+
const raw = JSON.parse(readFileSync24(join34(baseDir, "package.json"), "utf-8"));
|
|
19505
19745
|
if (!raw || typeof raw !== "object")
|
|
19506
19746
|
return null;
|
|
19507
19747
|
const profile = {
|
|
@@ -19525,7 +19765,7 @@ function readPackageJson(baseDir) {
|
|
|
19525
19765
|
}
|
|
19526
19766
|
function readPyproject(baseDir) {
|
|
19527
19767
|
try {
|
|
19528
|
-
const content = readFileSync24(
|
|
19768
|
+
const content = readFileSync24(join34(baseDir, "pyproject.toml"), "utf-8");
|
|
19529
19769
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
19530
19770
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
19531
19771
|
if (nameMatch)
|
|
@@ -19541,7 +19781,7 @@ function readPyproject(baseDir) {
|
|
|
19541
19781
|
}
|
|
19542
19782
|
function readCargo(baseDir) {
|
|
19543
19783
|
try {
|
|
19544
|
-
const content = readFileSync24(
|
|
19784
|
+
const content = readFileSync24(join34(baseDir, "Cargo.toml"), "utf-8");
|
|
19545
19785
|
const profile = { runtime: "rust", deps: [], devDeps: [], scripts: {} };
|
|
19546
19786
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
19547
19787
|
if (nameMatch)
|
|
@@ -19565,7 +19805,7 @@ function readCargo(baseDir) {
|
|
|
19565
19805
|
}
|
|
19566
19806
|
function readGoMod(baseDir) {
|
|
19567
19807
|
try {
|
|
19568
|
-
const content = readFileSync24(
|
|
19808
|
+
const content = readFileSync24(join34(baseDir, "go.mod"), "utf-8");
|
|
19569
19809
|
const profile = { runtime: "go", deps: [], devDeps: [], scripts: {} };
|
|
19570
19810
|
const moduleMatch = content.match(/^module\s+(\S+)/m);
|
|
19571
19811
|
if (moduleMatch)
|
|
@@ -19583,7 +19823,7 @@ function readGoMod(baseDir) {
|
|
|
19583
19823
|
}
|
|
19584
19824
|
function readRequirements(baseDir) {
|
|
19585
19825
|
try {
|
|
19586
|
-
const content = readFileSync24(
|
|
19826
|
+
const content = readFileSync24(join34(baseDir, "requirements.txt"), "utf-8");
|
|
19587
19827
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
19588
19828
|
for (const line of content.split(`
|
|
19589
19829
|
`)) {
|
|
@@ -19811,6 +20051,7 @@ ${t("indexer.and_more", { count: result.files.length - 100 })}` : "";
|
|
|
19811
20051
|
createProjectMapTool() {
|
|
19812
20052
|
return {
|
|
19813
20053
|
name: "project_map",
|
|
20054
|
+
alwaysOn: true,
|
|
19814
20055
|
description: t("indexer.project_map_desc"),
|
|
19815
20056
|
parameters: {
|
|
19816
20057
|
type: "object",
|
|
@@ -19851,7 +20092,10 @@ ${stackLine2}` : summary2;
|
|
|
19851
20092
|
return `- ${path}${exports}`;
|
|
19852
20093
|
}).join(`
|
|
19853
20094
|
`);
|
|
19854
|
-
return this.makeResult(t("indexer.find_results", {
|
|
20095
|
+
return this.makeResult(t("indexer.find_results", {
|
|
20096
|
+
count: matches.length,
|
|
20097
|
+
results: lines
|
|
20098
|
+
}));
|
|
19855
20099
|
}
|
|
19856
20100
|
if (!this.index) {
|
|
19857
20101
|
await this.buildIndex();
|
|
@@ -20037,7 +20281,7 @@ var init_mcp = __esm(() => {
|
|
|
20037
20281
|
|
|
20038
20282
|
// src/modules/memory/module.ts
|
|
20039
20283
|
import { homedir as homedir10 } from "os";
|
|
20040
|
-
import { join as
|
|
20284
|
+
import { join as join35 } from "path";
|
|
20041
20285
|
|
|
20042
20286
|
class MemoryModule {
|
|
20043
20287
|
name = "memory";
|
|
@@ -20046,7 +20290,7 @@ class MemoryModule {
|
|
|
20046
20290
|
if (storeOrDir instanceof MemoryStore) {
|
|
20047
20291
|
this.store = storeOrDir;
|
|
20048
20292
|
} else {
|
|
20049
|
-
const dir = storeOrDir ||
|
|
20293
|
+
const dir = storeOrDir || join35(homedir10(), ".mma", "memory");
|
|
20050
20294
|
this.store = new MemoryStore(dir);
|
|
20051
20295
|
}
|
|
20052
20296
|
}
|
|
@@ -20132,17 +20376,14 @@ var init_module8 = __esm(() => {
|
|
|
20132
20376
|
});
|
|
20133
20377
|
|
|
20134
20378
|
// src/core/version.ts
|
|
20135
|
-
import { existsSync as
|
|
20136
|
-
import { join as
|
|
20379
|
+
import { existsSync as existsSync43, readFileSync as readFileSync25 } from "fs";
|
|
20380
|
+
import { join as join36, dirname as dirname13 } from "path";
|
|
20137
20381
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20138
20382
|
function readMmaVersion() {
|
|
20139
20383
|
const here = dirname13(fileURLToPath2(import.meta.url));
|
|
20140
|
-
const candidates = [
|
|
20141
|
-
join35(here, "..", "..", "package.json"),
|
|
20142
|
-
join35(here, "..", "package.json")
|
|
20143
|
-
];
|
|
20384
|
+
const candidates = [join36(here, "..", "..", "package.json"), join36(here, "..", "package.json")];
|
|
20144
20385
|
for (const p of candidates) {
|
|
20145
|
-
if (
|
|
20386
|
+
if (existsSync43(p)) {
|
|
20146
20387
|
try {
|
|
20147
20388
|
const raw = JSON.parse(readFileSync25(p, "utf8"));
|
|
20148
20389
|
if (raw.version)
|
|
@@ -20161,8 +20402,8 @@ __export(exports_bootstrap, {
|
|
|
20161
20402
|
bootstrap: () => bootstrap
|
|
20162
20403
|
});
|
|
20163
20404
|
import { homedir as homedir11 } from "os";
|
|
20164
|
-
import { join as
|
|
20165
|
-
import { existsSync as
|
|
20405
|
+
import { join as join37, resolve as resolve23 } from "path";
|
|
20406
|
+
import { existsSync as existsSync44, readFileSync as readFileSync26, writeFileSync as writeFileSync15 } from "fs";
|
|
20166
20407
|
function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
20167
20408
|
const now = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
20168
20409
|
const isWin = profileCompressed.toLowerCase().includes("win32");
|
|
@@ -20175,11 +20416,11 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
20175
20416
|
lines.push(`Windows (PowerShell): use list_dir/read_file/delete_file/create_dir tools instead of dir/type/del/mkdir. No PowerShell cmdlets (Get-Content, Select-Object, Write-Output), no head/tail/grep/cat. Use forward slashes in paths. CWD: ${baseDir}`);
|
|
20176
20417
|
}
|
|
20177
20418
|
lines.push(`Runtime: Bun is available — run TypeScript directly with "bun <file.ts>" and tests with "bun test" (no tsx/ts-node/npm install needed for that).`);
|
|
20178
|
-
lines.push(`Bash: use "workdir" param instead of "cd dir && cmd". One command per call. Long-running processes: pass "background: true" (id immediately), otherwise auto-backgrounded after a few seconds — check with process_log.`, `DEVELOPMENT RULES (strict): 1) install deps BEFORE writing source (npm/pip/cargo, verify lockfile exists; never import uninstalled packages); 2) framework/toolkit init BEFORE app code; 3) follow plan sequentially, after each step verify deliverables exist with real content, then "plan update step=N status=done"; 4) verify work on disk + command output — don't assume success; 5) no premature work (no files/imports for future steps); 6) stuck after 2+ failures: STOP, try a different approach, write files directly, ask the user.`, `PLAN QUALITY: each step = CONCRETE deliverables (exact file paths with extensions, exact packages, exact commands). Vague steps ("Setup the project") forbidden. Cover init → deps → framework → code → verification. 5-8 steps.`, `For "check/fix errors" tasks, each verification step must name the exact command that proves the errors are gone — "bun run build", "bun test", or the "lsp_check" tool — and the step is done only after that check reports clean.`);
|
|
20419
|
+
lines.push(`Bash: use "workdir" param instead of "cd dir && cmd". One command per call. Long-running processes: pass "background: true" (id immediately), otherwise auto-backgrounded after a few seconds — check with process_log.`, `DEVELOPMENT RULES (strict): 1) install deps BEFORE writing source (npm/pip/cargo, verify lockfile exists; never import uninstalled packages); 2) framework/toolkit init BEFORE app code; 3) follow plan sequentially, after each step verify deliverables exist with real content, then "plan update step=N status=done"; 4) verify work on disk + command output — don't assume success; 5) no premature work (no files/imports for future steps); 6) stuck after 2+ failures: STOP, try a different approach, write files directly, ask the user.`, `VERIFY EVERY WRITE: after write_file or edit_file, if the tool result contains NO [LSP errors], [LSP warnings], [Syntax check failed], or [Project typecheck failed] feedback, call the "lsp_check" tool on the file you just wrote BEFORE marking the step done. Never assume a written file is valid — prove it.`, `PLAN QUALITY: each step = CONCRETE deliverables (exact file paths with extensions, exact packages, exact commands). Vague steps ("Setup the project") forbidden. Cover init → deps → framework → code → verification. 5-8 steps.`, `For "check/fix errors" tasks, each verification step must name the exact command that proves the errors are gone — "bun run build", "bun test", or the "lsp_check" tool — and the step is done only after that check reports clean.`);
|
|
20179
20420
|
if (config.autoPlan) {
|
|
20180
20421
|
lines.push(`Plan rule (MANDATORY): any task creating files, installing packages, or requiring multiple actions MUST create a plan with the "plan" tool BEFORE starting. Each step = a concrete deliverable.`);
|
|
20181
20422
|
}
|
|
20182
|
-
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".`);
|
|
20423
|
+
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.`);
|
|
20183
20424
|
const hasMCP = config.mcpServers && Object.values(config.mcpServers).some((s) => s.enabled !== false);
|
|
20184
20425
|
if (hasMCP) {
|
|
20185
20426
|
lines.push(`MCP servers are available — use the named MCP tools (prefixed mcp__) to query external services.`);
|
|
@@ -20188,8 +20429,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
20188
20429
|
`);
|
|
20189
20430
|
}
|
|
20190
20431
|
async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
20191
|
-
const dir = configDir ||
|
|
20192
|
-
const projectConfigPath = projectDir ?
|
|
20432
|
+
const dir = configDir || join37(homedir11(), ".mma");
|
|
20433
|
+
const projectConfigPath = projectDir ? join37(projectDir, ".mmrc") : join37(process.cwd(), ".mmrc");
|
|
20193
20434
|
const config = loadConfig({ configDir: dir, projectConfigPath });
|
|
20194
20435
|
setLocale(config.locale);
|
|
20195
20436
|
try {
|
|
@@ -20199,7 +20440,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20199
20440
|
}
|
|
20200
20441
|
} catch {}
|
|
20201
20442
|
const logger = new Logger(config.logLevel);
|
|
20202
|
-
logger.setLogDir(
|
|
20443
|
+
logger.setLogDir(join37(dir, "logs"));
|
|
20203
20444
|
logger.debug("MMA bootstrap", {
|
|
20204
20445
|
version: config.version,
|
|
20205
20446
|
model: config.model
|
|
@@ -20221,7 +20462,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20221
20462
|
logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
|
|
20222
20463
|
}
|
|
20223
20464
|
}
|
|
20224
|
-
const profile = new UserProfile(
|
|
20465
|
+
const profile = new UserProfile(join37(dir));
|
|
20225
20466
|
profile.load() || profile.collect();
|
|
20226
20467
|
profile.save();
|
|
20227
20468
|
const llmProvider = new OpenAICompatProvider({
|
|
@@ -20233,7 +20474,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20233
20474
|
rateLimits: config.security?.rateLimits
|
|
20234
20475
|
});
|
|
20235
20476
|
const baseDir = projectDir ? resolve23(projectDir) : process.cwd();
|
|
20236
|
-
const projectMapCacheDir =
|
|
20477
|
+
const projectMapCacheDir = join37(baseDir, ".mma");
|
|
20237
20478
|
const indexerModule = new IndexerModule({
|
|
20238
20479
|
baseDir,
|
|
20239
20480
|
cacheDir: projectMapCacheDir
|
|
@@ -20244,14 +20485,16 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20244
20485
|
logger.warn(`Project indexing failed: ${err.message}`);
|
|
20245
20486
|
}
|
|
20246
20487
|
const skillsLoader = new SkillsLoader;
|
|
20247
|
-
const builtinDir =
|
|
20248
|
-
const globalDir =
|
|
20249
|
-
const projectSkillsDir =
|
|
20488
|
+
const builtinDir = join37(import.meta.dirname, "skills", "builtin");
|
|
20489
|
+
const globalDir = join37(homedir11(), ".agents", "skills");
|
|
20490
|
+
const projectSkillsDir = join37(baseDir, ".mma", "skills");
|
|
20250
20491
|
const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
|
|
20251
20492
|
const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
|
|
20252
20493
|
const skillsModule = new SkillsModule(availableSkills, skillsBudget);
|
|
20253
20494
|
const toolRegistry = new ToolRegistry;
|
|
20254
|
-
registerAllTools(toolRegistry, skillsModule
|
|
20495
|
+
registerAllTools(toolRegistry, skillsModule, {
|
|
20496
|
+
enableOnDemand: config.tools?.enableOnDemand
|
|
20497
|
+
});
|
|
20255
20498
|
const pluginManager = new PluginManager;
|
|
20256
20499
|
const systemInfoContent = buildSystemInfo(config, baseDir, profile.compress());
|
|
20257
20500
|
const systemInfoPrompt = {
|
|
@@ -20260,11 +20503,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20260
20503
|
essential: true,
|
|
20261
20504
|
estimatedTokens: Math.ceil(systemInfoContent.length / 4)
|
|
20262
20505
|
};
|
|
20263
|
-
const agentsMdGlobal =
|
|
20264
|
-
if (!
|
|
20506
|
+
const agentsMdGlobal = join37(dir, "AGENTS.md");
|
|
20507
|
+
if (!existsSync44(agentsMdGlobal)) {
|
|
20265
20508
|
writeFileSync15(agentsMdGlobal, "", "utf-8");
|
|
20266
20509
|
}
|
|
20267
|
-
const sessionDir =
|
|
20510
|
+
const sessionDir = join37(dir, "sessions");
|
|
20268
20511
|
const sessionStore = new SessionStore(sessionDir);
|
|
20269
20512
|
sessionStore.init();
|
|
20270
20513
|
const sessionManager = new SessionManager(sessionStore, {
|
|
@@ -20278,6 +20521,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20278
20521
|
sessionManager.create();
|
|
20279
20522
|
}
|
|
20280
20523
|
const tokenCounter = new TokenCounter(config.model);
|
|
20524
|
+
const enableOnDemand = config.tools?.enableOnDemand !== false;
|
|
20525
|
+
const activeToolTags = enableOnDemand ? config.tools?.defaultTags ? [...config.tools.defaultTags] : [] : [];
|
|
20281
20526
|
const contextManager = new ContextManager(config.contextWindow, config.contextBudget, tokenCounter);
|
|
20282
20527
|
const toolCtx = {
|
|
20283
20528
|
config,
|
|
@@ -20285,6 +20530,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20285
20530
|
logger,
|
|
20286
20531
|
exitOnComplete,
|
|
20287
20532
|
contextManager,
|
|
20533
|
+
activeToolTags,
|
|
20288
20534
|
sessionId: sessionManager.getActiveMeta()?.id,
|
|
20289
20535
|
sessionContext: sessionManager.getSessionContext() ?? undefined,
|
|
20290
20536
|
recursionDepth: 0,
|
|
@@ -20331,7 +20577,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20331
20577
|
const mcpModule = new MCPModule(config);
|
|
20332
20578
|
await mcpModule.initialize();
|
|
20333
20579
|
moduleRegistry.register(mcpModule);
|
|
20334
|
-
const memoryStore = new MemoryStore(
|
|
20580
|
+
const memoryStore = new MemoryStore(join37(dir, "memory"));
|
|
20335
20581
|
const memoryModule = new MemoryModule(memoryStore);
|
|
20336
20582
|
moduleRegistry.register(memoryModule);
|
|
20337
20583
|
if (config.browser.enabled) {
|
|
@@ -20350,6 +20596,10 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20350
20596
|
lspPlugin.isBuiltin = true;
|
|
20351
20597
|
pluginManager.register(lspPlugin);
|
|
20352
20598
|
}
|
|
20599
|
+
let startupCheckBlock = null;
|
|
20600
|
+
if (!exitOnComplete && true) {
|
|
20601
|
+
startupCheckBlock = await runStartupHealthCheck(config.lsp ?? DEFAULT_LSP_CONFIG, baseDir);
|
|
20602
|
+
}
|
|
20353
20603
|
const moduleTools = moduleRegistry.collectToolDefinitions();
|
|
20354
20604
|
for (const tool of moduleTools) {
|
|
20355
20605
|
toolRegistry.register(tool);
|
|
@@ -20382,8 +20632,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20382
20632
|
pluginManager.register(plugin);
|
|
20383
20633
|
pluginManager.register(plugin2);
|
|
20384
20634
|
const pluginLoader = new PluginLoader;
|
|
20385
|
-
const globalPluginsDir =
|
|
20386
|
-
const projectPluginsDir =
|
|
20635
|
+
const globalPluginsDir = join37(homedir11(), ".mma", "plugins");
|
|
20636
|
+
const projectPluginsDir = join37(baseDir, ".mma", "plugins");
|
|
20387
20637
|
const mmaVersion = readMmaVersion();
|
|
20388
20638
|
pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger, {
|
|
20389
20639
|
source: "global",
|
|
@@ -20409,12 +20659,12 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20409
20659
|
const skipAgentsMd = noAgentsMd === true;
|
|
20410
20660
|
if (!skipAgentsMd) {
|
|
20411
20661
|
const agentsMdCandidates = [
|
|
20412
|
-
|
|
20413
|
-
|
|
20414
|
-
|
|
20662
|
+
join37(baseDir, "AGENTS.md"),
|
|
20663
|
+
join37(baseDir, ".mma", "AGENTS.md"),
|
|
20664
|
+
join37(dir, "AGENTS.md")
|
|
20415
20665
|
];
|
|
20416
20666
|
for (const p of agentsMdCandidates) {
|
|
20417
|
-
if (
|
|
20667
|
+
if (existsSync44(p)) {
|
|
20418
20668
|
const content = readFileSync26(p, "utf-8").trim();
|
|
20419
20669
|
if (content) {
|
|
20420
20670
|
agentsMdBlocks.push({
|
|
@@ -20432,6 +20682,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20432
20682
|
...moduleRegistry.collectPromptBlocks(["indexer"]),
|
|
20433
20683
|
...agentsMdBlocks
|
|
20434
20684
|
];
|
|
20685
|
+
if (startupCheckBlock)
|
|
20686
|
+
promptBlocks.push(startupCheckBlock);
|
|
20435
20687
|
const agentDeps = {
|
|
20436
20688
|
config,
|
|
20437
20689
|
llmProvider,
|
|
@@ -20441,6 +20693,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20441
20693
|
hallucinationDetector,
|
|
20442
20694
|
logger,
|
|
20443
20695
|
baseDir,
|
|
20696
|
+
toolTags: activeToolTags,
|
|
20444
20697
|
promptBlocks,
|
|
20445
20698
|
getDynamicPromptBlocks: () => {
|
|
20446
20699
|
const blocks = [];
|
|
@@ -20453,6 +20706,15 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20453
20706
|
const mapBlock = indexerModule.getSystemPromptBlock();
|
|
20454
20707
|
if (mapBlock)
|
|
20455
20708
|
blocks.push(mapBlock);
|
|
20709
|
+
const hiddenToolsBlock = buildHiddenToolsBlock(toolRegistry.getAll(), activeToolTags);
|
|
20710
|
+
if (hiddenToolsBlock) {
|
|
20711
|
+
blocks.push({
|
|
20712
|
+
content: hiddenToolsBlock,
|
|
20713
|
+
priority: "low",
|
|
20714
|
+
essential: false,
|
|
20715
|
+
estimatedTokens: Math.ceil(hiddenToolsBlock.length / 4)
|
|
20716
|
+
});
|
|
20717
|
+
}
|
|
20456
20718
|
return blocks;
|
|
20457
20719
|
},
|
|
20458
20720
|
finalAudit: () => execModule.runFinalAudit(),
|
|
@@ -20478,6 +20740,7 @@ var init_bootstrap = __esm(() => {
|
|
|
20478
20740
|
init_app_logger();
|
|
20479
20741
|
init_openai_compat();
|
|
20480
20742
|
init_tools();
|
|
20743
|
+
init_hidden_tools_block();
|
|
20481
20744
|
init_executor();
|
|
20482
20745
|
init_manager2();
|
|
20483
20746
|
init_loader();
|
|
@@ -20492,6 +20755,7 @@ var init_bootstrap = __esm(() => {
|
|
|
20492
20755
|
init_skills();
|
|
20493
20756
|
init_browser2();
|
|
20494
20757
|
init_lsp();
|
|
20758
|
+
init_startup_check();
|
|
20495
20759
|
init_indexer();
|
|
20496
20760
|
init_mcp();
|
|
20497
20761
|
init_module8();
|
|
@@ -21219,18 +21483,8 @@ async function runSetup(externalRl) {
|
|
|
21219
21483
|
t("setup.summary_value")
|
|
21220
21484
|
], [
|
|
21221
21485
|
[t("setup.provider_type"), provider, t("setup.model_name"), model],
|
|
21222
|
-
[
|
|
21223
|
-
|
|
21224
|
-
apiBase,
|
|
21225
|
-
t("setup.context_window"),
|
|
21226
|
-
String(contextWindow)
|
|
21227
|
-
],
|
|
21228
|
-
[
|
|
21229
|
-
t("setup.api_key"),
|
|
21230
|
-
apiKey || "not-needed",
|
|
21231
|
-
t("setup.max_iters"),
|
|
21232
|
-
String(maxIterations)
|
|
21233
|
-
],
|
|
21486
|
+
["API Base URL", apiBase, t("setup.context_window"), String(contextWindow)],
|
|
21487
|
+
[t("setup.api_key"), apiKey || "not-needed", t("setup.max_iters"), String(maxIterations)],
|
|
21234
21488
|
[t("setup.ui_lang"), locale, "", ""]
|
|
21235
21489
|
], { maxColumns: 4 });
|
|
21236
21490
|
for (const l of summary)
|
|
@@ -21271,12 +21525,12 @@ __export(exports_manifest, {
|
|
|
21271
21525
|
getCertMark: () => getCertMark,
|
|
21272
21526
|
MANIFEST_PATH: () => MANIFEST_PATH
|
|
21273
21527
|
});
|
|
21274
|
-
import { existsSync as
|
|
21528
|
+
import { existsSync as existsSync45, readFileSync as readFileSync27, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
21275
21529
|
import { homedir as homedir13 } from "os";
|
|
21276
|
-
import { join as
|
|
21530
|
+
import { join as join39 } from "path";
|
|
21277
21531
|
function readManifest(path = MANIFEST_PATH) {
|
|
21278
21532
|
try {
|
|
21279
|
-
if (
|
|
21533
|
+
if (existsSync45(path)) {
|
|
21280
21534
|
const raw = JSON.parse(readFileSync27(path, "utf-8"));
|
|
21281
21535
|
return { version: 1, certifications: raw.certifications ?? [] };
|
|
21282
21536
|
}
|
|
@@ -21284,7 +21538,7 @@ function readManifest(path = MANIFEST_PATH) {
|
|
|
21284
21538
|
return { version: 1, certifications: [] };
|
|
21285
21539
|
}
|
|
21286
21540
|
function saveManifest(m, path = MANIFEST_PATH) {
|
|
21287
|
-
mkdirSync18(
|
|
21541
|
+
mkdirSync18(join39(homedir13(), ".mma"), { recursive: true });
|
|
21288
21542
|
writeFileSync16(path, JSON.stringify(m, null, 2), "utf-8");
|
|
21289
21543
|
}
|
|
21290
21544
|
function upsertCertification(entry, path = MANIFEST_PATH) {
|
|
@@ -21319,7 +21573,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
|
|
|
21319
21573
|
}
|
|
21320
21574
|
var MANIFEST_PATH;
|
|
21321
21575
|
var init_manifest = __esm(() => {
|
|
21322
|
-
MANIFEST_PATH =
|
|
21576
|
+
MANIFEST_PATH = join39(homedir13(), ".mma", "certifications.json");
|
|
21323
21577
|
});
|
|
21324
21578
|
|
|
21325
21579
|
// node_modules/yaml/dist/nodes/identity.js
|
|
@@ -28442,8 +28696,8 @@ var init_scenarios = __esm(() => {
|
|
|
28442
28696
|
});
|
|
28443
28697
|
|
|
28444
28698
|
// src/modules/certification/loader.ts
|
|
28445
|
-
import { existsSync as
|
|
28446
|
-
import { join as
|
|
28699
|
+
import { existsSync as existsSync46, readdirSync as readdirSync15, readFileSync as readFileSync28 } from "fs";
|
|
28700
|
+
import { join as join40 } from "path";
|
|
28447
28701
|
function validateScenario(s) {
|
|
28448
28702
|
const errors2 = [];
|
|
28449
28703
|
const isSkip = s.mode === "skip";
|
|
@@ -28492,12 +28746,12 @@ function loadScenarios(userDir) {
|
|
|
28492
28746
|
else
|
|
28493
28747
|
scenarios.push(s);
|
|
28494
28748
|
}
|
|
28495
|
-
if (userDir &&
|
|
28749
|
+
if (userDir && existsSync46(userDir)) {
|
|
28496
28750
|
for (const file of readdirSync15(userDir)) {
|
|
28497
28751
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
|
|
28498
28752
|
continue;
|
|
28499
28753
|
try {
|
|
28500
|
-
const raw = readFileSync28(
|
|
28754
|
+
const raw = readFileSync28(join40(userDir, file), "utf-8");
|
|
28501
28755
|
const data = $parse(raw);
|
|
28502
28756
|
const parsed = normalizeScenario(data, file);
|
|
28503
28757
|
const errs = validateScenario(parsed);
|
|
@@ -28550,31 +28804,31 @@ var init_loader3 = __esm(() => {
|
|
|
28550
28804
|
});
|
|
28551
28805
|
|
|
28552
28806
|
// src/modules/certification/fact-checker.ts
|
|
28553
|
-
import { existsSync as
|
|
28554
|
-
import { join as
|
|
28807
|
+
import { existsSync as existsSync47, readFileSync as readFileSync29, statSync as statSync8 } from "fs";
|
|
28808
|
+
import { join as join41 } from "path";
|
|
28555
28809
|
function checkSandbox(sandboxDir, checks, exitCode, output) {
|
|
28556
28810
|
const failures = [];
|
|
28557
28811
|
for (const check of checks) {
|
|
28558
|
-
if (!
|
|
28812
|
+
if (!runCheck2(sandboxDir, check, exitCode, output)) {
|
|
28559
28813
|
failures.push(describe(check));
|
|
28560
28814
|
}
|
|
28561
28815
|
}
|
|
28562
28816
|
return { pass: failures.length === 0, failures };
|
|
28563
28817
|
}
|
|
28564
|
-
function
|
|
28818
|
+
function runCheck2(sandboxDir, check, exitCode, output) {
|
|
28565
28819
|
switch (check.type) {
|
|
28566
28820
|
case "exitCode":
|
|
28567
28821
|
return exitCode === (check.code ?? 0);
|
|
28568
28822
|
case "outputContains":
|
|
28569
28823
|
return output.includes(check.text);
|
|
28570
28824
|
case "fileExists":
|
|
28571
|
-
return isFile(
|
|
28825
|
+
return isFile(join41(sandboxDir, check.path));
|
|
28572
28826
|
case "fileNotExists":
|
|
28573
|
-
return !
|
|
28827
|
+
return !existsSync47(join41(sandboxDir, check.path));
|
|
28574
28828
|
case "dirExists":
|
|
28575
|
-
return isDir(
|
|
28829
|
+
return isDir(join41(sandboxDir, check.path));
|
|
28576
28830
|
case "fileContent": {
|
|
28577
|
-
const abs =
|
|
28831
|
+
const abs = join41(sandboxDir, check.path);
|
|
28578
28832
|
if (!isFile(abs))
|
|
28579
28833
|
return false;
|
|
28580
28834
|
const content = readFileSync29(abs, "utf-8");
|
|
@@ -28585,7 +28839,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
28585
28839
|
return false;
|
|
28586
28840
|
}
|
|
28587
28841
|
case "fileRegex": {
|
|
28588
|
-
const abs =
|
|
28842
|
+
const abs = join41(sandboxDir, check.path);
|
|
28589
28843
|
if (!isFile(abs))
|
|
28590
28844
|
return false;
|
|
28591
28845
|
return new RegExp(check.pattern).test(readFileSync29(abs, "utf-8"));
|
|
@@ -28596,14 +28850,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
28596
28850
|
}
|
|
28597
28851
|
function isFile(p) {
|
|
28598
28852
|
try {
|
|
28599
|
-
return
|
|
28853
|
+
return existsSync47(p) && statSync8(p).isFile();
|
|
28600
28854
|
} catch {
|
|
28601
28855
|
return false;
|
|
28602
28856
|
}
|
|
28603
28857
|
}
|
|
28604
28858
|
function isDir(p) {
|
|
28605
28859
|
try {
|
|
28606
|
-
return
|
|
28860
|
+
return existsSync47(p) && statSync8(p).isDirectory();
|
|
28607
28861
|
} catch {
|
|
28608
28862
|
return false;
|
|
28609
28863
|
}
|
|
@@ -28633,10 +28887,10 @@ function describe(check) {
|
|
|
28633
28887
|
var init_fact_checker = () => {};
|
|
28634
28888
|
|
|
28635
28889
|
// src/modules/certification/runner.ts
|
|
28636
|
-
import { spawn as
|
|
28637
|
-
import { existsSync as
|
|
28890
|
+
import { spawn as spawn8 } from "child_process";
|
|
28891
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
|
|
28638
28892
|
import { platform as platform9 } from "os";
|
|
28639
|
-
import { join as
|
|
28893
|
+
import { join as join42, resolve as resolve24, dirname as dirname14 } from "path";
|
|
28640
28894
|
async function runScenario(scenario, opts) {
|
|
28641
28895
|
if (scenario.mode === "skip") {
|
|
28642
28896
|
return {
|
|
@@ -28655,7 +28909,7 @@ async function runScenario(scenario, opts) {
|
|
|
28655
28909
|
let passed = 0;
|
|
28656
28910
|
let firstError;
|
|
28657
28911
|
for (let i = 1;i <= reps; i++) {
|
|
28658
|
-
const sandbox =
|
|
28912
|
+
const sandbox = join42(opts.sandboxBase, `run-${scenario.id}-${i}`);
|
|
28659
28913
|
let failures = [];
|
|
28660
28914
|
let exitCode = -1;
|
|
28661
28915
|
let output = "";
|
|
@@ -28716,28 +28970,25 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
28716
28970
|
rmSync4(sandbox, { recursive: true, force: true });
|
|
28717
28971
|
mkdirSync19(sandbox, { recursive: true });
|
|
28718
28972
|
for (const f of scenario.fixtures ?? []) {
|
|
28719
|
-
const src =
|
|
28720
|
-
if (!
|
|
28973
|
+
const src = join42(mmaRoot, f.source);
|
|
28974
|
+
if (!existsSync48(src)) {
|
|
28721
28975
|
throw new Error(`fixture missing: ${f.source}`);
|
|
28722
28976
|
}
|
|
28723
|
-
const dest =
|
|
28977
|
+
const dest = join42(sandbox, f.dest);
|
|
28724
28978
|
mkdirSync19(dirname14(dest), { recursive: true });
|
|
28725
28979
|
cpSync2(src, dest);
|
|
28726
28980
|
}
|
|
28727
28981
|
}
|
|
28728
28982
|
function resolveMmaEntry(mmaRoot) {
|
|
28729
|
-
const dev =
|
|
28730
|
-
if (
|
|
28983
|
+
const dev = join42(mmaRoot, "src", "cli", "main.ts");
|
|
28984
|
+
if (existsSync48(dev))
|
|
28731
28985
|
return dev;
|
|
28732
|
-
return
|
|
28986
|
+
return join42(mmaRoot, "dist", "main.js");
|
|
28733
28987
|
}
|
|
28734
28988
|
function findMmaRoot(fromDir) {
|
|
28735
|
-
const candidates = [
|
|
28736
|
-
resolve24(fromDir, "..", "..", ".."),
|
|
28737
|
-
resolve24(fromDir, "..")
|
|
28738
|
-
];
|
|
28989
|
+
const candidates = [resolve24(fromDir, "..", "..", ".."), resolve24(fromDir, "..")];
|
|
28739
28990
|
for (const c of candidates) {
|
|
28740
|
-
if (
|
|
28991
|
+
if (existsSync48(join42(c, "package.json")))
|
|
28741
28992
|
return c;
|
|
28742
28993
|
}
|
|
28743
28994
|
return process.cwd();
|
|
@@ -28747,7 +28998,7 @@ function killTree2(child) {
|
|
|
28747
28998
|
if (!pid)
|
|
28748
28999
|
return;
|
|
28749
29000
|
if (platform9() === "win32") {
|
|
28750
|
-
|
|
29001
|
+
spawn8("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
28751
29002
|
windowsHide: true,
|
|
28752
29003
|
stdio: "ignore"
|
|
28753
29004
|
});
|
|
@@ -28762,7 +29013,7 @@ function killTree2(child) {
|
|
|
28762
29013
|
}
|
|
28763
29014
|
}
|
|
28764
29015
|
var defaultRunner2 = (env2, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
|
|
28765
|
-
const child =
|
|
29016
|
+
const child = spawn8(process.execPath, args, {
|
|
28766
29017
|
cwd,
|
|
28767
29018
|
env: env2,
|
|
28768
29019
|
windowsHide: true,
|
|
@@ -28805,13 +29056,13 @@ __export(exports_cli, {
|
|
|
28805
29056
|
});
|
|
28806
29057
|
import { rmSync as rmSync5 } from "fs";
|
|
28807
29058
|
import { homedir as homedir14 } from "os";
|
|
28808
|
-
import { join as
|
|
29059
|
+
import { join as join43, dirname as dirname15 } from "path";
|
|
28809
29060
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
28810
|
-
import { existsSync as
|
|
29061
|
+
import { existsSync as existsSync49, readFileSync as readFileSync30 } from "fs";
|
|
28811
29062
|
function readVersion() {
|
|
28812
|
-
const candidates = [
|
|
29063
|
+
const candidates = [join43(MMA_ROOT, "package.json")];
|
|
28813
29064
|
for (const p of candidates) {
|
|
28814
|
-
if (
|
|
29065
|
+
if (existsSync49(p)) {
|
|
28815
29066
|
try {
|
|
28816
29067
|
const raw = JSON.parse(readFileSync30(p, "utf-8"));
|
|
28817
29068
|
if (raw.version)
|
|
@@ -28849,7 +29100,7 @@ async function certify(opts) {
|
|
|
28849
29100
|
return;
|
|
28850
29101
|
}
|
|
28851
29102
|
console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
|
|
28852
|
-
const sandboxBase =
|
|
29103
|
+
const sandboxBase = join43(process.cwd(), ".mma", "certification");
|
|
28853
29104
|
const results = [];
|
|
28854
29105
|
const total = selected.length;
|
|
28855
29106
|
let idx = 0;
|
|
@@ -28963,7 +29214,7 @@ var init_cli = __esm(() => {
|
|
|
28963
29214
|
init_manifest();
|
|
28964
29215
|
HERE = dirname15(fileURLToPath3(import.meta.url));
|
|
28965
29216
|
MMA_ROOT = findMmaRoot(HERE);
|
|
28966
|
-
USER_SCENARIO_DIR =
|
|
29217
|
+
USER_SCENARIO_DIR = join43(homedir14(), ".mma", "certification", "scenarios");
|
|
28967
29218
|
});
|
|
28968
29219
|
|
|
28969
29220
|
// src/cli/repl-commands.ts
|
|
@@ -28972,18 +29223,15 @@ __export(exports_repl_commands, {
|
|
|
28972
29223
|
registerAllCommands: () => registerAllCommands,
|
|
28973
29224
|
COMMAND_GROUPS: () => COMMAND_GROUPS
|
|
28974
29225
|
});
|
|
28975
|
-
import { join as
|
|
29226
|
+
import { join as join45, dirname as dirname17 } from "path";
|
|
28976
29227
|
import { homedir as homedir16 } from "os";
|
|
28977
|
-
import { existsSync as
|
|
29228
|
+
import { existsSync as existsSync51, readFileSync as readFileSync32 } from "fs";
|
|
28978
29229
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
28979
29230
|
function readVersion3() {
|
|
28980
29231
|
const here = dirname17(fileURLToPath5(import.meta.url));
|
|
28981
|
-
const candidates = [
|
|
28982
|
-
join44(here, "..", "..", "package.json"),
|
|
28983
|
-
join44(here, "..", "package.json")
|
|
28984
|
-
];
|
|
29232
|
+
const candidates = [join45(here, "..", "..", "package.json"), join45(here, "..", "package.json")];
|
|
28985
29233
|
for (const p of candidates) {
|
|
28986
|
-
if (
|
|
29234
|
+
if (existsSync51(p)) {
|
|
28987
29235
|
try {
|
|
28988
29236
|
const raw = JSON.parse(readFileSync32(p, "utf8"));
|
|
28989
29237
|
if (raw.version)
|
|
@@ -29049,7 +29297,7 @@ function registerMmaCommands(ctx) {
|
|
|
29049
29297
|
}
|
|
29050
29298
|
try {
|
|
29051
29299
|
const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
|
|
29052
|
-
const { existsSync:
|
|
29300
|
+
const { existsSync: existsSync52 } = await import("fs");
|
|
29053
29301
|
const { resolve: resolve25 } = await import("path");
|
|
29054
29302
|
let dataUrl;
|
|
29055
29303
|
let label;
|
|
@@ -29069,7 +29317,7 @@ function registerMmaCommands(ctx) {
|
|
|
29069
29317
|
label = source;
|
|
29070
29318
|
} else {
|
|
29071
29319
|
const absPath = resolve25(process.cwd(), source);
|
|
29072
|
-
if (!
|
|
29320
|
+
if (!existsSync52(absPath)) {
|
|
29073
29321
|
console.log(pc2.red(t("image.not_found", { path: source })));
|
|
29074
29322
|
return;
|
|
29075
29323
|
}
|
|
@@ -29148,7 +29396,7 @@ function registerMmaCommands(ctx) {
|
|
|
29148
29396
|
console.log(pc2.yellow(t("repl.wizard_running")));
|
|
29149
29397
|
await ctx.withExclusiveInput(async () => {
|
|
29150
29398
|
const answers = await runSetup(ctx.rl);
|
|
29151
|
-
const configPath =
|
|
29399
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
29152
29400
|
ctx.config.provider.type = answers.provider;
|
|
29153
29401
|
ctx.config.provider.baseUrl = answers.apiBase;
|
|
29154
29402
|
ctx.config.provider.apiKey = answers.apiKey;
|
|
@@ -29202,7 +29450,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
29202
29450
|
return;
|
|
29203
29451
|
}
|
|
29204
29452
|
ctx.config.provider.type = name;
|
|
29205
|
-
const configPath =
|
|
29453
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
29206
29454
|
saveConfig(ctx.config, configPath);
|
|
29207
29455
|
await ctx.agent.reconfigure(ctx.config);
|
|
29208
29456
|
console.log(pc2.green(t("repl.provider_set", { name })));
|
|
@@ -29258,7 +29506,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
29258
29506
|
return;
|
|
29259
29507
|
}
|
|
29260
29508
|
ctx.config.model = name;
|
|
29261
|
-
const configPath =
|
|
29509
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
29262
29510
|
saveConfig(ctx.config, configPath);
|
|
29263
29511
|
await ctx.agent.reconfigure(ctx.config);
|
|
29264
29512
|
console.log(pc2.green(t("repl.model_set", { name })));
|
|
@@ -29283,7 +29531,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
29283
29531
|
return;
|
|
29284
29532
|
}
|
|
29285
29533
|
ctx.config.contextWindow = size;
|
|
29286
|
-
const configPath =
|
|
29534
|
+
const configPath = join45(homedir16(), ".mma", "config.json");
|
|
29287
29535
|
saveConfig(ctx.config, configPath);
|
|
29288
29536
|
await ctx.agent.reconfigure(ctx.config);
|
|
29289
29537
|
console.log(pc2.green(t("cli.context_set", { size })));
|
|
@@ -29302,10 +29550,10 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
29302
29550
|
ctx.agent.shutdown();
|
|
29303
29551
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
29304
29552
|
const { homedir: homedir17 } = await import("os");
|
|
29305
|
-
const { join:
|
|
29553
|
+
const { join: join46 } = await import("path");
|
|
29306
29554
|
const configDir = ctx.configDir;
|
|
29307
29555
|
const baseDir = ctx.baseDir;
|
|
29308
|
-
const projectConfigPath =
|
|
29556
|
+
const projectConfigPath = join46(baseDir, ".mmrc");
|
|
29309
29557
|
const freshConfig = loadConfig2({ configDir, projectConfigPath });
|
|
29310
29558
|
Object.assign(ctx.config, freshConfig);
|
|
29311
29559
|
const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
|
|
@@ -29321,6 +29569,41 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
29321
29569
|
console.log(`${t("repl.provider")} ${ctx.config.provider.type} @ ${ctx.config.provider.baseUrl}`);
|
|
29322
29570
|
}
|
|
29323
29571
|
});
|
|
29572
|
+
ctx.registerCommand({
|
|
29573
|
+
name: "plugins",
|
|
29574
|
+
description: t("repl.plugins"),
|
|
29575
|
+
usage: t("repl.plugins_usage"),
|
|
29576
|
+
action: (args) => {
|
|
29577
|
+
if (!ctx.pluginManager) {
|
|
29578
|
+
console.log(t("cli.plugins.none"));
|
|
29579
|
+
return;
|
|
29580
|
+
}
|
|
29581
|
+
const showAll = args.includes("--all");
|
|
29582
|
+
const infos = ctx.pluginManager.getPluginInfos();
|
|
29583
|
+
const filtered = showAll ? infos : infos.filter(({ plugin: plugin3 }) => !plugin3.isBuiltin);
|
|
29584
|
+
if (filtered.length === 0) {
|
|
29585
|
+
console.log(t("cli.plugins.none"));
|
|
29586
|
+
return;
|
|
29587
|
+
}
|
|
29588
|
+
const mmaVersion = version2;
|
|
29589
|
+
console.log(t("cli.plugins.header", {
|
|
29590
|
+
count: String(filtered.length),
|
|
29591
|
+
mma: mmaVersion
|
|
29592
|
+
}));
|
|
29593
|
+
for (const { plugin: plugin3, source } of filtered) {
|
|
29594
|
+
const v = plugin3.version || "-";
|
|
29595
|
+
const origin = source || "builtin";
|
|
29596
|
+
const mark = plugin3.isBuiltin ? t("cli.plugins.builtin_mark") : " ";
|
|
29597
|
+
console.log(` ${mark} ${plugin3.name} v${v} [${origin}]`);
|
|
29598
|
+
}
|
|
29599
|
+
if (!showAll) {
|
|
29600
|
+
const builtinCount = infos.filter(({ plugin: plugin3 }) => plugin3.isBuiltin).length;
|
|
29601
|
+
if (builtinCount > 0) {
|
|
29602
|
+
console.log(pc2.dim(` (${builtinCount} builtin hidden — /plugins --all to show)`));
|
|
29603
|
+
}
|
|
29604
|
+
}
|
|
29605
|
+
}
|
|
29606
|
+
});
|
|
29324
29607
|
}
|
|
29325
29608
|
function registerSessionCommands(ctx) {
|
|
29326
29609
|
if (!ctx.sessionManager)
|
|
@@ -29580,7 +29863,8 @@ var init_repl_commands = __esm(() => {
|
|
|
29580
29863
|
resume: "session",
|
|
29581
29864
|
rename: "session",
|
|
29582
29865
|
delete: "session",
|
|
29583
|
-
skill: "skill"
|
|
29866
|
+
skill: "skill",
|
|
29867
|
+
plugins: "agent"
|
|
29584
29868
|
};
|
|
29585
29869
|
});
|
|
29586
29870
|
|
|
@@ -29605,14 +29889,14 @@ init_bootstrap();
|
|
|
29605
29889
|
init_config2();
|
|
29606
29890
|
init_setup();
|
|
29607
29891
|
init_i18n();
|
|
29608
|
-
import { join as
|
|
29892
|
+
import { join as join44, dirname as dirname16 } from "path";
|
|
29609
29893
|
import { homedir as homedir15 } from "os";
|
|
29610
|
-
import { existsSync as
|
|
29894
|
+
import { existsSync as existsSync50, readFileSync as readFileSync31 } from "fs";
|
|
29611
29895
|
|
|
29612
29896
|
// src/cli/security-commands.ts
|
|
29613
29897
|
init_bootstrap();
|
|
29614
29898
|
init_config2();
|
|
29615
|
-
import { join as
|
|
29899
|
+
import { join as join38 } from "path";
|
|
29616
29900
|
import { homedir as homedir12 } from "os";
|
|
29617
29901
|
|
|
29618
29902
|
// src/modules/security/security-policies.ts
|
|
@@ -29684,18 +29968,7 @@ var STRICT_POLICY = {
|
|
|
29684
29968
|
"-R",
|
|
29685
29969
|
"--no-clobber"
|
|
29686
29970
|
],
|
|
29687
|
-
dangerousOperators: [
|
|
29688
|
-
">",
|
|
29689
|
-
">>",
|
|
29690
|
-
"2>",
|
|
29691
|
-
"2>>",
|
|
29692
|
-
"|",
|
|
29693
|
-
"&&",
|
|
29694
|
-
"||",
|
|
29695
|
-
";",
|
|
29696
|
-
"&",
|
|
29697
|
-
"`"
|
|
29698
|
-
],
|
|
29971
|
+
dangerousOperators: [">", ">>", "2>", "2>>", "|", "&&", "||", ";", "&", "`"],
|
|
29699
29972
|
logCommands: true
|
|
29700
29973
|
},
|
|
29701
29974
|
paths: {
|
|
@@ -29909,12 +30182,7 @@ var BALANCED_POLICY = {
|
|
|
29909
30182
|
auditNotifier: {
|
|
29910
30183
|
enabled: false,
|
|
29911
30184
|
minSeverity: "medium",
|
|
29912
|
-
eventTypes: [
|
|
29913
|
-
"security_block",
|
|
29914
|
-
"bash_command",
|
|
29915
|
-
"file_operation",
|
|
29916
|
-
"network_request"
|
|
29917
|
-
],
|
|
30185
|
+
eventTypes: ["security_block", "bash_command", "file_operation", "network_request"],
|
|
29918
30186
|
maxRetries: 3
|
|
29919
30187
|
}
|
|
29920
30188
|
}
|
|
@@ -30142,7 +30410,7 @@ function createSecurityCommand(program2) {
|
|
|
30142
30410
|
}
|
|
30143
30411
|
});
|
|
30144
30412
|
securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
|
|
30145
|
-
const configPath =
|
|
30413
|
+
const configPath = join38(homedir12(), ".mma", "config.json");
|
|
30146
30414
|
const { config: appConfig } = await bootstrap();
|
|
30147
30415
|
const validPresets = ["strict", "balanced", "permissive"];
|
|
30148
30416
|
if (!validPresets.includes(preset)) {
|
|
@@ -30157,7 +30425,7 @@ function createSecurityCommand(program2) {
|
|
|
30157
30425
|
console.log(t("cli.security.policy_description", { description: policy.description }));
|
|
30158
30426
|
});
|
|
30159
30427
|
securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
|
|
30160
|
-
const configPath =
|
|
30428
|
+
const configPath = join38(homedir12(), ".mma", "config.json");
|
|
30161
30429
|
const { config: appConfig } = await bootstrap();
|
|
30162
30430
|
appConfig.security = appConfig.security || {};
|
|
30163
30431
|
appConfig.security.sessionEncryption = {
|
|
@@ -30169,7 +30437,7 @@ function createSecurityCommand(program2) {
|
|
|
30169
30437
|
console.log(t("cli.security.encryption_enabled"));
|
|
30170
30438
|
});
|
|
30171
30439
|
securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
|
|
30172
|
-
const configPath =
|
|
30440
|
+
const configPath = join38(homedir12(), ".mma", "config.json");
|
|
30173
30441
|
const { config: appConfig } = await bootstrap();
|
|
30174
30442
|
appConfig.security = appConfig.security || {};
|
|
30175
30443
|
appConfig.security.sessionEncryption = {
|
|
@@ -30181,7 +30449,7 @@ function createSecurityCommand(program2) {
|
|
|
30181
30449
|
console.log(t("cli.security.encryption_disabled"));
|
|
30182
30450
|
});
|
|
30183
30451
|
securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
|
|
30184
|
-
const configPath =
|
|
30452
|
+
const configPath = join38(homedir12(), ".mma", "config.json");
|
|
30185
30453
|
const { config: appConfig } = await bootstrap();
|
|
30186
30454
|
appConfig.security = appConfig.security || {};
|
|
30187
30455
|
appConfig.security.auditNotifier = {
|
|
@@ -30195,7 +30463,7 @@ function createSecurityCommand(program2) {
|
|
|
30195
30463
|
console.log(t("cli.security.audit_enabled"));
|
|
30196
30464
|
});
|
|
30197
30465
|
securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
|
|
30198
|
-
const configPath =
|
|
30466
|
+
const configPath = join38(homedir12(), ".mma", "config.json");
|
|
30199
30467
|
const { config: appConfig } = await bootstrap();
|
|
30200
30468
|
appConfig.security = appConfig.security || {};
|
|
30201
30469
|
appConfig.security.auditNotifier = {
|
|
@@ -30261,12 +30529,9 @@ function createPluginCommand(program2) {
|
|
|
30261
30529
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
30262
30530
|
function readVersion2() {
|
|
30263
30531
|
const here = dirname16(fileURLToPath4(import.meta.url));
|
|
30264
|
-
const candidates = [
|
|
30265
|
-
join43(here, "..", "..", "package.json"),
|
|
30266
|
-
join43(here, "..", "package.json")
|
|
30267
|
-
];
|
|
30532
|
+
const candidates = [join44(here, "..", "..", "package.json"), join44(here, "..", "package.json")];
|
|
30268
30533
|
for (const p of candidates) {
|
|
30269
|
-
if (
|
|
30534
|
+
if (existsSync50(p)) {
|
|
30270
30535
|
try {
|
|
30271
30536
|
const raw = JSON.parse(readFileSync31(p, "utf8"));
|
|
30272
30537
|
if (raw.version)
|
|
@@ -30281,7 +30546,7 @@ function createProgram() {
|
|
|
30281
30546
|
const program2 = new Command().name("mma").description(t("cli.description")).version(version).option("--no-agents-md", t("cli.no_agents_md")).option("-d, --dir <path>", t("cli.dir")).option("-e, --exit-on-complete", t("cli.exit_on_complete")).option("-j, --json", t("cli.json"));
|
|
30282
30547
|
program2.command("init").description(t("cli.init")).action(async () => {
|
|
30283
30548
|
const answers = await runSetup();
|
|
30284
|
-
const configPath =
|
|
30549
|
+
const configPath = join44(homedir15(), ".mma", "config.json");
|
|
30285
30550
|
const { config } = await bootstrap();
|
|
30286
30551
|
config.provider.type = answers.provider;
|
|
30287
30552
|
config.provider.baseUrl = answers.apiBase;
|
|
@@ -30326,7 +30591,7 @@ function createProgram() {
|
|
|
30326
30591
|
});
|
|
30327
30592
|
const configCmd = program2.command("config").description(t("cli.manage_config"));
|
|
30328
30593
|
configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
|
|
30329
|
-
const configPath =
|
|
30594
|
+
const configPath = join44(homedir15(), ".mma", "config.json");
|
|
30330
30595
|
const { config } = await bootstrap();
|
|
30331
30596
|
const keys = key.split(".");
|
|
30332
30597
|
let obj = config;
|
|
@@ -30389,7 +30654,7 @@ function createProgram() {
|
|
|
30389
30654
|
console.log(t("cli.model_hint"));
|
|
30390
30655
|
});
|
|
30391
30656
|
model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
|
|
30392
|
-
const configPath =
|
|
30657
|
+
const configPath = join44(homedir15(), ".mma", "config.json");
|
|
30393
30658
|
const { config } = await bootstrap();
|
|
30394
30659
|
config.model = name;
|
|
30395
30660
|
saveConfig(config, configPath);
|
|
@@ -30425,7 +30690,7 @@ function createProgram() {
|
|
|
30425
30690
|
await uncertify2(name, config);
|
|
30426
30691
|
});
|
|
30427
30692
|
program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
|
|
30428
|
-
const configPath =
|
|
30693
|
+
const configPath = join44(homedir15(), ".mma", "config.json");
|
|
30429
30694
|
const { config } = await bootstrap();
|
|
30430
30695
|
const contextWindow = parseInt(size, 10);
|
|
30431
30696
|
if (isNaN(contextWindow) || contextWindow < 1024) {
|
|
@@ -30443,7 +30708,7 @@ function createProgram() {
|
|
|
30443
30708
|
console.log(t("cli.base_url"), config.provider.baseUrl);
|
|
30444
30709
|
});
|
|
30445
30710
|
provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
|
|
30446
|
-
const configPath =
|
|
30711
|
+
const configPath = join44(homedir15(), ".mma", "config.json");
|
|
30447
30712
|
const { config } = await bootstrap();
|
|
30448
30713
|
config.provider.type = name;
|
|
30449
30714
|
saveConfig(config, configPath);
|
|
@@ -31251,8 +31516,8 @@ class LineEditor {
|
|
|
31251
31516
|
}
|
|
31252
31517
|
|
|
31253
31518
|
// src/cli/repl.ts
|
|
31254
|
-
import { existsSync as
|
|
31255
|
-
import { join as
|
|
31519
|
+
import { existsSync as existsSync52, readFileSync as readFileSync33, writeFileSync as writeFileSync17 } from "fs";
|
|
31520
|
+
import { join as join46, dirname as dirname18 } from "path";
|
|
31256
31521
|
import { homedir as homedir17 } from "os";
|
|
31257
31522
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
31258
31523
|
|
|
@@ -31757,12 +32022,9 @@ init_i18n();
|
|
|
31757
32022
|
init_repl_commands();
|
|
31758
32023
|
function readVersion4() {
|
|
31759
32024
|
const here = dirname18(fileURLToPath6(import.meta.url));
|
|
31760
|
-
const candidates = [
|
|
31761
|
-
join45(here, "..", "..", "package.json"),
|
|
31762
|
-
join45(here, "..", "package.json")
|
|
31763
|
-
];
|
|
32025
|
+
const candidates = [join46(here, "..", "..", "package.json"), join46(here, "..", "package.json")];
|
|
31764
32026
|
for (const p of candidates) {
|
|
31765
|
-
if (
|
|
32027
|
+
if (existsSync52(p)) {
|
|
31766
32028
|
try {
|
|
31767
32029
|
const raw = JSON.parse(readFileSync33(p, "utf8"));
|
|
31768
32030
|
if (raw.version)
|
|
@@ -31820,10 +32082,10 @@ class Repl {
|
|
|
31820
32082
|
this.skillsModule = skillsModule;
|
|
31821
32083
|
this.pluginManager = pluginManager;
|
|
31822
32084
|
this.logger = logger;
|
|
31823
|
-
this.configDir = configDir ||
|
|
32085
|
+
this.configDir = configDir || join46(homedir17(), ".mma");
|
|
31824
32086
|
this.baseDir = baseDir || process.cwd();
|
|
31825
32087
|
this.noAgentsMd = noAgentsMd === true;
|
|
31826
|
-
this.historyPath =
|
|
32088
|
+
this.historyPath = join46(homedir17(), ".mma", "repl-history");
|
|
31827
32089
|
this.loadHistory();
|
|
31828
32090
|
this.rl = process.stdin.isTTY ? new LineEditor({
|
|
31829
32091
|
input: process.stdin,
|
|
@@ -31856,7 +32118,7 @@ class Repl {
|
|
|
31856
32118
|
this.setupListeners();
|
|
31857
32119
|
}
|
|
31858
32120
|
loadHistory() {
|
|
31859
|
-
if (
|
|
32121
|
+
if (existsSync52(this.historyPath)) {
|
|
31860
32122
|
try {
|
|
31861
32123
|
const raw = readFileSync33(this.historyPath, "utf-8");
|
|
31862
32124
|
this.history = raw.split(`
|
|
@@ -31878,13 +32140,7 @@ class Repl {
|
|
|
31878
32140
|
this.completer.registerProvider(new SessionNameProvider(() => this.sessionManager.list().map((s) => s.name)));
|
|
31879
32141
|
}
|
|
31880
32142
|
if (this.skillsModule) {
|
|
31881
|
-
this.completer.registerProvider(new SubcommandProvider("skill", [
|
|
31882
|
-
"list",
|
|
31883
|
-
"loaded",
|
|
31884
|
-
"load",
|
|
31885
|
-
"unload",
|
|
31886
|
-
"search"
|
|
31887
|
-
]));
|
|
32143
|
+
this.completer.registerProvider(new SubcommandProvider("skill", ["list", "loaded", "load", "unload", "search"]));
|
|
31888
32144
|
this.completer.registerProvider(new SkillNameProvider(this.skillsModule));
|
|
31889
32145
|
}
|
|
31890
32146
|
}
|
|
@@ -32219,11 +32475,11 @@ ${t("image.clipboard_empty")}`));
|
|
|
32219
32475
|
row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
|
|
32220
32476
|
} else {
|
|
32221
32477
|
const agentsMdCandidates = [
|
|
32222
|
-
|
|
32223
|
-
|
|
32224
|
-
|
|
32478
|
+
join46(this.baseDir, "AGENTS.md"),
|
|
32479
|
+
join46(this.baseDir, ".mma", "AGENTS.md"),
|
|
32480
|
+
join46(this.configDir, "AGENTS.md")
|
|
32225
32481
|
];
|
|
32226
|
-
const foundAgents = agentsMdCandidates.filter((p) =>
|
|
32482
|
+
const foundAgents = agentsMdCandidates.filter((p) => existsSync52(p));
|
|
32227
32483
|
if (foundAgents.length > 0) {
|
|
32228
32484
|
for (const p of foundAgents) {
|
|
32229
32485
|
row(t("repl.agents_label"), pc2.dim(p));
|
|
@@ -32234,7 +32490,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
32234
32490
|
}
|
|
32235
32491
|
const meta = this.sessionManager?.getActiveMeta();
|
|
32236
32492
|
if (meta) {
|
|
32237
|
-
const sessionPath =
|
|
32493
|
+
const sessionPath = join46(this.configDir, "sessions", meta.id);
|
|
32238
32494
|
row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
|
|
32239
32495
|
}
|
|
32240
32496
|
const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
|
|
@@ -32275,8 +32531,8 @@ init_setup();
|
|
|
32275
32531
|
init_config2();
|
|
32276
32532
|
init_i18n();
|
|
32277
32533
|
init_colors();
|
|
32278
|
-
import { existsSync as
|
|
32279
|
-
import { join as
|
|
32534
|
+
import { existsSync as existsSync53, readFileSync as readFileSync34 } from "fs";
|
|
32535
|
+
import { join as join47, dirname as dirname19 } from "path";
|
|
32280
32536
|
import { homedir as homedir18 } from "os";
|
|
32281
32537
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
32282
32538
|
|
|
@@ -32380,12 +32636,9 @@ class UpdaterModule {
|
|
|
32380
32636
|
// src/cli/main.ts
|
|
32381
32637
|
function readVersion5() {
|
|
32382
32638
|
const here = dirname19(fileURLToPath7(import.meta.url));
|
|
32383
|
-
const candidates = [
|
|
32384
|
-
join46(here, "..", "..", "package.json"),
|
|
32385
|
-
join46(here, "..", "package.json")
|
|
32386
|
-
];
|
|
32639
|
+
const candidates = [join47(here, "..", "..", "package.json"), join47(here, "..", "package.json")];
|
|
32387
32640
|
for (const p of candidates) {
|
|
32388
|
-
if (
|
|
32641
|
+
if (existsSync53(p)) {
|
|
32389
32642
|
try {
|
|
32390
32643
|
const raw = JSON.parse(readFileSync34(p, "utf8"));
|
|
32391
32644
|
if (raw.version)
|
|
@@ -32470,15 +32723,15 @@ async function main() {
|
|
|
32470
32723
|
await updater?.waitForIdle();
|
|
32471
32724
|
process.exit(exitCode);
|
|
32472
32725
|
} else {
|
|
32473
|
-
const configPath =
|
|
32474
|
-
if (!
|
|
32726
|
+
const configPath = join47(homedir18(), ".mma", "config.json");
|
|
32727
|
+
if (!existsSync53(configPath)) {
|
|
32475
32728
|
console.log(pc2.yellow(`
|
|
32476
32729
|
` + t("cli.first_run") + `
|
|
32477
32730
|
`));
|
|
32478
32731
|
const answers = await runSetup();
|
|
32479
32732
|
const config2 = loadConfig({
|
|
32480
|
-
configDir:
|
|
32481
|
-
projectConfigPath: projectDir ?
|
|
32733
|
+
configDir: join47(homedir18(), ".mma"),
|
|
32734
|
+
projectConfigPath: projectDir ? join47(projectDir, ".mmrc") : join47(process.cwd(), ".mmrc")
|
|
32482
32735
|
});
|
|
32483
32736
|
config2.provider.type = answers.provider;
|
|
32484
32737
|
config2.provider.baseUrl = answers.apiBase;
|