micro-models-agent 0.35.0 → 0.35.2
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 -8
- package/dist/main.js +59 -7
- package/package.json +1 -1
package/bin/mma.mjs
CHANGED
|
@@ -1,8 +1,41 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
|
|
6
|
+
// MMA is designed to run under Bun: clipboard image paste relies on
|
|
7
|
+
// `Bun.Image.fromClipboard()` (Node has no clipboard API), and on Windows a
|
|
8
|
+
// bare `npx.cmd` shim can only be spawned reliably through Bun's child_process
|
|
9
|
+
// (under Node it throws `spawn EINVAL`). The global npm shim (`mma` /
|
|
10
|
+
// `mma.cmd`) launches this file under Node, so re-execute ourselves under Bun
|
|
11
|
+
// when it is available. The `bun run mma` path already runs under Bun and
|
|
12
|
+
// skips the respawn.
|
|
13
|
+
const runningUnderBun =
|
|
14
|
+
typeof globalThis.Bun !== "undefined" &&
|
|
15
|
+
typeof globalThis.Bun?.version !== "undefined";
|
|
16
|
+
|
|
17
|
+
if (process.env.MMA_DEBUG_RUNTIME) {
|
|
18
|
+
console.error(
|
|
19
|
+
"[mma] runtime=" +
|
|
20
|
+
(runningUnderBun ? "bun " + globalThis.Bun.version : "node " + process.version),
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!runningUnderBun) {
|
|
25
|
+
try {
|
|
26
|
+
const res = spawnSync("bun", [process.argv[1], ...process.argv.slice(2)], {
|
|
27
|
+
stdio: "inherit",
|
|
28
|
+
windowsHide: true,
|
|
29
|
+
});
|
|
30
|
+
if (res.error) throw res.error;
|
|
31
|
+
process.exit(res.status ?? 0);
|
|
32
|
+
} catch {
|
|
33
|
+
// `bun` is not on PATH — fall back to the Node import path (clipboard
|
|
34
|
+
// paste and LSP will degrade, but the agent still works).
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
39
|
+
const main = join(__dirname, "..", "dist", "main.js");
|
|
40
|
+
|
|
41
|
+
await import(pathToFileURL(main).href);
|
package/dist/main.js
CHANGED
|
@@ -2463,6 +2463,7 @@ Command: {command}`,
|
|
|
2463
2463
|
"plan.step_not_found": "Step not found",
|
|
2464
2464
|
"plan.step_already_done": "Step {step} is already done — nothing to do. Plan progress:",
|
|
2465
2465
|
"plan.order_blocked": 'Cannot mark step {step} done: step {first} ("{desc}") is not finished yet. Complete earlier steps first, or mark step {first} status=skipped if it is not needed.',
|
|
2466
|
+
"plan.deliverables_missing": "Cannot mark step {step} done: the files it names do not exist yet: {files}. Create these files first (or mark the step status=skipped if they are not actually needed).",
|
|
2466
2467
|
"plan.show_header": "Plan status:",
|
|
2467
2468
|
"plan.show_empty": "(plan has no steps)",
|
|
2468
2469
|
"plan.list_header": "Plans:",
|
|
@@ -2756,6 +2757,7 @@ Use this knowledge to answer the user's question.`,
|
|
|
2756
2757
|
"exec.step_gate_ok": '[✓] Step {step} completed and verified. MOVING to step {nextStep}: "{nextDesc}". Work ONLY on this step.',
|
|
2757
2758
|
"exec.step_gate_last": "[✓] Step {step} completed — that was the final step. Verify everything together and provide the final answer.]",
|
|
2758
2759
|
"exec.audit_pass": "[✓] Task complete: {done}/{total} steps done, {files} files verified",
|
|
2760
|
+
"exec.audit_pending": "[✗] Task incomplete: {done}/{total} steps done — remaining steps are not marked done",
|
|
2759
2761
|
"exec.audit_fail": "[✗] Task incomplete: {done}/{total} steps done, {files} files missing",
|
|
2760
2762
|
"exec.audit_fail_tests": "[✗] Task incomplete: {done}/{total} steps done, tests FAILING: {failed} failed / {passed} passed — {detail}",
|
|
2761
2763
|
"exec.audit_fail_typecheck": "[✗] Task incomplete: {done}/{total} steps done, {missing} files missing, typecheck error: {typeError}",
|
|
@@ -3051,6 +3053,7 @@ var init_ru = __esm(() => {
|
|
|
3051
3053
|
"plan.step_not_found": "Шаг не найден",
|
|
3052
3054
|
"plan.step_already_done": "Шаг {step} уже выполнен — ничего делать не нужно. Прогресс плана:",
|
|
3053
3055
|
"plan.order_blocked": "Нельзя отметить шаг {step} выполненным: шаг {first} («{desc}») ещё не завершён. Сначала завершите предыдущие шаги или отметьте шаг {first} status=skipped, если он не нужен.",
|
|
3056
|
+
"plan.deliverables_missing": "Нельзя отметить шаг {step} выполненным: указанные в нём файлы ещё не существуют: {files}. Сначала создайте эти файлы (или отметьте шаг status=skipped, если они на самом деле не нужны).",
|
|
3054
3057
|
"plan.show_header": "Статус плана:",
|
|
3055
3058
|
"plan.show_empty": "(в плане нет шагов)",
|
|
3056
3059
|
"plan.list_header": "Планы:",
|
|
@@ -3344,6 +3347,7 @@ var init_ru = __esm(() => {
|
|
|
3344
3347
|
"exec.step_gate_ok": '[✓] Шаг {step} завершён и проверен. ПЕРЕХОДИМ к шагу {nextStep}: "{nextDesc}". Работайте ТОЛЬКО над этим шагом.',
|
|
3345
3348
|
"exec.step_gate_last": "[✓] Шаг {step} завершён — это был последний шаг. Проверьте всё вместе и предоставьте финальный ответ.]",
|
|
3346
3349
|
"exec.audit_pass": "[✓] Задача выполнена: {done}/{total} шагов, {files} файлов проверено",
|
|
3350
|
+
"exec.audit_pending": "[✗] Задача не выполнена: {done}/{total} шагов — оставшиеся шаги не отмечены выполненными",
|
|
3347
3351
|
"exec.audit_fail": "[✗] Задача не выполнена: {done}/{total} шагов, {files} файлов отсутствует",
|
|
3348
3352
|
"exec.audit_fail_tests": "[✗] Задача не выполнена: {done}/{total} шагов, тесты ПАДАЮТ: {failed} failed / {passed} passed — {detail}",
|
|
3349
3353
|
"exec.audit_fail_typecheck": "[✗] Задача не выполнена: {done}/{total} шагов, {missing} файлов отсутствует, ошибка typecheck: {typeError}",
|
|
@@ -15908,6 +15912,7 @@ class Auditor {
|
|
|
15908
15912
|
}
|
|
15909
15913
|
const testsFailing = testRun !== null && testRun.failed > 0;
|
|
15910
15914
|
const passed = missingFiles.length === 0 && !testsFailing;
|
|
15915
|
+
const stepsPending = doneSteps < totalSteps;
|
|
15911
15916
|
let summary;
|
|
15912
15917
|
if (missingFiles.length > 0) {
|
|
15913
15918
|
summary = t("exec.audit_fail", {
|
|
@@ -15923,6 +15928,11 @@ class Auditor {
|
|
|
15923
15928
|
passed: String(testRun.passedCount),
|
|
15924
15929
|
detail: testRun.detail
|
|
15925
15930
|
});
|
|
15931
|
+
} else if (stepsPending) {
|
|
15932
|
+
summary = t("exec.audit_pending", {
|
|
15933
|
+
done: doneSteps,
|
|
15934
|
+
total: totalSteps
|
|
15935
|
+
});
|
|
15926
15936
|
} else {
|
|
15927
15937
|
summary = t("exec.audit_pass", {
|
|
15928
15938
|
done: doneSteps,
|
|
@@ -16468,6 +16478,18 @@ ${progress2}`,
|
|
|
16468
16478
|
};
|
|
16469
16479
|
}
|
|
16470
16480
|
}
|
|
16481
|
+
if (status === "done") {
|
|
16482
|
+
const missing = this.missingStepDeliverables(target);
|
|
16483
|
+
if (missing.length > 0) {
|
|
16484
|
+
return {
|
|
16485
|
+
success: false,
|
|
16486
|
+
output: t("plan.deliverables_missing", {
|
|
16487
|
+
step: String(stepId),
|
|
16488
|
+
files: missing.join(", ")
|
|
16489
|
+
})
|
|
16490
|
+
};
|
|
16491
|
+
}
|
|
16492
|
+
}
|
|
16471
16493
|
this.tracker.updateStepStatus(stepId, status);
|
|
16472
16494
|
if (args.note)
|
|
16473
16495
|
this.tracker.addNote(Number(args.step), String(args.note));
|
|
@@ -16972,6 +16994,12 @@ Tool "${this.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
|
|
|
16972
16994
|
});
|
|
16973
16995
|
}
|
|
16974
16996
|
}
|
|
16997
|
+
missingStepDeliverables(step) {
|
|
16998
|
+
const tokens = extractFileLikeTokens(stripUrls(step.description));
|
|
16999
|
+
if (tokens.length === 0)
|
|
17000
|
+
return [];
|
|
17001
|
+
return tokens.filter((p) => !findExistingFile(this.baseDir, p));
|
|
17002
|
+
}
|
|
16975
17003
|
getTaskText(ctx) {
|
|
16976
17004
|
const manager = ctx?.contextManager;
|
|
16977
17005
|
if (!manager)
|
|
@@ -16993,6 +17021,7 @@ var init_module = __esm(() => {
|
|
|
16993
17021
|
init_plan_store();
|
|
16994
17022
|
init_plan_coverage();
|
|
16995
17023
|
init_bash();
|
|
17024
|
+
init_js_identifiers();
|
|
16996
17025
|
});
|
|
16997
17026
|
|
|
16998
17027
|
// src/modules/security/session-encryption.ts
|
|
@@ -17898,14 +17927,28 @@ function resolveSpawnCommand(command, platformName = platform5(), pathEnv = proc
|
|
|
17898
17927
|
}
|
|
17899
17928
|
return command;
|
|
17900
17929
|
}
|
|
17930
|
+
function buildWinCommandLine(command, args) {
|
|
17931
|
+
const quote = (part) => {
|
|
17932
|
+
if (part === "")
|
|
17933
|
+
return '""';
|
|
17934
|
+
if (!/[\s"&|^<>()%!]/.test(part))
|
|
17935
|
+
return part;
|
|
17936
|
+
return `"${part.replace(/"/g, "\\\"")}"`;
|
|
17937
|
+
};
|
|
17938
|
+
return [command, ...args].map(quote).join(" ");
|
|
17939
|
+
}
|
|
17901
17940
|
var WIN_EXTS;
|
|
17902
17941
|
var init_command = __esm(() => {
|
|
17903
17942
|
WIN_EXTS = [".cmd", ".bat", ".exe", ".com"];
|
|
17904
17943
|
});
|
|
17905
17944
|
|
|
17906
17945
|
// src/modules/lsp/client.ts
|
|
17907
|
-
import {
|
|
17946
|
+
import {
|
|
17947
|
+
spawn as spawn6,
|
|
17948
|
+
execSync as execSync2
|
|
17949
|
+
} from "child_process";
|
|
17908
17950
|
import { resolve as resolve19 } from "path";
|
|
17951
|
+
import { platform as platform6 } from "os";
|
|
17909
17952
|
|
|
17910
17953
|
class LspClient {
|
|
17911
17954
|
process = null;
|
|
@@ -17968,11 +18011,20 @@ class LspClient {
|
|
|
17968
18011
|
}
|
|
17969
18012
|
return new Promise((resolve20, reject) => {
|
|
17970
18013
|
const args = config.args ?? [];
|
|
17971
|
-
const
|
|
18014
|
+
const isWin = platform6() === "win32";
|
|
18015
|
+
let spawnCommand = resolveSpawnCommand(config.command);
|
|
18016
|
+
let spawnArgs = args;
|
|
18017
|
+
const spawnOpts = {
|
|
17972
18018
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17973
18019
|
env: { ...process.env, ...config.env },
|
|
17974
18020
|
cwd: baseDir
|
|
17975
|
-
}
|
|
18021
|
+
};
|
|
18022
|
+
if (isWin) {
|
|
18023
|
+
spawnCommand = buildWinCommandLine(spawnCommand, args);
|
|
18024
|
+
spawnArgs = [];
|
|
18025
|
+
spawnOpts.shell = true;
|
|
18026
|
+
}
|
|
18027
|
+
const proc = spawn6(spawnCommand, spawnArgs, spawnOpts);
|
|
17976
18028
|
proc.on("error", reject);
|
|
17977
18029
|
proc.stdout.on("data", (chunk) => {
|
|
17978
18030
|
this.handleData(chunk);
|
|
@@ -27411,7 +27463,7 @@ var init_fact_checker = () => {};
|
|
|
27411
27463
|
// src/modules/certification/runner.ts
|
|
27412
27464
|
import { spawn as spawn7 } from "child_process";
|
|
27413
27465
|
import { existsSync as existsSync43, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
|
|
27414
|
-
import { platform as
|
|
27466
|
+
import { platform as platform7 } from "os";
|
|
27415
27467
|
import { join as join38, resolve as resolve22, dirname as dirname10 } from "path";
|
|
27416
27468
|
async function runScenario(scenario, opts) {
|
|
27417
27469
|
if (scenario.mode === "skip") {
|
|
@@ -27522,7 +27574,7 @@ function killTree2(child) {
|
|
|
27522
27574
|
const pid = child.pid;
|
|
27523
27575
|
if (!pid)
|
|
27524
27576
|
return;
|
|
27525
|
-
if (
|
|
27577
|
+
if (platform7() === "win32") {
|
|
27526
27578
|
spawn7("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
27527
27579
|
windowsHide: true,
|
|
27528
27580
|
stdio: "ignore"
|
|
@@ -30985,7 +31037,7 @@ import { fileURLToPath as fileURLToPath6 } from "url";
|
|
|
30985
31037
|
|
|
30986
31038
|
// src/modules/updater/checker.ts
|
|
30987
31039
|
init_command();
|
|
30988
|
-
import { platform as
|
|
31040
|
+
import { platform as platform8 } from "os";
|
|
30989
31041
|
var defaultRunner2 = async (command, args, options) => {
|
|
30990
31042
|
const { execFile } = await import("child_process");
|
|
30991
31043
|
return new Promise((resolve23) => {
|
|
@@ -31047,7 +31099,7 @@ class Updater {
|
|
|
31047
31099
|
buildInstallCommand(latest) {
|
|
31048
31100
|
const npmArgs = ["install", "-g", `${this.packageName}@${latest}`];
|
|
31049
31101
|
const command = resolveSpawnCommand("npm");
|
|
31050
|
-
if (
|
|
31102
|
+
if (platform8() === "win32" && /\.(cmd|bat)$/i.test(command)) {
|
|
31051
31103
|
return { command: "cmd.exe", args: ["/c", command, ...npmArgs] };
|
|
31052
31104
|
}
|
|
31053
31105
|
return { command, args: npmArgs };
|