micro-models-agent 0.33.2 → 0.33.3
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/dist/main.js +377 -156
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2472,6 +2472,8 @@ Command: {command}`,
|
|
|
2472
2472
|
"todo.added": "Added {count} todo(s): {items}",
|
|
2473
2473
|
"todo.marked_done": "Marked {count} item(s) as done",
|
|
2474
2474
|
"todo.no_active": "No active todos",
|
|
2475
|
+
"todo.no_items": "No todo items specified — provide items to mark done",
|
|
2476
|
+
"todo.subtask_not_found": "No matching sub-task(s) found for: {items}",
|
|
2475
2477
|
"todo.unknown_action": "Unknown todo action: {action}",
|
|
2476
2478
|
"todo.acknowledged": "Todo acknowledged",
|
|
2477
2479
|
"verify.passed": "Verification passed",
|
|
@@ -2740,6 +2742,8 @@ Use this knowledge to answer the user's question.`,
|
|
|
2740
2742
|
"exec.tool_errors_recovery": "Tool {tool} has failed {count} times in a row. Try an alternative: create files directly via write_file, use a different command, or if nothing works — skip this step via plan update step=N status=skipped with a note explaining why.",
|
|
2741
2743
|
"exec.repetitive_tool": "Called {tool} {count} times with identical arguments and result. Try a different approach — create files directly, change arguments, or check process status via process_log.",
|
|
2742
2744
|
"exec.consecutive_failures_recovery": "{count} consecutive tool failures. Create files directly via write_file instead of terminal commands. Check that dependencies are installed (npm install). Do not run build/tests until all files are created.",
|
|
2745
|
+
"exec.read_only_loop": "No write/exec for {count} tool calls — the agent is only reading/exploring.",
|
|
2746
|
+
"exec.read_only_loop_recovery": "{count} consecutive read-only tool calls (read_file/glob/grep/browser) with no writes. STOP exploring and make the edit the task requires: read the file, then call write_file or edit_file. If you cannot finish the task, ask the user instead of re-reading the same files.",
|
|
2743
2747
|
"exec.plan_warning": 'Current plan step {step} is "{description}", but {tool} is being called for files outside this step. Complete the current step first, then call plan update step={step} status=done before moving to the next step.',
|
|
2744
2748
|
"exec.plan_blocked": "{max} consecutive calls outside the current step. Finish step {step} before proceeding — other steps should wait until this one is complete.",
|
|
2745
2749
|
"exec.off_track": 'Step {stepId} — "{description}" — but you are using {tool} on a different path. Return to the current step.',
|
|
@@ -3050,6 +3054,8 @@ var init_ru = __esm(() => {
|
|
|
3050
3054
|
"todo.added": "Добавлено {count} задач: {items}",
|
|
3051
3055
|
"todo.marked_done": "Отмечено выполненными: {count}",
|
|
3052
3056
|
"todo.no_active": "Нет активных задач",
|
|
3057
|
+
"todo.no_items": "Не указаны подзадачи — укажите items для отметки выполненными",
|
|
3058
|
+
"todo.subtask_not_found": "Подзадачи не найдены: {items}",
|
|
3053
3059
|
"todo.unknown_action": "Неизвестное действие todo: {action}",
|
|
3054
3060
|
"todo.acknowledged": "Todo принято",
|
|
3055
3061
|
"verify.passed": "Проверка пройдена",
|
|
@@ -3318,6 +3324,8 @@ var init_ru = __esm(() => {
|
|
|
3318
3324
|
"exec.tool_errors_recovery": "Инструмент {tool} упал {count} раз подряд. Попробуйте альтернативу: создайте файлы напрямую через write_file, используйте другую команду, или пропустите этот шаг через plan update step=N status=skipped с пометкой почему.",
|
|
3319
3325
|
"exec.repetitive_tool": "Инструмент {tool} вызван {count} раз с одинаковыми аргументами и результатом. Попробуйте другой подход — создайте файлы напрямую, измените аргументы или проверьте статус процесса через process_log.",
|
|
3320
3326
|
"exec.consecutive_failures_recovery": "{count} инструментов подряд упали. Создавайте файлы напрямую через write_file вместо команд терминала. Проверьте что зависимости установлены (npm install). Не запускайте сборку/тесты пока не созданы все файлы.",
|
|
3327
|
+
"exec.read_only_loop": "Нет записи/выполнения за {count} вызовов — агент только читает/исследует.",
|
|
3328
|
+
"exec.read_only_loop_recovery": "{count} вызовов только для чтения подряд (read_file/glob/grep/browser) без записи. Хватит исследовать — внесите правку, которую требует задача: прочитайте файл, затем вызовите write_file или edit_file. Если не можете завершить задачу — спросите пользователя, а не перечитывайте одни и те же файлы.",
|
|
3321
3329
|
"exec.plan_warning": 'Текущий шаг плана {step} — "{description}", но вызывается {tool} для файлов вне этого шага. Завершите текущий шаг, вызовите plan update step={step} status=done, затем переходите к следующему.',
|
|
3322
3330
|
"exec.plan_blocked": "{max} вызовов подряд вне текущего шага. Завершите шаг {step} — остальные шаги ждут пока этот не будет выполнен.",
|
|
3323
3331
|
"exec.off_track": 'Шаг {stepId} — "{description}", но используется {tool} для другого пути. Вернитесь к текущему шагу.',
|
|
@@ -6018,20 +6026,16 @@ function safeResolvePath(baseDir, userPath) {
|
|
|
6018
6026
|
}
|
|
6019
6027
|
var init_path_utils = () => {};
|
|
6020
6028
|
|
|
6021
|
-
// src/tools/preview.ts
|
|
6022
|
-
var MAX_PREVIEW_LINES = 15;
|
|
6023
|
-
|
|
6024
6029
|
// src/tools/read-file.ts
|
|
6025
6030
|
import { readFileSync as readFileSync5, existsSync as existsSync10 } from "fs";
|
|
6026
6031
|
import { extname } from "path";
|
|
6027
|
-
var DEFAULT_LIMIT, readFileTool;
|
|
6032
|
+
var DEFAULT_LIMIT = 300, readFileTool;
|
|
6028
6033
|
var init_read_file = __esm(() => {
|
|
6029
6034
|
init_i18n();
|
|
6030
6035
|
init_path_validator();
|
|
6031
6036
|
init_security();
|
|
6032
6037
|
init_audit_log();
|
|
6033
6038
|
init_path_utils();
|
|
6034
|
-
DEFAULT_LIMIT = MAX_PREVIEW_LINES;
|
|
6035
6039
|
readFileTool = {
|
|
6036
6040
|
name: "read_file",
|
|
6037
6041
|
description: `Read a file from the filesystem. Reads up to ${DEFAULT_LIMIT} lines at a time by default; use offset to page through large files.`,
|
|
@@ -6540,6 +6544,9 @@ var init_edit_file = __esm(() => {
|
|
|
6540
6544
|
};
|
|
6541
6545
|
});
|
|
6542
6546
|
|
|
6547
|
+
// src/tools/preview.ts
|
|
6548
|
+
var MAX_PREVIEW_LINES = 15;
|
|
6549
|
+
|
|
6543
6550
|
// src/tools/glob-tool.ts
|
|
6544
6551
|
import { globSync } from "fs";
|
|
6545
6552
|
var globTool;
|
|
@@ -9197,6 +9204,7 @@ class StuckDetector {
|
|
|
9197
9204
|
lastBashCommand = "";
|
|
9198
9205
|
lastBashOutput = "";
|
|
9199
9206
|
emptyBashRunCount = 0;
|
|
9207
|
+
readOnlyStreak = 0;
|
|
9200
9208
|
constructor(threshold = 6, errorThreshold = 3) {
|
|
9201
9209
|
this.threshold = threshold;
|
|
9202
9210
|
this.errorThreshold = errorThreshold;
|
|
@@ -9214,6 +9222,14 @@ class StuckDetector {
|
|
|
9214
9222
|
if (this.recentToolCalls.length > this.maxRecentCalls) {
|
|
9215
9223
|
this.recentToolCalls.shift();
|
|
9216
9224
|
}
|
|
9225
|
+
if (READ_ONLY_TOOLS.has(name)) {
|
|
9226
|
+
this.readOnlyStreak++;
|
|
9227
|
+
} else {
|
|
9228
|
+
this.readOnlyStreak = 0;
|
|
9229
|
+
}
|
|
9230
|
+
}
|
|
9231
|
+
hasReadOnlyLoop() {
|
|
9232
|
+
return this.readOnlyStreak >= READ_ONLY_LOOP_THRESHOLD;
|
|
9217
9233
|
}
|
|
9218
9234
|
recordToolError(toolName, output) {
|
|
9219
9235
|
this.toolErrors.set(toolName, (this.toolErrors.get(toolName) || 0) + 1);
|
|
@@ -9331,6 +9347,9 @@ class StuckDetector {
|
|
|
9331
9347
|
if (this.hasConsecutiveFailures()) {
|
|
9332
9348
|
hints.push("Multiple different tools are failing. Check if the environment is set up correctly.");
|
|
9333
9349
|
}
|
|
9350
|
+
if (this.hasReadOnlyLoop()) {
|
|
9351
|
+
hints.push("You have made many read-only tool calls (read_file/glob/grep/browser) without writing anything. Stop exploring — make the edit/write the task needs, or use the plan tool to decide next steps.");
|
|
9352
|
+
}
|
|
9334
9353
|
return hints;
|
|
9335
9354
|
}
|
|
9336
9355
|
getActionableHints() {
|
|
@@ -9446,6 +9465,11 @@ class StuckDetector {
|
|
|
9446
9465
|
if (errorTool) {
|
|
9447
9466
|
return t("exec.tool_errors", { tool: errorTool[0], count: errorTool[1] });
|
|
9448
9467
|
}
|
|
9468
|
+
if (this.hasReadOnlyLoop()) {
|
|
9469
|
+
return t("exec.read_only_loop", {
|
|
9470
|
+
count: String(this.readOnlyStreak)
|
|
9471
|
+
});
|
|
9472
|
+
}
|
|
9449
9473
|
return "";
|
|
9450
9474
|
}
|
|
9451
9475
|
getRecoveryMessage() {
|
|
@@ -9471,6 +9495,11 @@ class StuckDetector {
|
|
|
9471
9495
|
if (this.hasRepetitiveToolCalls()) {
|
|
9472
9496
|
return this.getRepetitiveToolMessage();
|
|
9473
9497
|
}
|
|
9498
|
+
if (this.hasReadOnlyLoop()) {
|
|
9499
|
+
return t("exec.read_only_loop_recovery", {
|
|
9500
|
+
count: String(this.readOnlyStreak)
|
|
9501
|
+
});
|
|
9502
|
+
}
|
|
9474
9503
|
return "";
|
|
9475
9504
|
}
|
|
9476
9505
|
reset() {
|
|
@@ -9486,6 +9515,20 @@ class StuckDetector {
|
|
|
9486
9515
|
this.lastBashCommand = "";
|
|
9487
9516
|
this.lastBashOutput = "";
|
|
9488
9517
|
this.emptyBashRunCount = 0;
|
|
9518
|
+
this.readOnlyStreak = 0;
|
|
9519
|
+
}
|
|
9520
|
+
resetStepProgress() {
|
|
9521
|
+
this.currentStepId = null;
|
|
9522
|
+
this.iterationsOnCurrentStep = 0;
|
|
9523
|
+
this.toolErrors.clear();
|
|
9524
|
+
this.consecutiveFailures = 0;
|
|
9525
|
+
this.lastFailedTool = "";
|
|
9526
|
+
this.lastErrorOutput = "";
|
|
9527
|
+
this.fileRewriteCount.clear();
|
|
9528
|
+
this.escalationCount = 0;
|
|
9529
|
+
this.lastBashCommand = "";
|
|
9530
|
+
this.lastBashOutput = "";
|
|
9531
|
+
this.emptyBashRunCount = 0;
|
|
9489
9532
|
}
|
|
9490
9533
|
resetStepState(stepId) {
|
|
9491
9534
|
this.currentStepId = stepId;
|
|
@@ -9499,10 +9542,33 @@ class StuckDetector {
|
|
|
9499
9542
|
this.lastBashCommand = "";
|
|
9500
9543
|
this.lastBashOutput = "";
|
|
9501
9544
|
this.emptyBashRunCount = 0;
|
|
9545
|
+
this.readOnlyStreak = 0;
|
|
9502
9546
|
}
|
|
9503
9547
|
}
|
|
9548
|
+
var READ_ONLY_TOOLS, READ_ONLY_LOOP_THRESHOLD = 10;
|
|
9504
9549
|
var init_stuck_detector = __esm(() => {
|
|
9505
9550
|
init_i18n();
|
|
9551
|
+
READ_ONLY_TOOLS = new Set([
|
|
9552
|
+
"read_file",
|
|
9553
|
+
"glob",
|
|
9554
|
+
"grep",
|
|
9555
|
+
"list_dir",
|
|
9556
|
+
"file_info",
|
|
9557
|
+
"browser",
|
|
9558
|
+
"web_search",
|
|
9559
|
+
"web_fetch",
|
|
9560
|
+
"web_browse",
|
|
9561
|
+
"search_history",
|
|
9562
|
+
"recall",
|
|
9563
|
+
"project_map",
|
|
9564
|
+
"chunk_query",
|
|
9565
|
+
"process_list",
|
|
9566
|
+
"process_log",
|
|
9567
|
+
"plan",
|
|
9568
|
+
"todo",
|
|
9569
|
+
"verify",
|
|
9570
|
+
"load_skill"
|
|
9571
|
+
]);
|
|
9506
9572
|
});
|
|
9507
9573
|
|
|
9508
9574
|
// src/modules/artifacts/store.ts
|
|
@@ -10408,6 +10474,9 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
10408
10474
|
}).catch(() => {});
|
|
10409
10475
|
}
|
|
10410
10476
|
}
|
|
10477
|
+
if (typeof contextManager.resetUserTurn === "function") {
|
|
10478
|
+
contextManager.resetUserTurn();
|
|
10479
|
+
}
|
|
10411
10480
|
contextManager.addMessage({ role: "user", content: input });
|
|
10412
10481
|
slog.logUser(input);
|
|
10413
10482
|
if (config.moe?.enabled) {
|
|
@@ -10447,6 +10516,9 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
10447
10516
|
const MAX_HALLUCINATION_RETRIES = 3;
|
|
10448
10517
|
let consecutiveToolFailures = 0;
|
|
10449
10518
|
const MAX_CONSECUTIVE_TOOL_FAILURES = 5;
|
|
10519
|
+
const toolFailureCounts = new Map;
|
|
10520
|
+
const memoryRuleRecorded = new Set;
|
|
10521
|
+
const MIN_REPEATED_TOOL_FAILURES = 3;
|
|
10450
10522
|
let auditRetries = 0;
|
|
10451
10523
|
const MAX_AUDIT_RETRIES = 3;
|
|
10452
10524
|
let emptyResponseRetries = 0;
|
|
@@ -10686,6 +10758,25 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
10686
10758
|
contextManager.compact();
|
|
10687
10759
|
logger.debug("Context compacted after tool result");
|
|
10688
10760
|
}
|
|
10761
|
+
if (!result.success) {
|
|
10762
|
+
const key = call.name;
|
|
10763
|
+
const prev = toolFailureCounts.get(key) ?? { count: 0, error: "" };
|
|
10764
|
+
prev.count++;
|
|
10765
|
+
prev.error = String(result.output ?? "").slice(0, 200);
|
|
10766
|
+
toolFailureCounts.set(key, prev);
|
|
10767
|
+
if (prev.count >= MIN_REPEATED_TOOL_FAILURES && !memoryRuleRecorded.has(key)) {
|
|
10768
|
+
memoryRuleRecorded.add(key);
|
|
10769
|
+
if (sessionManager) {
|
|
10770
|
+
const activeSession = sessionManager.getActiveMeta();
|
|
10771
|
+
if (activeSession) {
|
|
10772
|
+
const memDir = join12(baseDir, ".mma", "memory");
|
|
10773
|
+
const memStore = new MemoryStore(memDir);
|
|
10774
|
+
memStore.appendRule("errors", `Tool ${key} failed ${prev.count}x (${prev.error})`, `Repeated ${key} failures suggest a systemic problem (config, environment, or a broken tool), not a one-off`, "Check the error message, verify the tool's dependencies are installed/configured, and consider a different tool");
|
|
10775
|
+
logger.warn(`Recorded repeated ${key} failures to memory (${prev.count}x)`);
|
|
10776
|
+
}
|
|
10777
|
+
}
|
|
10778
|
+
}
|
|
10779
|
+
}
|
|
10689
10780
|
}
|
|
10690
10781
|
if (anyToolFailed) {
|
|
10691
10782
|
consecutiveToolFailures++;
|
|
@@ -11026,6 +11117,7 @@ class ContextManager {
|
|
|
11026
11117
|
fileFacts = [];
|
|
11027
11118
|
decisionFacts = [];
|
|
11028
11119
|
errorFacts = [];
|
|
11120
|
+
lastUserTask = "";
|
|
11029
11121
|
static MAX_FACTS = 20;
|
|
11030
11122
|
tokenCounter;
|
|
11031
11123
|
pendingImageParts = [];
|
|
@@ -11062,6 +11154,10 @@ class ContextManager {
|
|
|
11062
11154
|
noteIteration() {
|
|
11063
11155
|
this.iterationsSinceCompaction++;
|
|
11064
11156
|
}
|
|
11157
|
+
resetUserTurn() {
|
|
11158
|
+
this.iterationsSinceCompaction = 0;
|
|
11159
|
+
this.lastUserTask = "";
|
|
11160
|
+
}
|
|
11065
11161
|
getQuality() {
|
|
11066
11162
|
const usedTokens = this.getEstimatedTokens();
|
|
11067
11163
|
const tokenLoad = Math.max(0, 1 - usedTokens / this.budget.history);
|
|
@@ -11074,6 +11170,12 @@ class ContextManager {
|
|
|
11074
11170
|
return Math.round(Math.min(100, Math.max(0, score * 100)));
|
|
11075
11171
|
}
|
|
11076
11172
|
addMessage(msg) {
|
|
11173
|
+
if (msg.role === "user" && !this.lastUserTask) {
|
|
11174
|
+
const text = typeof msg.content === "string" ? msg.content : getMessageText(msg.content);
|
|
11175
|
+
if (text.trim() && !text.startsWith("<system-summary>") && !text.includes("[Compressed:")) {
|
|
11176
|
+
this.lastUserTask = text.trim();
|
|
11177
|
+
}
|
|
11178
|
+
}
|
|
11077
11179
|
if (msg.role === "user" && this.pendingImageParts.length > 0) {
|
|
11078
11180
|
const textPart = {
|
|
11079
11181
|
type: "text",
|
|
@@ -11163,6 +11265,10 @@ class ContextManager {
|
|
|
11163
11265
|
this.extractFacts(oldTurns);
|
|
11164
11266
|
const parts = [];
|
|
11165
11267
|
parts.push(`[Compressed: ${oldTurns.length} old turns removed]`);
|
|
11268
|
+
if (this.lastUserTask) {
|
|
11269
|
+
const task = this.lastUserTask.slice(0, 400);
|
|
11270
|
+
parts.push(`[Task: ${task}]`);
|
|
11271
|
+
}
|
|
11166
11272
|
if (this.fileFacts.length > 0) {
|
|
11167
11273
|
parts.push(`[Files: ${this.fileFacts.slice(-15).join("; ")}]`);
|
|
11168
11274
|
}
|
|
@@ -11202,10 +11308,12 @@ ${lines.join(`
|
|
|
11202
11308
|
}
|
|
11203
11309
|
}
|
|
11204
11310
|
extractFacts(turns) {
|
|
11311
|
+
const DRIVE = "(?:[a-zA-Z]:[\\\\/])?";
|
|
11205
11312
|
const filePatterns = [
|
|
11206
|
-
|
|
11207
|
-
|
|
11208
|
-
|
|
11313
|
+
new RegExp(`(?:Created|Updated|Written|Deleted|Moved) ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi"),
|
|
11314
|
+
new RegExp(`Replaced in ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi"),
|
|
11315
|
+
new RegExp(`Файл (?:создан|обновлён|записан|удалён|перемещён):? ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi"),
|
|
11316
|
+
new RegExp(`file (?:created|updated|written|deleted|moved):? ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi")
|
|
11209
11317
|
];
|
|
11210
11318
|
const newFiles = [];
|
|
11211
11319
|
const newDecisions = [];
|
|
@@ -11265,6 +11373,7 @@ ${lines.join(`
|
|
|
11265
11373
|
this.iterationsSinceCompaction = 0;
|
|
11266
11374
|
this.compactionCount = 0;
|
|
11267
11375
|
this.peakTokens = 0;
|
|
11376
|
+
this.lastUserTask = "";
|
|
11268
11377
|
}
|
|
11269
11378
|
getEstimatedTokens() {
|
|
11270
11379
|
return this.messages.reduce((sum, m) => sum + this.estimateMessageTokens(m), 0) + this.toolTokens;
|
|
@@ -15453,6 +15562,9 @@ class PlanCreator {
|
|
|
15453
15562
|
const icon = step.status === "done" ? "[x]" : step.status === "in_progress" ? "[*]" : step.status === "failed" ? "[!]" : step.status === "skipped" ? "[-]" : "[ ]";
|
|
15454
15563
|
const note = step.note ? ` — ${step.note}` : "";
|
|
15455
15564
|
lines.push(`${icon} ${step.id}. ${step.description}${note}`);
|
|
15565
|
+
for (const sub of step.subtasks ?? []) {
|
|
15566
|
+
lines.push(` ${sub.done ? "[x]" : "[ ]"} ${sub.text}`);
|
|
15567
|
+
}
|
|
15456
15568
|
}
|
|
15457
15569
|
return lines.join(`
|
|
15458
15570
|
`);
|
|
@@ -15521,7 +15633,40 @@ var init_tracker = () => {};
|
|
|
15521
15633
|
|
|
15522
15634
|
// src/modules/execution/auditor.ts
|
|
15523
15635
|
import { existsSync as existsSync27, readdirSync as readdirSync8 } from "fs";
|
|
15524
|
-
import { resolve as resolve17, join as join22 } from "path";
|
|
15636
|
+
import { resolve as resolve17, join as join22, basename as basename2 } from "path";
|
|
15637
|
+
function findExistingFile(baseDir, filePath) {
|
|
15638
|
+
const direct = resolve17(baseDir, filePath);
|
|
15639
|
+
if (existsSync27(direct))
|
|
15640
|
+
return direct;
|
|
15641
|
+
const name = basename2(filePath).toLowerCase();
|
|
15642
|
+
const suffix = filePath.replace(/\\/g, "/").toLowerCase();
|
|
15643
|
+
let found = null;
|
|
15644
|
+
const walk = (dir, depth) => {
|
|
15645
|
+
if (found || depth > RESOLVE_MAX_DEPTH)
|
|
15646
|
+
return;
|
|
15647
|
+
let entries;
|
|
15648
|
+
try {
|
|
15649
|
+
entries = readdirSync8(dir, { withFileTypes: true });
|
|
15650
|
+
} catch {
|
|
15651
|
+
return;
|
|
15652
|
+
}
|
|
15653
|
+
for (const e of entries) {
|
|
15654
|
+
if (found)
|
|
15655
|
+
return;
|
|
15656
|
+
const full = join22(dir, e.name);
|
|
15657
|
+
if (e.isDirectory()) {
|
|
15658
|
+
if (SKIP_DIRS.has(e.name))
|
|
15659
|
+
continue;
|
|
15660
|
+
walk(full, depth + 1);
|
|
15661
|
+
} else if (e.name.toLowerCase() === name || full.replace(/\\/g, "/").toLowerCase().endsWith("/" + suffix)) {
|
|
15662
|
+
found = full;
|
|
15663
|
+
return;
|
|
15664
|
+
}
|
|
15665
|
+
}
|
|
15666
|
+
};
|
|
15667
|
+
walk(baseDir, 0);
|
|
15668
|
+
return found;
|
|
15669
|
+
}
|
|
15525
15670
|
function findTestFile(dir, depth = 0) {
|
|
15526
15671
|
if (depth > 5)
|
|
15527
15672
|
return null;
|
|
@@ -15608,8 +15753,8 @@ class Auditor {
|
|
|
15608
15753
|
const missingFiles = [];
|
|
15609
15754
|
const existingFiles = [];
|
|
15610
15755
|
for (const filePath of uniqueFiles) {
|
|
15611
|
-
const resolved =
|
|
15612
|
-
if (
|
|
15756
|
+
const resolved = findExistingFile(this.baseDir, filePath);
|
|
15757
|
+
if (resolved) {
|
|
15613
15758
|
existingFiles.push(filePath);
|
|
15614
15759
|
} else {
|
|
15615
15760
|
missingFiles.push(filePath);
|
|
@@ -15666,7 +15811,7 @@ class Auditor {
|
|
|
15666
15811
|
};
|
|
15667
15812
|
}
|
|
15668
15813
|
}
|
|
15669
|
-
var MASS_EDIT_THRESHOLD = 10, SKIP_DIRS, TEST_EXT_RE, TEST_STEP_RE;
|
|
15814
|
+
var MASS_EDIT_THRESHOLD = 10, SKIP_DIRS, TEST_EXT_RE, TEST_STEP_RE, RESOLVE_MAX_DEPTH = 8;
|
|
15670
15815
|
var init_auditor = __esm(() => {
|
|
15671
15816
|
init_i18n();
|
|
15672
15817
|
init_js_identifiers();
|
|
@@ -15859,7 +16004,7 @@ function extractFilePaths(text) {
|
|
|
15859
16004
|
}
|
|
15860
16005
|
return result;
|
|
15861
16006
|
}
|
|
15862
|
-
function
|
|
16007
|
+
function basename3(p) {
|
|
15863
16008
|
const parts = p.split(/[/\\]/);
|
|
15864
16009
|
return parts[parts.length - 1] ?? p;
|
|
15865
16010
|
}
|
|
@@ -15871,7 +16016,7 @@ function checkPlanCoverage(taskText, stepDescriptions) {
|
|
|
15871
16016
|
`);
|
|
15872
16017
|
const missing = taskPaths.filter((p) => {
|
|
15873
16018
|
const lower = p.toLowerCase();
|
|
15874
|
-
const base =
|
|
16019
|
+
const base = basename3(lower);
|
|
15875
16020
|
return !stepText.includes(lower) && !stepText.includes(base);
|
|
15876
16021
|
});
|
|
15877
16022
|
return { missing };
|
|
@@ -16133,6 +16278,23 @@ ${lines.join(`
|
|
|
16133
16278
|
};
|
|
16134
16279
|
}
|
|
16135
16280
|
if (action === "show") {
|
|
16281
|
+
const planId = args.id ? String(args.id) : "";
|
|
16282
|
+
if (planId && planId !== this.tracker?.getPlan()?.id) {
|
|
16283
|
+
const found = this.store.find(planId);
|
|
16284
|
+
if (!found) {
|
|
16285
|
+
return {
|
|
16286
|
+
success: false,
|
|
16287
|
+
output: t("plan.not_found", { id: planId })
|
|
16288
|
+
};
|
|
16289
|
+
}
|
|
16290
|
+
const display2 = PlanCreator.toPromptBlock(found.plan, 0);
|
|
16291
|
+
return {
|
|
16292
|
+
success: true,
|
|
16293
|
+
output: `${t("plan.show_header")}
|
|
16294
|
+
${display2}`,
|
|
16295
|
+
display: display2
|
|
16296
|
+
};
|
|
16297
|
+
}
|
|
16136
16298
|
if (!this.tracker) {
|
|
16137
16299
|
return { success: false, output: t("plan.no_active") };
|
|
16138
16300
|
}
|
|
@@ -16246,38 +16408,70 @@ ${progress}`,
|
|
|
16246
16408
|
}
|
|
16247
16409
|
if (action === "add" && Array.isArray(args.items)) {
|
|
16248
16410
|
const items = args.items.map(String);
|
|
16249
|
-
|
|
16411
|
+
const existing = currentStep.subtasks ?? [];
|
|
16412
|
+
let nextId = existing.reduce((m, s) => Math.max(m, s.id), 0) + 1;
|
|
16413
|
+
for (const item of items) {
|
|
16414
|
+
existing.push({ id: nextId++, text: item, done: false });
|
|
16415
|
+
}
|
|
16416
|
+
currentStep.subtasks = existing;
|
|
16417
|
+
this.store.saveActive(this.tracker.getPlan());
|
|
16418
|
+
const display = this.tracker.toPromptBlock();
|
|
16250
16419
|
return {
|
|
16251
16420
|
success: true,
|
|
16252
16421
|
output: t("todo.added", {
|
|
16253
16422
|
count: String(items.length),
|
|
16254
16423
|
items: items.join(", ")
|
|
16255
|
-
})
|
|
16424
|
+
}),
|
|
16425
|
+
display
|
|
16256
16426
|
};
|
|
16257
16427
|
}
|
|
16258
16428
|
if (action === "done") {
|
|
16259
|
-
|
|
16260
|
-
|
|
16429
|
+
const items = Array.isArray(args.items) ? args.items.map(String) : [];
|
|
16430
|
+
if (items.length === 0) {
|
|
16431
|
+
return {
|
|
16432
|
+
success: false,
|
|
16433
|
+
output: t("todo.no_items")
|
|
16434
|
+
};
|
|
16261
16435
|
}
|
|
16262
|
-
|
|
16263
|
-
|
|
16436
|
+
const subs = currentStep.subtasks ?? [];
|
|
16437
|
+
let marked = 0;
|
|
16438
|
+
for (const item of items) {
|
|
16439
|
+
const sub = subs.find((s) => !s.done && s.text.toLowerCase() === item.toLowerCase());
|
|
16440
|
+
if (sub) {
|
|
16441
|
+
sub.done = true;
|
|
16442
|
+
marked++;
|
|
16443
|
+
}
|
|
16444
|
+
}
|
|
16445
|
+
if (marked === 0) {
|
|
16446
|
+
return {
|
|
16447
|
+
success: false,
|
|
16448
|
+
output: t("todo.subtask_not_found", {
|
|
16449
|
+
items: items.join(", ")
|
|
16450
|
+
})
|
|
16451
|
+
};
|
|
16452
|
+
}
|
|
16453
|
+
currentStep.subtasks = subs;
|
|
16264
16454
|
this.store.saveActive(this.tracker.getPlan());
|
|
16455
|
+
const doneCount = subs.filter((s) => s.done).length;
|
|
16265
16456
|
const display = this.tracker.toPromptBlock();
|
|
16266
|
-
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
|
|
16271
|
-
|
|
16272
|
-
|
|
16273
|
-
}
|
|
16457
|
+
let output = t("todo.marked_done", {
|
|
16458
|
+
count: String(marked)
|
|
16459
|
+
});
|
|
16460
|
+
output += ` (${doneCount}/${subs.length})`;
|
|
16461
|
+
if (doneCount === subs.length) {
|
|
16462
|
+
output += `
|
|
16463
|
+
All sub-tasks done — call plan update step=${currentStep.id} status=done to complete this step.`;
|
|
16464
|
+
}
|
|
16465
|
+
return { success: true, output, display };
|
|
16274
16466
|
}
|
|
16275
16467
|
if (action === "list") {
|
|
16276
|
-
const
|
|
16468
|
+
const subs = currentStep.subtasks ?? [];
|
|
16469
|
+
const lines = subs.length ? subs.map((s) => `${s.done ? "[x]" : "[ ]"} ${s.text}`) : ["(no sub-tasks)"];
|
|
16277
16470
|
return {
|
|
16278
16471
|
success: true,
|
|
16279
16472
|
output: `Step ${currentStep.id}: ${currentStep.description}
|
|
16280
|
-
|
|
16473
|
+
${lines.join(`
|
|
16474
|
+
`)}`
|
|
16281
16475
|
};
|
|
16282
16476
|
}
|
|
16283
16477
|
return {
|
|
@@ -16322,7 +16516,7 @@ Sub-tasks: ${note}`
|
|
|
16322
16516
|
}
|
|
16323
16517
|
}
|
|
16324
16518
|
if (this.tracker?.isComplete()) {
|
|
16325
|
-
this.stuckDetector.
|
|
16519
|
+
this.stuckDetector.resetStepProgress();
|
|
16326
16520
|
this.consecutivePlanWarnings = 0;
|
|
16327
16521
|
this.lastStepId = -1;
|
|
16328
16522
|
this.stuckNotified = false;
|
|
@@ -16366,7 +16560,7 @@ Sub-tasks: ${note}`
|
|
|
16366
16560
|
this.stuckNotified = true;
|
|
16367
16561
|
}
|
|
16368
16562
|
}
|
|
16369
|
-
if (this.stuckDetector.isStuck() || this.stuckDetector.hasRepetitiveToolCalls()) {
|
|
16563
|
+
if (this.stuckDetector.isStuck() || this.stuckDetector.hasRepetitiveToolCalls() || this.stuckDetector.hasReadOnlyLoop()) {
|
|
16370
16564
|
const currentIter = typeof ctx.iteration === "number" ? ctx.iteration : 0;
|
|
16371
16565
|
if (currentIter - this.lastRecoveryIteration >= STUCK_RECOVERY_COOLDOWN) {
|
|
16372
16566
|
const recovery = this.stuckDetector.getRecoveryMessage();
|
|
@@ -17554,6 +17748,31 @@ var init_browser2 = __esm(() => {
|
|
|
17554
17748
|
init_types();
|
|
17555
17749
|
});
|
|
17556
17750
|
|
|
17751
|
+
// src/modules/lsp/command.ts
|
|
17752
|
+
import { delimiter, join as join28 } from "path";
|
|
17753
|
+
import { existsSync as existsSync34 } from "fs";
|
|
17754
|
+
import { platform as platform5 } from "os";
|
|
17755
|
+
function resolveSpawnCommand(command, platformName = platform5(), pathEnv = process.env.PATH ?? "") {
|
|
17756
|
+
if (platformName !== "win32")
|
|
17757
|
+
return command;
|
|
17758
|
+
if (command.includes("/") || command.includes("\\") || WIN_EXTS.some((ext) => command.toLowerCase().endsWith(ext))) {
|
|
17759
|
+
return command;
|
|
17760
|
+
}
|
|
17761
|
+
const dirs = pathEnv.split(delimiter).filter(Boolean);
|
|
17762
|
+
for (const dir of dirs) {
|
|
17763
|
+
for (const ext of WIN_EXTS) {
|
|
17764
|
+
const candidate = join28(dir, `${command}${ext}`);
|
|
17765
|
+
if (existsSync34(candidate))
|
|
17766
|
+
return `${command}${ext}`;
|
|
17767
|
+
}
|
|
17768
|
+
}
|
|
17769
|
+
return command;
|
|
17770
|
+
}
|
|
17771
|
+
var WIN_EXTS;
|
|
17772
|
+
var init_command = __esm(() => {
|
|
17773
|
+
WIN_EXTS = [".cmd", ".bat", ".exe", ".com"];
|
|
17774
|
+
});
|
|
17775
|
+
|
|
17557
17776
|
// src/modules/lsp/client.ts
|
|
17558
17777
|
import { spawn as spawn6, execSync as execSync2 } from "child_process";
|
|
17559
17778
|
import { resolve as resolve19 } from "path";
|
|
@@ -17619,7 +17838,7 @@ class LspClient {
|
|
|
17619
17838
|
}
|
|
17620
17839
|
return new Promise((resolve20, reject) => {
|
|
17621
17840
|
const args = config.args ?? [];
|
|
17622
|
-
const proc = spawn6(config.command, args, {
|
|
17841
|
+
const proc = spawn6(resolveSpawnCommand(config.command), args, {
|
|
17623
17842
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17624
17843
|
env: { ...process.env, ...config.env },
|
|
17625
17844
|
cwd: baseDir
|
|
@@ -17784,10 +18003,12 @@ class LspClient {
|
|
|
17784
18003
|
}
|
|
17785
18004
|
}
|
|
17786
18005
|
var DEFAULT_TIMEOUT = 15000;
|
|
17787
|
-
var init_client2 = () => {
|
|
18006
|
+
var init_client2 = __esm(() => {
|
|
18007
|
+
init_command();
|
|
18008
|
+
});
|
|
17788
18009
|
|
|
17789
18010
|
// src/modules/lsp/module.ts
|
|
17790
|
-
import { existsSync as
|
|
18011
|
+
import { existsSync as existsSync35 } from "fs";
|
|
17791
18012
|
import { resolve as resolve20 } from "path";
|
|
17792
18013
|
|
|
17793
18014
|
class LspModule {
|
|
@@ -17813,7 +18034,7 @@ class LspModule {
|
|
|
17813
18034
|
if (!filePath)
|
|
17814
18035
|
return;
|
|
17815
18036
|
const fullPath = resolve20(_ctx.baseDir, filePath);
|
|
17816
|
-
if (!
|
|
18037
|
+
if (!existsSync35(fullPath))
|
|
17817
18038
|
return;
|
|
17818
18039
|
const serverConfig = getServerForFile(fullPath, self.config);
|
|
17819
18040
|
if (!serverConfig)
|
|
@@ -17879,8 +18100,8 @@ var init_lsp = __esm(() => {
|
|
|
17879
18100
|
});
|
|
17880
18101
|
|
|
17881
18102
|
// src/modules/indexer/walker.ts
|
|
17882
|
-
import { readdirSync as readdirSync13, readFileSync as readFileSync22, statSync as statSync7, existsSync as
|
|
17883
|
-
import { join as
|
|
18103
|
+
import { readdirSync as readdirSync13, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync36, watch } from "fs";
|
|
18104
|
+
import { join as join29, relative as relative2, extname as extname5 } from "path";
|
|
17884
18105
|
|
|
17885
18106
|
class Indexer {
|
|
17886
18107
|
baseDir;
|
|
@@ -17907,7 +18128,7 @@ class Indexer {
|
|
|
17907
18128
|
let totalSize = 0;
|
|
17908
18129
|
let count = 0;
|
|
17909
18130
|
const walkDir = (dir) => {
|
|
17910
|
-
if (!
|
|
18131
|
+
if (!existsSync36(dir))
|
|
17911
18132
|
return;
|
|
17912
18133
|
let entries;
|
|
17913
18134
|
try {
|
|
@@ -17918,7 +18139,7 @@ class Indexer {
|
|
|
17918
18139
|
for (const entry of entries) {
|
|
17919
18140
|
if (count >= this.MAX_FILES)
|
|
17920
18141
|
return;
|
|
17921
|
-
const fullPath =
|
|
18142
|
+
const fullPath = join29(dir, entry);
|
|
17922
18143
|
const relPath = relative2(this.baseDir, fullPath);
|
|
17923
18144
|
const stat = statSync7(fullPath);
|
|
17924
18145
|
if (stat.isDirectory()) {
|
|
@@ -17981,19 +18202,19 @@ var init_walker = __esm(() => {
|
|
|
17981
18202
|
});
|
|
17982
18203
|
|
|
17983
18204
|
// src/modules/indexer/cache.ts
|
|
17984
|
-
import { readFileSync as readFileSync23, writeFileSync as writeFileSync13, existsSync as
|
|
17985
|
-
import { join as
|
|
18205
|
+
import { readFileSync as readFileSync23, writeFileSync as writeFileSync13, existsSync as existsSync37, mkdirSync as mkdirSync16, rmSync as rmSync3 } from "fs";
|
|
18206
|
+
import { join as join30 } from "path";
|
|
17986
18207
|
|
|
17987
18208
|
class IndexCache {
|
|
17988
18209
|
cachePath;
|
|
17989
18210
|
cache = null;
|
|
17990
18211
|
constructor(cacheDir) {
|
|
17991
|
-
this.cachePath =
|
|
18212
|
+
this.cachePath = join30(cacheDir, "index-cache.json");
|
|
17992
18213
|
}
|
|
17993
18214
|
load() {
|
|
17994
18215
|
if (this.cache)
|
|
17995
18216
|
return this.cache;
|
|
17996
|
-
if (!
|
|
18217
|
+
if (!existsSync37(this.cachePath))
|
|
17997
18218
|
return null;
|
|
17998
18219
|
try {
|
|
17999
18220
|
this.cache = JSON.parse(readFileSync23(this.cachePath, "utf-8"));
|
|
@@ -18004,14 +18225,14 @@ class IndexCache {
|
|
|
18004
18225
|
}
|
|
18005
18226
|
save(result) {
|
|
18006
18227
|
this.cache = result;
|
|
18007
|
-
const dir =
|
|
18008
|
-
if (!
|
|
18228
|
+
const dir = join30(this.cachePath, "..");
|
|
18229
|
+
if (!existsSync37(dir))
|
|
18009
18230
|
mkdirSync16(dir, { recursive: true });
|
|
18010
18231
|
writeFileSync13(this.cachePath, JSON.stringify(result), "utf-8");
|
|
18011
18232
|
}
|
|
18012
18233
|
invalidate() {
|
|
18013
18234
|
this.cache = null;
|
|
18014
|
-
if (
|
|
18235
|
+
if (existsSync37(this.cachePath)) {
|
|
18015
18236
|
try {
|
|
18016
18237
|
rmSync3(this.cachePath);
|
|
18017
18238
|
} catch {}
|
|
@@ -18369,13 +18590,13 @@ var init_mcp = __esm(() => {
|
|
|
18369
18590
|
|
|
18370
18591
|
// src/modules/memory/module.ts
|
|
18371
18592
|
import { homedir as homedir10 } from "os";
|
|
18372
|
-
import { join as
|
|
18593
|
+
import { join as join31 } from "path";
|
|
18373
18594
|
|
|
18374
18595
|
class MemoryModule {
|
|
18375
18596
|
name = "memory";
|
|
18376
18597
|
store;
|
|
18377
18598
|
constructor(memoryDir) {
|
|
18378
|
-
const dir = memoryDir ||
|
|
18599
|
+
const dir = memoryDir || join31(homedir10(), ".mma", "memory");
|
|
18379
18600
|
this.store = new MemoryStore(dir);
|
|
18380
18601
|
}
|
|
18381
18602
|
getSystemPromptBlock() {
|
|
@@ -18423,8 +18644,8 @@ __export(exports_bootstrap, {
|
|
|
18423
18644
|
bootstrap: () => bootstrap
|
|
18424
18645
|
});
|
|
18425
18646
|
import { homedir as homedir11 } from "os";
|
|
18426
|
-
import { join as
|
|
18427
|
-
import { existsSync as
|
|
18647
|
+
import { join as join32, resolve as resolve21 } from "path";
|
|
18648
|
+
import { existsSync as existsSync38, readFileSync as readFileSync24, writeFileSync as writeFileSync14 } from "fs";
|
|
18428
18649
|
function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
18429
18650
|
const now = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
18430
18651
|
const isWin = profileCompressed.toLowerCase().includes("win32");
|
|
@@ -18449,8 +18670,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
18449
18670
|
`);
|
|
18450
18671
|
}
|
|
18451
18672
|
async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
18452
|
-
const dir = configDir ||
|
|
18453
|
-
const projectConfigPath = projectDir ?
|
|
18673
|
+
const dir = configDir || join32(homedir11(), ".mma");
|
|
18674
|
+
const projectConfigPath = projectDir ? join32(projectDir, ".mmrc") : join32(process.cwd(), ".mmrc");
|
|
18454
18675
|
const config = loadConfig({ configDir: dir, projectConfigPath });
|
|
18455
18676
|
setLocale(config.locale);
|
|
18456
18677
|
try {
|
|
@@ -18460,7 +18681,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18460
18681
|
}
|
|
18461
18682
|
} catch {}
|
|
18462
18683
|
const logger = new Logger(config.logLevel);
|
|
18463
|
-
logger.setLogDir(
|
|
18684
|
+
logger.setLogDir(join32(dir, "logs"));
|
|
18464
18685
|
logger.debug("MMA bootstrap", {
|
|
18465
18686
|
version: config.version,
|
|
18466
18687
|
model: config.model
|
|
@@ -18482,7 +18703,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18482
18703
|
logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
|
|
18483
18704
|
}
|
|
18484
18705
|
}
|
|
18485
|
-
const profile = new UserProfile(
|
|
18706
|
+
const profile = new UserProfile(join32(dir));
|
|
18486
18707
|
profile.load() || profile.collect();
|
|
18487
18708
|
profile.save();
|
|
18488
18709
|
const llmProvider = new OpenAICompatProvider({
|
|
@@ -18494,7 +18715,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18494
18715
|
rateLimits: config.security?.rateLimits
|
|
18495
18716
|
});
|
|
18496
18717
|
const baseDir = projectDir ? resolve21(projectDir) : process.cwd();
|
|
18497
|
-
const projectMapCacheDir =
|
|
18718
|
+
const projectMapCacheDir = join32(baseDir, ".mma");
|
|
18498
18719
|
const indexerModule = new IndexerModule({
|
|
18499
18720
|
baseDir,
|
|
18500
18721
|
cacheDir: projectMapCacheDir
|
|
@@ -18505,9 +18726,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18505
18726
|
logger.warn(`Project indexing failed: ${err.message}`);
|
|
18506
18727
|
}
|
|
18507
18728
|
const skillsLoader = new SkillsLoader;
|
|
18508
|
-
const builtinDir =
|
|
18509
|
-
const globalDir =
|
|
18510
|
-
const projectSkillsDir =
|
|
18729
|
+
const builtinDir = join32(import.meta.dirname, "skills", "builtin");
|
|
18730
|
+
const globalDir = join32(homedir11(), ".agents", "skills");
|
|
18731
|
+
const projectSkillsDir = join32(baseDir, ".mma", "skills");
|
|
18511
18732
|
const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
|
|
18512
18733
|
const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
|
|
18513
18734
|
const skillsModule = new SkillsModule(availableSkills, skillsBudget);
|
|
@@ -18521,11 +18742,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18521
18742
|
essential: true,
|
|
18522
18743
|
estimatedTokens: Math.ceil(systemInfoContent.length / 4)
|
|
18523
18744
|
};
|
|
18524
|
-
const agentsMdGlobal =
|
|
18525
|
-
if (!
|
|
18745
|
+
const agentsMdGlobal = join32(dir, "AGENTS.md");
|
|
18746
|
+
if (!existsSync38(agentsMdGlobal)) {
|
|
18526
18747
|
writeFileSync14(agentsMdGlobal, "", "utf-8");
|
|
18527
18748
|
}
|
|
18528
|
-
const sessionDir =
|
|
18749
|
+
const sessionDir = join32(dir, "sessions");
|
|
18529
18750
|
const sessionStore = new SessionStore(sessionDir);
|
|
18530
18751
|
sessionStore.init();
|
|
18531
18752
|
const sessionManager = new SessionManager(sessionStore, {
|
|
@@ -18592,7 +18813,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18592
18813
|
const mcpModule = new MCPModule(config);
|
|
18593
18814
|
await mcpModule.initialize();
|
|
18594
18815
|
moduleRegistry.register(mcpModule);
|
|
18595
|
-
const memoryModule = new MemoryModule(
|
|
18816
|
+
const memoryModule = new MemoryModule(join32(dir, "memory"));
|
|
18596
18817
|
moduleRegistry.register(memoryModule);
|
|
18597
18818
|
if (config.browser.enabled) {
|
|
18598
18819
|
const browserModule = new BrowserModule;
|
|
@@ -18642,8 +18863,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18642
18863
|
pluginManager.register(plugin);
|
|
18643
18864
|
pluginManager.register(plugin2);
|
|
18644
18865
|
const pluginLoader = new PluginLoader;
|
|
18645
|
-
const globalPluginsDir =
|
|
18646
|
-
const projectPluginsDir =
|
|
18866
|
+
const globalPluginsDir = join32(homedir11(), ".mma", "plugins");
|
|
18867
|
+
const projectPluginsDir = join32(baseDir, ".mma", "plugins");
|
|
18647
18868
|
pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger);
|
|
18648
18869
|
pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger);
|
|
18649
18870
|
contextManager.onCompact = (summary) => {
|
|
@@ -18661,12 +18882,12 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
18661
18882
|
const skipAgentsMd = noAgentsMd === true;
|
|
18662
18883
|
if (!skipAgentsMd) {
|
|
18663
18884
|
const agentsMdCandidates = [
|
|
18664
|
-
|
|
18665
|
-
|
|
18666
|
-
|
|
18885
|
+
join32(baseDir, "AGENTS.md"),
|
|
18886
|
+
join32(baseDir, ".mma", "AGENTS.md"),
|
|
18887
|
+
join32(dir, "AGENTS.md")
|
|
18667
18888
|
];
|
|
18668
18889
|
for (const p of agentsMdCandidates) {
|
|
18669
|
-
if (
|
|
18890
|
+
if (existsSync38(p)) {
|
|
18670
18891
|
const content = readFileSync24(p, "utf-8").trim();
|
|
18671
18892
|
if (content) {
|
|
18672
18893
|
agentsMdBlocks.push({
|
|
@@ -19516,12 +19737,12 @@ __export(exports_manifest, {
|
|
|
19516
19737
|
getCertMark: () => getCertMark,
|
|
19517
19738
|
MANIFEST_PATH: () => MANIFEST_PATH
|
|
19518
19739
|
});
|
|
19519
|
-
import { existsSync as
|
|
19740
|
+
import { existsSync as existsSync39, readFileSync as readFileSync25, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
|
|
19520
19741
|
import { homedir as homedir13 } from "os";
|
|
19521
|
-
import { join as
|
|
19742
|
+
import { join as join34 } from "path";
|
|
19522
19743
|
function readManifest(path = MANIFEST_PATH) {
|
|
19523
19744
|
try {
|
|
19524
|
-
if (
|
|
19745
|
+
if (existsSync39(path)) {
|
|
19525
19746
|
const raw = JSON.parse(readFileSync25(path, "utf-8"));
|
|
19526
19747
|
return { version: 1, certifications: raw.certifications ?? [] };
|
|
19527
19748
|
}
|
|
@@ -19529,7 +19750,7 @@ function readManifest(path = MANIFEST_PATH) {
|
|
|
19529
19750
|
return { version: 1, certifications: [] };
|
|
19530
19751
|
}
|
|
19531
19752
|
function saveManifest(m, path = MANIFEST_PATH) {
|
|
19532
|
-
mkdirSync17(
|
|
19753
|
+
mkdirSync17(join34(homedir13(), ".mma"), { recursive: true });
|
|
19533
19754
|
writeFileSync15(path, JSON.stringify(m, null, 2), "utf-8");
|
|
19534
19755
|
}
|
|
19535
19756
|
function upsertCertification(entry, path = MANIFEST_PATH) {
|
|
@@ -19564,7 +19785,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
|
|
|
19564
19785
|
}
|
|
19565
19786
|
var MANIFEST_PATH;
|
|
19566
19787
|
var init_manifest = __esm(() => {
|
|
19567
|
-
MANIFEST_PATH =
|
|
19788
|
+
MANIFEST_PATH = join34(homedir13(), ".mma", "certifications.json");
|
|
19568
19789
|
});
|
|
19569
19790
|
|
|
19570
19791
|
// node_modules/yaml/dist/nodes/identity.js
|
|
@@ -26687,8 +26908,8 @@ var init_scenarios = __esm(() => {
|
|
|
26687
26908
|
});
|
|
26688
26909
|
|
|
26689
26910
|
// src/modules/certification/loader.ts
|
|
26690
|
-
import { existsSync as
|
|
26691
|
-
import { join as
|
|
26911
|
+
import { existsSync as existsSync40, readdirSync as readdirSync14, readFileSync as readFileSync26 } from "fs";
|
|
26912
|
+
import { join as join35 } from "path";
|
|
26692
26913
|
function validateScenario(s) {
|
|
26693
26914
|
const errors2 = [];
|
|
26694
26915
|
const isSkip = s.mode === "skip";
|
|
@@ -26737,12 +26958,12 @@ function loadScenarios(userDir) {
|
|
|
26737
26958
|
else
|
|
26738
26959
|
scenarios.push(s);
|
|
26739
26960
|
}
|
|
26740
|
-
if (userDir &&
|
|
26961
|
+
if (userDir && existsSync40(userDir)) {
|
|
26741
26962
|
for (const file of readdirSync14(userDir)) {
|
|
26742
26963
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
|
|
26743
26964
|
continue;
|
|
26744
26965
|
try {
|
|
26745
|
-
const raw = readFileSync26(
|
|
26966
|
+
const raw = readFileSync26(join35(userDir, file), "utf-8");
|
|
26746
26967
|
const data = $parse(raw);
|
|
26747
26968
|
const parsed = normalizeScenario(data, file);
|
|
26748
26969
|
const errs = validateScenario(parsed);
|
|
@@ -26795,8 +27016,8 @@ var init_loader3 = __esm(() => {
|
|
|
26795
27016
|
});
|
|
26796
27017
|
|
|
26797
27018
|
// src/modules/certification/fact-checker.ts
|
|
26798
|
-
import { existsSync as
|
|
26799
|
-
import { join as
|
|
27019
|
+
import { existsSync as existsSync41, readFileSync as readFileSync27, statSync as statSync8 } from "fs";
|
|
27020
|
+
import { join as join36 } from "path";
|
|
26800
27021
|
function checkSandbox(sandboxDir, checks, exitCode, output) {
|
|
26801
27022
|
const failures = [];
|
|
26802
27023
|
for (const check of checks) {
|
|
@@ -26813,13 +27034,13 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
26813
27034
|
case "outputContains":
|
|
26814
27035
|
return output.includes(check.text);
|
|
26815
27036
|
case "fileExists":
|
|
26816
|
-
return isFile(
|
|
27037
|
+
return isFile(join36(sandboxDir, check.path));
|
|
26817
27038
|
case "fileNotExists":
|
|
26818
|
-
return !
|
|
27039
|
+
return !existsSync41(join36(sandboxDir, check.path));
|
|
26819
27040
|
case "dirExists":
|
|
26820
|
-
return isDir(
|
|
27041
|
+
return isDir(join36(sandboxDir, check.path));
|
|
26821
27042
|
case "fileContent": {
|
|
26822
|
-
const abs =
|
|
27043
|
+
const abs = join36(sandboxDir, check.path);
|
|
26823
27044
|
if (!isFile(abs))
|
|
26824
27045
|
return false;
|
|
26825
27046
|
const content = readFileSync27(abs, "utf-8");
|
|
@@ -26830,7 +27051,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
26830
27051
|
return false;
|
|
26831
27052
|
}
|
|
26832
27053
|
case "fileRegex": {
|
|
26833
|
-
const abs =
|
|
27054
|
+
const abs = join36(sandboxDir, check.path);
|
|
26834
27055
|
if (!isFile(abs))
|
|
26835
27056
|
return false;
|
|
26836
27057
|
return new RegExp(check.pattern).test(readFileSync27(abs, "utf-8"));
|
|
@@ -26841,14 +27062,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
26841
27062
|
}
|
|
26842
27063
|
function isFile(p) {
|
|
26843
27064
|
try {
|
|
26844
|
-
return
|
|
27065
|
+
return existsSync41(p) && statSync8(p).isFile();
|
|
26845
27066
|
} catch {
|
|
26846
27067
|
return false;
|
|
26847
27068
|
}
|
|
26848
27069
|
}
|
|
26849
27070
|
function isDir(p) {
|
|
26850
27071
|
try {
|
|
26851
|
-
return
|
|
27072
|
+
return existsSync41(p) && statSync8(p).isDirectory();
|
|
26852
27073
|
} catch {
|
|
26853
27074
|
return false;
|
|
26854
27075
|
}
|
|
@@ -26879,9 +27100,9 @@ var init_fact_checker = () => {};
|
|
|
26879
27100
|
|
|
26880
27101
|
// src/modules/certification/runner.ts
|
|
26881
27102
|
import { spawn as spawn7 } from "child_process";
|
|
26882
|
-
import { existsSync as
|
|
26883
|
-
import { platform as
|
|
26884
|
-
import { join as
|
|
27103
|
+
import { existsSync as existsSync42, mkdirSync as mkdirSync18, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
|
|
27104
|
+
import { platform as platform6 } from "os";
|
|
27105
|
+
import { join as join37, resolve as resolve22, dirname as dirname9 } from "path";
|
|
26885
27106
|
async function runScenario(scenario, opts) {
|
|
26886
27107
|
if (scenario.mode === "skip") {
|
|
26887
27108
|
return {
|
|
@@ -26900,7 +27121,7 @@ async function runScenario(scenario, opts) {
|
|
|
26900
27121
|
let passed = 0;
|
|
26901
27122
|
let firstError;
|
|
26902
27123
|
for (let i = 1;i <= reps; i++) {
|
|
26903
|
-
const sandbox =
|
|
27124
|
+
const sandbox = join37(opts.sandboxBase, `run-${scenario.id}-${i}`);
|
|
26904
27125
|
let failures = [];
|
|
26905
27126
|
let exitCode = -1;
|
|
26906
27127
|
let output = "";
|
|
@@ -26961,20 +27182,20 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
26961
27182
|
rmSync4(sandbox, { recursive: true, force: true });
|
|
26962
27183
|
mkdirSync18(sandbox, { recursive: true });
|
|
26963
27184
|
for (const f of scenario.fixtures ?? []) {
|
|
26964
|
-
const src =
|
|
26965
|
-
if (!
|
|
27185
|
+
const src = join37(mmaRoot, f.source);
|
|
27186
|
+
if (!existsSync42(src)) {
|
|
26966
27187
|
throw new Error(`fixture missing: ${f.source}`);
|
|
26967
27188
|
}
|
|
26968
|
-
const dest =
|
|
27189
|
+
const dest = join37(sandbox, f.dest);
|
|
26969
27190
|
mkdirSync18(dirname9(dest), { recursive: true });
|
|
26970
27191
|
cpSync2(src, dest);
|
|
26971
27192
|
}
|
|
26972
27193
|
}
|
|
26973
27194
|
function resolveMmaEntry(mmaRoot) {
|
|
26974
|
-
const dev =
|
|
26975
|
-
if (
|
|
27195
|
+
const dev = join37(mmaRoot, "src", "cli", "main.ts");
|
|
27196
|
+
if (existsSync42(dev))
|
|
26976
27197
|
return dev;
|
|
26977
|
-
return
|
|
27198
|
+
return join37(mmaRoot, "dist", "main.js");
|
|
26978
27199
|
}
|
|
26979
27200
|
function findMmaRoot(fromDir) {
|
|
26980
27201
|
const candidates = [
|
|
@@ -26982,7 +27203,7 @@ function findMmaRoot(fromDir) {
|
|
|
26982
27203
|
resolve22(fromDir, "..")
|
|
26983
27204
|
];
|
|
26984
27205
|
for (const c of candidates) {
|
|
26985
|
-
if (
|
|
27206
|
+
if (existsSync42(join37(c, "package.json")))
|
|
26986
27207
|
return c;
|
|
26987
27208
|
}
|
|
26988
27209
|
return process.cwd();
|
|
@@ -26991,7 +27212,7 @@ function killTree2(child) {
|
|
|
26991
27212
|
const pid = child.pid;
|
|
26992
27213
|
if (!pid)
|
|
26993
27214
|
return;
|
|
26994
|
-
if (
|
|
27215
|
+
if (platform6() === "win32") {
|
|
26995
27216
|
spawn7("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
26996
27217
|
windowsHide: true,
|
|
26997
27218
|
stdio: "ignore"
|
|
@@ -27050,13 +27271,13 @@ __export(exports_cli, {
|
|
|
27050
27271
|
});
|
|
27051
27272
|
import { rmSync as rmSync5 } from "fs";
|
|
27052
27273
|
import { homedir as homedir14 } from "os";
|
|
27053
|
-
import { join as
|
|
27274
|
+
import { join as join38, dirname as dirname10 } from "path";
|
|
27054
27275
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
27055
|
-
import { existsSync as
|
|
27276
|
+
import { existsSync as existsSync43, readFileSync as readFileSync28 } from "fs";
|
|
27056
27277
|
function readVersion() {
|
|
27057
|
-
const candidates = [
|
|
27278
|
+
const candidates = [join38(MMA_ROOT, "package.json")];
|
|
27058
27279
|
for (const p of candidates) {
|
|
27059
|
-
if (
|
|
27280
|
+
if (existsSync43(p)) {
|
|
27060
27281
|
try {
|
|
27061
27282
|
const raw = JSON.parse(readFileSync28(p, "utf-8"));
|
|
27062
27283
|
if (raw.version)
|
|
@@ -27094,7 +27315,7 @@ async function certify(opts) {
|
|
|
27094
27315
|
return;
|
|
27095
27316
|
}
|
|
27096
27317
|
console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
|
|
27097
|
-
const sandboxBase =
|
|
27318
|
+
const sandboxBase = join38(process.cwd(), ".mma", "certification");
|
|
27098
27319
|
const results = [];
|
|
27099
27320
|
const total = selected.length;
|
|
27100
27321
|
let idx = 0;
|
|
@@ -27208,7 +27429,7 @@ var init_cli = __esm(() => {
|
|
|
27208
27429
|
init_manifest();
|
|
27209
27430
|
HERE = dirname10(fileURLToPath2(import.meta.url));
|
|
27210
27431
|
MMA_ROOT = findMmaRoot(HERE);
|
|
27211
|
-
USER_SCENARIO_DIR =
|
|
27432
|
+
USER_SCENARIO_DIR = join38(homedir14(), ".mma", "certification", "scenarios");
|
|
27212
27433
|
});
|
|
27213
27434
|
|
|
27214
27435
|
// src/cli/repl-commands.ts
|
|
@@ -27217,18 +27438,18 @@ __export(exports_repl_commands, {
|
|
|
27217
27438
|
registerAllCommands: () => registerAllCommands,
|
|
27218
27439
|
COMMAND_GROUPS: () => COMMAND_GROUPS
|
|
27219
27440
|
});
|
|
27220
|
-
import { join as
|
|
27441
|
+
import { join as join40, dirname as dirname12 } from "path";
|
|
27221
27442
|
import { homedir as homedir16 } from "os";
|
|
27222
|
-
import { existsSync as
|
|
27443
|
+
import { existsSync as existsSync45, readFileSync as readFileSync30 } from "fs";
|
|
27223
27444
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
27224
27445
|
function readVersion3() {
|
|
27225
27446
|
const here = dirname12(fileURLToPath4(import.meta.url));
|
|
27226
27447
|
const candidates = [
|
|
27227
|
-
|
|
27228
|
-
|
|
27448
|
+
join40(here, "..", "..", "package.json"),
|
|
27449
|
+
join40(here, "..", "package.json")
|
|
27229
27450
|
];
|
|
27230
27451
|
for (const p of candidates) {
|
|
27231
|
-
if (
|
|
27452
|
+
if (existsSync45(p)) {
|
|
27232
27453
|
try {
|
|
27233
27454
|
const raw = JSON.parse(readFileSync30(p, "utf8"));
|
|
27234
27455
|
if (raw.version)
|
|
@@ -27294,7 +27515,7 @@ function registerMmaCommands(ctx) {
|
|
|
27294
27515
|
}
|
|
27295
27516
|
try {
|
|
27296
27517
|
const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
|
|
27297
|
-
const { existsSync:
|
|
27518
|
+
const { existsSync: existsSync46 } = await import("fs");
|
|
27298
27519
|
const { resolve: resolve23 } = await import("path");
|
|
27299
27520
|
let dataUrl;
|
|
27300
27521
|
let label;
|
|
@@ -27314,7 +27535,7 @@ function registerMmaCommands(ctx) {
|
|
|
27314
27535
|
label = source;
|
|
27315
27536
|
} else {
|
|
27316
27537
|
const absPath = resolve23(process.cwd(), source);
|
|
27317
|
-
if (!
|
|
27538
|
+
if (!existsSync46(absPath)) {
|
|
27318
27539
|
console.log(pc2.red(t("image.not_found", { path: source })));
|
|
27319
27540
|
return;
|
|
27320
27541
|
}
|
|
@@ -27393,7 +27614,7 @@ function registerMmaCommands(ctx) {
|
|
|
27393
27614
|
console.log(pc2.yellow(t("repl.wizard_running")));
|
|
27394
27615
|
await ctx.withExclusiveInput(async () => {
|
|
27395
27616
|
const answers = await runSetup(ctx.rl);
|
|
27396
|
-
const configPath =
|
|
27617
|
+
const configPath = join40(homedir16(), ".mma", "config.json");
|
|
27397
27618
|
ctx.config.provider.type = answers.provider;
|
|
27398
27619
|
ctx.config.provider.baseUrl = answers.apiBase;
|
|
27399
27620
|
ctx.config.provider.apiKey = answers.apiKey;
|
|
@@ -27447,7 +27668,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
27447
27668
|
return;
|
|
27448
27669
|
}
|
|
27449
27670
|
ctx.config.provider.type = name;
|
|
27450
|
-
const configPath =
|
|
27671
|
+
const configPath = join40(homedir16(), ".mma", "config.json");
|
|
27451
27672
|
saveConfig(ctx.config, configPath);
|
|
27452
27673
|
await ctx.agent.reconfigure(ctx.config);
|
|
27453
27674
|
console.log(pc2.green(t("repl.provider_set", { name })));
|
|
@@ -27503,7 +27724,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
27503
27724
|
return;
|
|
27504
27725
|
}
|
|
27505
27726
|
ctx.config.model = name;
|
|
27506
|
-
const configPath =
|
|
27727
|
+
const configPath = join40(homedir16(), ".mma", "config.json");
|
|
27507
27728
|
saveConfig(ctx.config, configPath);
|
|
27508
27729
|
await ctx.agent.reconfigure(ctx.config);
|
|
27509
27730
|
console.log(pc2.green(t("repl.model_set", { name })));
|
|
@@ -27528,7 +27749,7 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
27528
27749
|
return;
|
|
27529
27750
|
}
|
|
27530
27751
|
ctx.config.contextWindow = size;
|
|
27531
|
-
const configPath =
|
|
27752
|
+
const configPath = join40(homedir16(), ".mma", "config.json");
|
|
27532
27753
|
saveConfig(ctx.config, configPath);
|
|
27533
27754
|
await ctx.agent.reconfigure(ctx.config);
|
|
27534
27755
|
console.log(pc2.green(t("cli.context_set", { size })));
|
|
@@ -27547,10 +27768,10 @@ Excluded blocks: ${info.excluded.length}`));
|
|
|
27547
27768
|
ctx.agent.shutdown();
|
|
27548
27769
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
27549
27770
|
const { homedir: homedir17 } = await import("os");
|
|
27550
|
-
const { join:
|
|
27771
|
+
const { join: join41 } = await import("path");
|
|
27551
27772
|
const configDir = ctx.configDir;
|
|
27552
27773
|
const baseDir = ctx.baseDir;
|
|
27553
|
-
const projectConfigPath =
|
|
27774
|
+
const projectConfigPath = join41(baseDir, ".mmrc");
|
|
27554
27775
|
const freshConfig = loadConfig2({ configDir, projectConfigPath });
|
|
27555
27776
|
Object.assign(ctx.config, freshConfig);
|
|
27556
27777
|
const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
|
|
@@ -27850,14 +28071,14 @@ init_bootstrap();
|
|
|
27850
28071
|
init_config2();
|
|
27851
28072
|
init_setup();
|
|
27852
28073
|
init_i18n();
|
|
27853
|
-
import { join as
|
|
28074
|
+
import { join as join39, dirname as dirname11 } from "path";
|
|
27854
28075
|
import { homedir as homedir15 } from "os";
|
|
27855
|
-
import { existsSync as
|
|
28076
|
+
import { existsSync as existsSync44, readFileSync as readFileSync29 } from "fs";
|
|
27856
28077
|
|
|
27857
28078
|
// src/cli/security-commands.ts
|
|
27858
28079
|
init_bootstrap();
|
|
27859
28080
|
init_config2();
|
|
27860
|
-
import { join as
|
|
28081
|
+
import { join as join33 } from "path";
|
|
27861
28082
|
import { homedir as homedir12 } from "os";
|
|
27862
28083
|
|
|
27863
28084
|
// src/modules/security/security-policies.ts
|
|
@@ -28387,7 +28608,7 @@ function createSecurityCommand(program2) {
|
|
|
28387
28608
|
}
|
|
28388
28609
|
});
|
|
28389
28610
|
securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
|
|
28390
|
-
const configPath =
|
|
28611
|
+
const configPath = join33(homedir12(), ".mma", "config.json");
|
|
28391
28612
|
const { config: appConfig } = await bootstrap();
|
|
28392
28613
|
const validPresets = ["strict", "balanced", "permissive"];
|
|
28393
28614
|
if (!validPresets.includes(preset)) {
|
|
@@ -28402,7 +28623,7 @@ function createSecurityCommand(program2) {
|
|
|
28402
28623
|
console.log(t("cli.security.policy_description", { description: policy.description }));
|
|
28403
28624
|
});
|
|
28404
28625
|
securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
|
|
28405
|
-
const configPath =
|
|
28626
|
+
const configPath = join33(homedir12(), ".mma", "config.json");
|
|
28406
28627
|
const { config: appConfig } = await bootstrap();
|
|
28407
28628
|
appConfig.security = appConfig.security || {};
|
|
28408
28629
|
appConfig.security.sessionEncryption = {
|
|
@@ -28414,7 +28635,7 @@ function createSecurityCommand(program2) {
|
|
|
28414
28635
|
console.log(t("cli.security.encryption_enabled"));
|
|
28415
28636
|
});
|
|
28416
28637
|
securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
|
|
28417
|
-
const configPath =
|
|
28638
|
+
const configPath = join33(homedir12(), ".mma", "config.json");
|
|
28418
28639
|
const { config: appConfig } = await bootstrap();
|
|
28419
28640
|
appConfig.security = appConfig.security || {};
|
|
28420
28641
|
appConfig.security.sessionEncryption = {
|
|
@@ -28426,7 +28647,7 @@ function createSecurityCommand(program2) {
|
|
|
28426
28647
|
console.log(t("cli.security.encryption_disabled"));
|
|
28427
28648
|
});
|
|
28428
28649
|
securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
|
|
28429
|
-
const configPath =
|
|
28650
|
+
const configPath = join33(homedir12(), ".mma", "config.json");
|
|
28430
28651
|
const { config: appConfig } = await bootstrap();
|
|
28431
28652
|
appConfig.security = appConfig.security || {};
|
|
28432
28653
|
appConfig.security.auditNotifier = {
|
|
@@ -28440,7 +28661,7 @@ function createSecurityCommand(program2) {
|
|
|
28440
28661
|
console.log(t("cli.security.audit_enabled"));
|
|
28441
28662
|
});
|
|
28442
28663
|
securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
|
|
28443
|
-
const configPath =
|
|
28664
|
+
const configPath = join33(homedir12(), ".mma", "config.json");
|
|
28444
28665
|
const { config: appConfig } = await bootstrap();
|
|
28445
28666
|
appConfig.security = appConfig.security || {};
|
|
28446
28667
|
appConfig.security.auditNotifier = {
|
|
@@ -28476,11 +28697,11 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
28476
28697
|
function readVersion2() {
|
|
28477
28698
|
const here = dirname11(fileURLToPath3(import.meta.url));
|
|
28478
28699
|
const candidates = [
|
|
28479
|
-
|
|
28480
|
-
|
|
28700
|
+
join39(here, "..", "..", "package.json"),
|
|
28701
|
+
join39(here, "..", "package.json")
|
|
28481
28702
|
];
|
|
28482
28703
|
for (const p of candidates) {
|
|
28483
|
-
if (
|
|
28704
|
+
if (existsSync44(p)) {
|
|
28484
28705
|
try {
|
|
28485
28706
|
const raw = JSON.parse(readFileSync29(p, "utf8"));
|
|
28486
28707
|
if (raw.version)
|
|
@@ -28495,7 +28716,7 @@ function createProgram() {
|
|
|
28495
28716
|
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"));
|
|
28496
28717
|
program2.command("init").description(t("cli.init")).action(async () => {
|
|
28497
28718
|
const answers = await runSetup();
|
|
28498
|
-
const configPath =
|
|
28719
|
+
const configPath = join39(homedir15(), ".mma", "config.json");
|
|
28499
28720
|
const { config } = await bootstrap();
|
|
28500
28721
|
config.provider.type = answers.provider;
|
|
28501
28722
|
config.provider.baseUrl = answers.apiBase;
|
|
@@ -28540,7 +28761,7 @@ function createProgram() {
|
|
|
28540
28761
|
});
|
|
28541
28762
|
const configCmd = program2.command("config").description(t("cli.manage_config"));
|
|
28542
28763
|
configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
|
|
28543
|
-
const configPath =
|
|
28764
|
+
const configPath = join39(homedir15(), ".mma", "config.json");
|
|
28544
28765
|
const { config } = await bootstrap();
|
|
28545
28766
|
const keys = key.split(".");
|
|
28546
28767
|
let obj = config;
|
|
@@ -28603,7 +28824,7 @@ function createProgram() {
|
|
|
28603
28824
|
console.log(t("cli.model_hint"));
|
|
28604
28825
|
});
|
|
28605
28826
|
model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
|
|
28606
|
-
const configPath =
|
|
28827
|
+
const configPath = join39(homedir15(), ".mma", "config.json");
|
|
28607
28828
|
const { config } = await bootstrap();
|
|
28608
28829
|
config.model = name;
|
|
28609
28830
|
saveConfig(config, configPath);
|
|
@@ -28639,7 +28860,7 @@ function createProgram() {
|
|
|
28639
28860
|
await uncertify2(name, config);
|
|
28640
28861
|
});
|
|
28641
28862
|
program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
|
|
28642
|
-
const configPath =
|
|
28863
|
+
const configPath = join39(homedir15(), ".mma", "config.json");
|
|
28643
28864
|
const { config } = await bootstrap();
|
|
28644
28865
|
const contextWindow = parseInt(size, 10);
|
|
28645
28866
|
if (isNaN(contextWindow) || contextWindow < 1024) {
|
|
@@ -28657,7 +28878,7 @@ function createProgram() {
|
|
|
28657
28878
|
console.log(t("cli.base_url"), config.provider.baseUrl);
|
|
28658
28879
|
});
|
|
28659
28880
|
provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
|
|
28660
|
-
const configPath =
|
|
28881
|
+
const configPath = join39(homedir15(), ".mma", "config.json");
|
|
28661
28882
|
const { config } = await bootstrap();
|
|
28662
28883
|
config.provider.type = name;
|
|
28663
28884
|
saveConfig(config, configPath);
|
|
@@ -29427,8 +29648,8 @@ class LineEditor {
|
|
|
29427
29648
|
}
|
|
29428
29649
|
|
|
29429
29650
|
// src/cli/repl.ts
|
|
29430
|
-
import { existsSync as
|
|
29431
|
-
import { join as
|
|
29651
|
+
import { existsSync as existsSync46, readFileSync as readFileSync31, writeFileSync as writeFileSync16 } from "fs";
|
|
29652
|
+
import { join as join41, dirname as dirname13 } from "path";
|
|
29432
29653
|
import { homedir as homedir17 } from "os";
|
|
29433
29654
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
29434
29655
|
|
|
@@ -29934,11 +30155,11 @@ init_repl_commands();
|
|
|
29934
30155
|
function readVersion4() {
|
|
29935
30156
|
const here = dirname13(fileURLToPath5(import.meta.url));
|
|
29936
30157
|
const candidates = [
|
|
29937
|
-
|
|
29938
|
-
|
|
30158
|
+
join41(here, "..", "..", "package.json"),
|
|
30159
|
+
join41(here, "..", "package.json")
|
|
29939
30160
|
];
|
|
29940
30161
|
for (const p of candidates) {
|
|
29941
|
-
if (
|
|
30162
|
+
if (existsSync46(p)) {
|
|
29942
30163
|
try {
|
|
29943
30164
|
const raw = JSON.parse(readFileSync31(p, "utf8"));
|
|
29944
30165
|
if (raw.version)
|
|
@@ -29996,10 +30217,10 @@ class Repl {
|
|
|
29996
30217
|
this.skillsModule = skillsModule;
|
|
29997
30218
|
this.pluginManager = pluginManager;
|
|
29998
30219
|
this.logger = logger;
|
|
29999
|
-
this.configDir = configDir ||
|
|
30220
|
+
this.configDir = configDir || join41(homedir17(), ".mma");
|
|
30000
30221
|
this.baseDir = baseDir || process.cwd();
|
|
30001
30222
|
this.noAgentsMd = noAgentsMd === true;
|
|
30002
|
-
this.historyPath =
|
|
30223
|
+
this.historyPath = join41(homedir17(), ".mma", "repl-history");
|
|
30003
30224
|
this.loadHistory();
|
|
30004
30225
|
this.rl = process.stdin.isTTY ? new LineEditor({
|
|
30005
30226
|
input: process.stdin,
|
|
@@ -30032,7 +30253,7 @@ class Repl {
|
|
|
30032
30253
|
this.setupListeners();
|
|
30033
30254
|
}
|
|
30034
30255
|
loadHistory() {
|
|
30035
|
-
if (
|
|
30256
|
+
if (existsSync46(this.historyPath)) {
|
|
30036
30257
|
try {
|
|
30037
30258
|
const raw = readFileSync31(this.historyPath, "utf-8");
|
|
30038
30259
|
this.history = raw.split(`
|
|
@@ -30391,11 +30612,11 @@ ${t("image.clipboard_empty")}`));
|
|
|
30391
30612
|
row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
|
|
30392
30613
|
} else {
|
|
30393
30614
|
const agentsMdCandidates = [
|
|
30394
|
-
|
|
30395
|
-
|
|
30396
|
-
|
|
30615
|
+
join41(this.baseDir, "AGENTS.md"),
|
|
30616
|
+
join41(this.baseDir, ".mma", "AGENTS.md"),
|
|
30617
|
+
join41(this.configDir, "AGENTS.md")
|
|
30397
30618
|
];
|
|
30398
|
-
const foundAgents = agentsMdCandidates.filter((p) =>
|
|
30619
|
+
const foundAgents = agentsMdCandidates.filter((p) => existsSync46(p));
|
|
30399
30620
|
if (foundAgents.length > 0) {
|
|
30400
30621
|
for (const p of foundAgents) {
|
|
30401
30622
|
row(t("repl.agents_label"), pc2.dim(p));
|
|
@@ -30406,7 +30627,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
30406
30627
|
}
|
|
30407
30628
|
const meta = this.sessionManager?.getActiveMeta();
|
|
30408
30629
|
if (meta) {
|
|
30409
|
-
const sessionPath =
|
|
30630
|
+
const sessionPath = join41(this.configDir, "sessions", meta.id);
|
|
30410
30631
|
row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
|
|
30411
30632
|
}
|
|
30412
30633
|
const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
|
|
@@ -30447,8 +30668,8 @@ init_setup();
|
|
|
30447
30668
|
init_config2();
|
|
30448
30669
|
init_i18n();
|
|
30449
30670
|
init_colors();
|
|
30450
|
-
import { existsSync as
|
|
30451
|
-
import { join as
|
|
30671
|
+
import { existsSync as existsSync47, readFileSync as readFileSync32 } from "fs";
|
|
30672
|
+
import { join as join42, dirname as dirname14 } from "path";
|
|
30452
30673
|
import { homedir as homedir18 } from "os";
|
|
30453
30674
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
30454
30675
|
|
|
@@ -30601,11 +30822,11 @@ class UpdaterModule {
|
|
|
30601
30822
|
function readVersion5() {
|
|
30602
30823
|
const here = dirname14(fileURLToPath6(import.meta.url));
|
|
30603
30824
|
const candidates = [
|
|
30604
|
-
|
|
30605
|
-
|
|
30825
|
+
join42(here, "..", "..", "package.json"),
|
|
30826
|
+
join42(here, "..", "package.json")
|
|
30606
30827
|
];
|
|
30607
30828
|
for (const p of candidates) {
|
|
30608
|
-
if (
|
|
30829
|
+
if (existsSync47(p)) {
|
|
30609
30830
|
try {
|
|
30610
30831
|
const raw = JSON.parse(readFileSync32(p, "utf8"));
|
|
30611
30832
|
if (raw.version)
|
|
@@ -30678,15 +30899,15 @@ async function main() {
|
|
|
30678
30899
|
agent.shutdown();
|
|
30679
30900
|
process.exit(exitCode);
|
|
30680
30901
|
} else {
|
|
30681
|
-
const configPath =
|
|
30682
|
-
if (!
|
|
30902
|
+
const configPath = join42(homedir18(), ".mma", "config.json");
|
|
30903
|
+
if (!existsSync47(configPath)) {
|
|
30683
30904
|
console.log(pc2.yellow(`
|
|
30684
30905
|
` + t("cli.first_run") + `
|
|
30685
30906
|
`));
|
|
30686
30907
|
const answers = await runSetup();
|
|
30687
30908
|
const config2 = loadConfig({
|
|
30688
|
-
configDir:
|
|
30689
|
-
projectConfigPath: projectDir ?
|
|
30909
|
+
configDir: join42(homedir18(), ".mma"),
|
|
30910
|
+
projectConfigPath: projectDir ? join42(projectDir, ".mmrc") : join42(process.cwd(), ".mmrc")
|
|
30690
30911
|
});
|
|
30691
30912
|
config2.provider.type = answers.provider;
|
|
30692
30913
|
config2.provider.baseUrl = answers.apiBase;
|