micro-models-agent 0.36.0 → 0.36.1

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.
Files changed (2) hide show
  1. package/dist/main.js +226 -162
  2. package/package.json +45 -45
package/dist/main.js CHANGED
@@ -2142,7 +2142,7 @@ var init_config = __esm(() => {
2142
2142
  css: {
2143
2143
  command: "npx",
2144
2144
  args: ["vscode-css-languageserver", "--stdio"],
2145
- timeout: 1e4,
2145
+ timeout: 20000,
2146
2146
  autoInstall: true,
2147
2147
  workspaceMarkers: ["package.json"]
2148
2148
  }
@@ -2785,6 +2785,7 @@ Use this knowledge to answer the user's question.`,
2785
2785
  {hints}`,
2786
2786
  "exec.file_rewrite_warning": "⚠️ File {file} has been rewritten {count} times. Consider a different approach — the current fix strategy is not working.",
2787
2787
  "exec.forbidden_cmd": 'STOP using "{cmd}" via the bash tool — it is not a native Windows cmd.exe command and has failed repeatedly this session. Use the dedicated tool instead: grep → the grep tool, ls/dir → list_dir, find → glob, rm → delete_file, sed → edit_file, touch → write_file, which → `where`, cp/mv → move_file, diff → read_file. Do NOT call bash for this purpose again.',
2788
+ "exec.npm_exec_hint": '"could not determine executable to run" — no "bin" for that package/script. Use "npm run <script>" (script must exist in package.json) or "bunx <pkg>" for a package that declares a bin.',
2788
2789
  "hall.max_retries_exhausted": "Model returned empty or insufficient responses after multiple retries",
2789
2790
  "hall.short_response": "Response too short or empty",
2790
2791
  "hall.repetitive": "Response too repetitive ({pct}% overlap)",
@@ -3383,6 +3384,7 @@ var init_ru = __esm(() => {
3383
3384
  {hints}`,
3384
3385
  "exec.file_rewrite_warning": "⚠️ Файл {file} был перезаписан {count} раз. Попробуйте другой подход — текущая стратегия исправлений не работает.",
3385
3386
  "exec.forbidden_cmd": 'ПРЕКРАТИ использовать "{cmd}" через bash — это не команда Windows cmd.exe, и она уже неоднократно падала в этой сессии. Используй предназначенный тул: grep → тул grep, ls/dir → list_dir, find → glob, rm → delete_file, sed → edit_file, touch → write_file, which → `where`, cp/mv → move_file, diff → read_file. Больше не вызывай bash для этого.',
3387
+ "exec.npm_exec_hint": '"could not determine executable to run" — у пакета/скрипта нет "bin". Используй "npm run <script>" (скрипт должен быть в package.json) или "bunx <pkg>" для пакета с объявленным bin.',
3386
3388
  "hall.max_retries_exhausted": "Модель вернула пустой или недостаточный ответ после нескольких попыток",
3387
3389
  "hall.short_response": "Слишком короткий или пустой ответ",
3388
3390
  "hall.repetitive": "Слишком повторяющийся ответ ({pct}% совпадение)",
@@ -7555,7 +7557,15 @@ function emptyCliRunHint(command, output, code) {
7555
7557
  return null;
7556
7558
  return "the command exited 0 but printed NOTHING to stdout. If this should run a CLI program, the file probably has no entry point: read it with read_file and check the code actually calls its main function with command-line arguments (e.g. main(process.argv[2])) and prints results with console.log.";
7557
7559
  }
7558
- var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, bashGraceMs, FAILING_FIRST_WORDS, HARD_BLOCK_THRESHOLD = 3, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, bashTool;
7560
+ function npmExecHint(output) {
7561
+ if (NPM_EXEC_RE.test(output)) {
7562
+ return `${output}
7563
+
7564
+ Hint: ${t("exec.npm_exec_hint")}`;
7565
+ }
7566
+ return output;
7567
+ }
7568
+ var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, bashGraceMs, FAILING_FIRST_WORDS, HARD_BLOCK_THRESHOLD = 3, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, NPM_EXEC_RE, bashTool;
7559
7569
  var init_bash = __esm(() => {
7560
7570
  init_command_validator();
7561
7571
  init_audit_log();
@@ -7620,6 +7630,7 @@ var init_bash = __esm(() => {
7620
7630
  "awk"
7621
7631
  ]);
7622
7632
  CLI_FILE_RUN_RE = /\b(bun|node|deno|python|python3|tsx|ts-node|php|ruby|go\s+run)\S*\s+(run\s+)?["']?[\w./\\-]+\.(ts|js|tsx|jsx|mjs|cjs|py)\b/;
7633
+ NPM_EXEC_RE = /could not determine executable to run/i;
7623
7634
  bashTool = {
7624
7635
  name: "bash",
7625
7636
  description: `Execute a shell command and return its output. Use for running tests, build, git, and shell operations. Commands that are still running after a few seconds are automatically moved to the background and return a process id — manage them with process_list, process_log, process_kill. Set background=true to return a process id immediately for commands you know are long-running (dev servers, watchers).
@@ -7716,6 +7727,7 @@ ${output2}`;
7716
7727
  if (!output2 && code !== 0) {
7717
7728
  output2 = `(exit code ${code})`;
7718
7729
  }
7730
+ output2 = npmExecHint(output2);
7719
7731
  if (platform2() === "win32") {
7720
7732
  const originalFirstWord = originalCommand.trim().split(/\s+/)[0]?.split(/[\\/]/).pop();
7721
7733
  if (originalFirstWord && originalFirstWord in UNIX_TO_WIN_HINTS) {
@@ -14216,6 +14228,7 @@ class BridgeDriver {
14216
14228
  proc = null;
14217
14229
  rl = null;
14218
14230
  pending = new Map;
14231
+ lastStderr = [];
14219
14232
  nextId = 1;
14220
14233
  lastUrl = "";
14221
14234
  console = new ConsoleBuffer(500);
@@ -14224,9 +14237,13 @@ class BridgeDriver {
14224
14237
  constructor(opts = {}) {
14225
14238
  this.maxConsoleLineChars = opts.maxConsoleLineChars ?? 400;
14226
14239
  }
14227
- async send(cmd, params = {}) {
14228
- if (!this.proc || !this.rl)
14229
- throw new Error("Bridge is not running");
14240
+ async send(cmd, params = {}, retried = false) {
14241
+ if (!this.proc || !this.rl) {
14242
+ if (retried || cmd === "close")
14243
+ throw new Error("Bridge is not running");
14244
+ this.spawnBridge();
14245
+ return this.send(cmd, params, true);
14246
+ }
14230
14247
  const id = this.nextId++;
14231
14248
  const response = await new Promise((resolve15, reject) => {
14232
14249
  const timer = setTimeout(() => {
@@ -14272,7 +14289,10 @@ class BridgeDriver {
14272
14289
  const script = bridgeScriptPath();
14273
14290
  const proc = spawn4("node", [script], { stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
14274
14291
  this.proc = proc;
14275
- proc.stderr.on("data", () => {});
14292
+ this.lastStderr = [];
14293
+ proc.stderr.on("data", (chunk) => {
14294
+ this.lastStderr = [...this.lastStderr.slice(-4), chunk.toString()];
14295
+ });
14276
14296
  const rl = createInterface({ input: proc.stdout });
14277
14297
  this.rl = rl;
14278
14298
  rl.on("line", (line) => {
@@ -14288,15 +14308,28 @@ class BridgeDriver {
14288
14308
  resolver(resp);
14289
14309
  }
14290
14310
  });
14291
- proc.on("exit", () => {
14292
- for (const [, resolver] of this.pending) {
14293
- resolver({ id: -1, ok: false, error: "Bridge process exited" });
14294
- }
14295
- this.pending.clear();
14311
+ proc.on("error", (err) => {
14312
+ if (this.proc !== proc)
14313
+ return;
14314
+ this.failPending(`Bridge process failed to start: ${err.message}`);
14315
+ this.proc = null;
14316
+ this.rl = null;
14317
+ });
14318
+ proc.on("exit", (code) => {
14319
+ if (this.proc !== proc)
14320
+ return;
14321
+ const stderrTail = this.lastStderr.join("").trim();
14322
+ this.failPending(stderrTail ? `Bridge process exited (code ${code}): ${stderrTail.slice(0, 300)}` : `Bridge process exited (code ${code})`);
14296
14323
  this.proc = null;
14297
14324
  this.rl = null;
14298
14325
  });
14299
14326
  }
14327
+ failPending(error) {
14328
+ for (const [, resolver] of this.pending) {
14329
+ resolver({ id: -1, ok: false, error });
14330
+ }
14331
+ this.pending.clear();
14332
+ }
14300
14333
  async goto(url, timeoutMs) {
14301
14334
  await this.send("goto", { url, timeoutMs });
14302
14335
  }
@@ -15940,8 +15973,8 @@ class PlanTracker {
15940
15973
  var init_tracker = () => {};
15941
15974
 
15942
15975
  // src/modules/execution/audit-runners.ts
15943
- import { readdirSync as readdirSync8 } from "fs";
15944
- import { join as join23 } from "path";
15976
+ import { existsSync as existsSync28, readdirSync as readdirSync8 } from "fs";
15977
+ import { dirname as dirname10, join as join23, resolve as resolve17 } from "path";
15945
15978
  function findTestFile(dir, depth = 0) {
15946
15979
  if (depth > 5)
15947
15980
  return null;
@@ -16000,7 +16033,7 @@ async function runTests(baseDir) {
16000
16033
  return {
16001
16034
  checked: true,
16002
16035
  passed: entry.exitCode === 0,
16003
- failed: entry.exitCode === 0 ? 0 : -1,
16036
+ failed: entry.exitCode === 0 ? 0 : 1,
16004
16037
  passedCount: 0,
16005
16038
  detail: output.slice(0, 200).trim(),
16006
16039
  command: "bun test"
@@ -16021,6 +16054,25 @@ function parseTypecheckErrors(output) {
16021
16054
  `).find((l) => /error TS\d+/.test(l));
16022
16055
  return line ? line.trim().slice(0, 300) : null;
16023
16056
  }
16057
+ function findTypecheckRoot(baseDir, existingFiles = []) {
16058
+ const candidates = [baseDir, ...existingFiles];
16059
+ let best = null;
16060
+ for (const start of candidates) {
16061
+ let dir = resolve17(start);
16062
+ for (let depth = 0;depth <= 10; depth++) {
16063
+ if (existsSync28(join23(dir, "tsconfig.json"))) {
16064
+ if (!best || depth < best.depth)
16065
+ best = { depth, root: dir };
16066
+ break;
16067
+ }
16068
+ const parent = dirname10(dir);
16069
+ if (parent === dir)
16070
+ break;
16071
+ dir = parent;
16072
+ }
16073
+ }
16074
+ return best?.root ?? null;
16075
+ }
16024
16076
  async function runTypecheck(baseDir) {
16025
16077
  const entry = processRegistry.start("npx --no-install tsc --noEmit --skipLibCheck", baseDir);
16026
16078
  const exited = await processRegistry.waitForExit(entry.id, 90000);
@@ -16051,11 +16103,11 @@ var init_audit_runners = __esm(() => {
16051
16103
  });
16052
16104
 
16053
16105
  // src/modules/execution/auditor.ts
16054
- import { existsSync as existsSync28, readdirSync as readdirSync9 } from "fs";
16055
- import { resolve as resolve17, join as join24, basename as basename2 } from "path";
16106
+ import { existsSync as existsSync29, readdirSync as readdirSync9 } from "fs";
16107
+ import { resolve as resolve18, join as join24, basename as basename2 } from "path";
16056
16108
  function findExistingFile(baseDir, filePath) {
16057
- const direct = resolve17(baseDir, filePath);
16058
- if (existsSync28(direct))
16109
+ const direct = resolve18(baseDir, filePath);
16110
+ if (existsSync29(direct))
16059
16111
  return direct;
16060
16112
  const name = basename2(filePath).toLowerCase();
16061
16113
  const suffix = filePath.replace(/\\/g, "/").toLowerCase();
@@ -16103,8 +16155,9 @@ class Auditor {
16103
16155
  const existingFiles = [];
16104
16156
  const leftoverFiles = [];
16105
16157
  for (const filePath of createFiles) {
16106
- if (findExistingFile(this.baseDir, filePath)) {
16107
- existingFiles.push(filePath);
16158
+ const resolved = findExistingFile(this.baseDir, filePath);
16159
+ if (resolved) {
16160
+ existingFiles.push(resolved);
16108
16161
  } else {
16109
16162
  missingFiles.push(filePath);
16110
16163
  }
@@ -16123,11 +16176,14 @@ class Auditor {
16123
16176
  }
16124
16177
  }
16125
16178
  let typecheckError = null;
16126
- if (missingFiles.length === 0 && leftoverFiles.length === 0 && existsSync28(join24(this.baseDir, "tsconfig.json"))) {
16127
- try {
16128
- typecheckError = await runTypecheck(this.baseDir);
16129
- } catch {
16130
- typecheckError = null;
16179
+ if (missingFiles.length === 0 && leftoverFiles.length === 0) {
16180
+ const root = findTypecheckRoot(this.baseDir, existingFiles);
16181
+ if (root) {
16182
+ try {
16183
+ typecheckError = await runTypecheck(root);
16184
+ } catch {
16185
+ typecheckError = null;
16186
+ }
16131
16187
  }
16132
16188
  }
16133
16189
  const doneSteps = plan.steps.filter((s) => s.status === "done").length;
@@ -16140,7 +16196,7 @@ class Auditor {
16140
16196
  count: String(auditedFiles.length)
16141
16197
  });
16142
16198
  }
16143
- const testsFailing = testRun !== null && testRun.failed > 0;
16199
+ const testsFailing = testRun !== null && !testRun.passed;
16144
16200
  const typecheckFailing = typecheckError !== null;
16145
16201
  const passed = missingFiles.length === 0 && leftoverFiles.length === 0 && !testsFailing && !typecheckFailing;
16146
16202
  const stepsPending = terminalSteps < totalSteps;
@@ -16206,7 +16262,7 @@ var init_auditor = __esm(() => {
16206
16262
  });
16207
16263
 
16208
16264
  // src/modules/execution/plan-store.ts
16209
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync29, readdirSync as readdirSync10, rmSync } from "fs";
16265
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync30, readdirSync as readdirSync10, rmSync } from "fs";
16210
16266
  import { join as join25 } from "path";
16211
16267
  function readPlanFile(path, fallbackBaseDir) {
16212
16268
  try {
@@ -16232,7 +16288,7 @@ function writePlanFile(path, plan) {
16232
16288
  writeFileSync10(path, JSON.stringify(plan, null, 2), "utf-8");
16233
16289
  }
16234
16290
  function listDir(dir, baseDir) {
16235
- if (!existsSync29(dir))
16291
+ if (!existsSync30(dir))
16236
16292
  return [];
16237
16293
  const files = readdirSync10(dir).filter((f) => f.endsWith(".json"));
16238
16294
  return files.map((f) => readPlanFile(join25(dir, f), baseDir)).filter((p) => p !== null);
@@ -16257,7 +16313,7 @@ class PlanStore {
16257
16313
  legacyPath;
16258
16314
  constructor(baseDir) {
16259
16315
  const mmaDir = join25(baseDir, ".mma");
16260
- if (!existsSync29(mmaDir))
16316
+ if (!existsSync30(mmaDir))
16261
16317
  mkdirSync14(mmaDir, { recursive: true });
16262
16318
  this.baseDir = baseDir;
16263
16319
  this.plansDir = join25(mmaDir, "plans");
@@ -16265,7 +16321,7 @@ class PlanStore {
16265
16321
  this.archiveDir = join25(this.plansDir, "archive");
16266
16322
  this.legacyPath = join25(mmaDir, LEGACY_FILE);
16267
16323
  for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
16268
- if (!existsSync29(dir))
16324
+ if (!existsSync30(dir))
16269
16325
  mkdirSync14(dir, { recursive: true });
16270
16326
  }
16271
16327
  }
@@ -16277,12 +16333,12 @@ class PlanStore {
16277
16333
  }
16278
16334
  loadActive() {
16279
16335
  const activePath = this.activePath();
16280
- if (existsSync29(activePath)) {
16336
+ if (existsSync30(activePath)) {
16281
16337
  const plan = readPlanFile(activePath, this.baseDir);
16282
16338
  if (plan)
16283
16339
  return plan;
16284
16340
  }
16285
- if (existsSync29(this.legacyPath)) {
16341
+ if (existsSync30(this.legacyPath)) {
16286
16342
  const legacy = readPlanFile(this.legacyPath, this.baseDir);
16287
16343
  if (legacy) {
16288
16344
  this.saveActive(legacy);
@@ -16296,7 +16352,7 @@ class PlanStore {
16296
16352
  }
16297
16353
  clearActive() {
16298
16354
  const p = this.activePath();
16299
- if (existsSync29(p))
16355
+ if (existsSync30(p))
16300
16356
  rmSync(p, { force: true });
16301
16357
  }
16302
16358
  saveDraft(plan) {
@@ -16304,11 +16360,11 @@ class PlanStore {
16304
16360
  }
16305
16361
  loadDraft(id) {
16306
16362
  const p = join25(this.draftsDir, `${id}.json`);
16307
- return existsSync29(p) ? readPlanFile(p, this.baseDir) : null;
16363
+ return existsSync30(p) ? readPlanFile(p, this.baseDir) : null;
16308
16364
  }
16309
16365
  removeDraft(id) {
16310
16366
  const p = join25(this.draftsDir, `${id}.json`);
16311
- if (existsSync29(p))
16367
+ if (existsSync30(p))
16312
16368
  rmSync(p, { force: true });
16313
16369
  }
16314
16370
  listDrafts() {
@@ -16327,7 +16383,7 @@ class PlanStore {
16327
16383
  }
16328
16384
  removeArchived(id) {
16329
16385
  const p = join25(this.archiveDir, `${id}.json`);
16330
- if (existsSync29(p))
16386
+ if (existsSync30(p))
16331
16387
  rmSync(p, { force: true });
16332
16388
  }
16333
16389
  listAll() {
@@ -17104,8 +17160,8 @@ var init_execution_plugin = __esm(() => {
17104
17160
  });
17105
17161
 
17106
17162
  // src/modules/execution/module.ts
17107
- import { existsSync as existsSync30, readFileSync as readFileSync17 } from "fs";
17108
- import { resolve as resolve18 } from "path";
17163
+ import { existsSync as existsSync31, readFileSync as readFileSync17 } from "fs";
17164
+ import { resolve as resolve19 } from "path";
17109
17165
 
17110
17166
  class ExecutionModule {
17111
17167
  name = "execution";
@@ -17299,7 +17355,7 @@ class ExecutionModule {
17299
17355
  "poetry.lock",
17300
17356
  "requirements.txt"
17301
17357
  ];
17302
- const hasLockFile = lockFiles.some((f) => existsSync30(resolve18(this.baseDir, f)));
17358
+ const hasLockFile = lockFiles.some((f) => existsSync31(resolve19(this.baseDir, f)));
17303
17359
  if (!hasLockFile) {
17304
17360
  if (contextManager) {
17305
17361
  const hints = this.state.depsGateHints.get(step.id) || 0;
@@ -17319,8 +17375,8 @@ class ExecutionModule {
17319
17375
  }
17320
17376
  if (stepPaths.length === 0)
17321
17377
  return;
17322
- const allExist = stepPaths.every((p) => existsSync30(resolve18(this.baseDir, p)));
17323
- const allGone = stepPaths.every((p) => !existsSync30(resolve18(this.baseDir, p)));
17378
+ const allExist = stepPaths.every((p) => existsSync31(resolve19(this.baseDir, p)));
17379
+ const allGone = stepPaths.every((p) => !existsSync31(resolve19(this.baseDir, p)));
17324
17380
  const satisfied = step.kind === "delete" ? allGone && !allExist : allExist;
17325
17381
  if (!satisfied)
17326
17382
  return;
@@ -17328,7 +17384,7 @@ class ExecutionModule {
17328
17384
  const emptyFiles = [];
17329
17385
  for (const p of stepPaths) {
17330
17386
  try {
17331
- const content = readFileSync17(resolve18(this.baseDir, p), "utf-8");
17387
+ const content = readFileSync17(resolve19(this.baseDir, p), "utf-8");
17332
17388
  if (content.trim().length < 10) {
17333
17389
  emptyFiles.push(p);
17334
17390
  }
@@ -17426,7 +17482,7 @@ var init_module = __esm(() => {
17426
17482
  import {
17427
17483
  readFileSync as readFileSync18,
17428
17484
  writeFileSync as writeFileSync11,
17429
- existsSync as existsSync31,
17485
+ existsSync as existsSync32,
17430
17486
  readdirSync as readdirSync11,
17431
17487
  unlinkSync as unlinkSync4
17432
17488
  } from "fs";
@@ -17526,7 +17582,7 @@ class SessionFileEncryptor {
17526
17582
  const files = readdirSync11(sessionDir);
17527
17583
  for (const file of files) {
17528
17584
  const filePath = join26(sessionDir, file);
17529
- if (existsSync31(filePath) && !file.endsWith(".enc")) {
17585
+ if (existsSync32(filePath) && !file.endsWith(".enc")) {
17530
17586
  try {
17531
17587
  const content = readFileSync18(filePath, "utf8");
17532
17588
  const encrypted = this.encryptFileContent(content);
@@ -17567,7 +17623,7 @@ var init_session_encryption = __esm(() => {
17567
17623
 
17568
17624
  // src/modules/session/store.ts
17569
17625
  import {
17570
- existsSync as existsSync32,
17626
+ existsSync as existsSync33,
17571
17627
  mkdirSync as mkdirSync15,
17572
17628
  readdirSync as readdirSync12,
17573
17629
  readFileSync as readFileSync19,
@@ -17617,7 +17673,7 @@ class SessionStore {
17617
17673
  return join27(this.sessionDir(id), "session.jsonl");
17618
17674
  }
17619
17675
  sessionExists(id) {
17620
- return existsSync32(this.metaPath(id));
17676
+ return existsSync33(this.metaPath(id));
17621
17677
  }
17622
17678
  saveMeta(id, meta) {
17623
17679
  this._metaCache.set(id, meta);
@@ -17635,7 +17691,7 @@ class SessionStore {
17635
17691
  if (cached)
17636
17692
  return cached;
17637
17693
  const path = this.metaPath(id);
17638
- if (!existsSync32(path))
17694
+ if (!existsSync33(path))
17639
17695
  return null;
17640
17696
  try {
17641
17697
  const raw = readFileSync19(path, "utf-8");
@@ -17667,7 +17723,7 @@ class SessionStore {
17667
17723
  }
17668
17724
  loadHistory(id) {
17669
17725
  const path = this.historyPath(id);
17670
- if (!existsSync32(path))
17726
+ if (!existsSync33(path))
17671
17727
  return [];
17672
17728
  try {
17673
17729
  const raw = readFileSync19(path, "utf-8");
@@ -17708,7 +17764,7 @@ class SessionStore {
17708
17764
  }
17709
17765
  loadSessionLog(id) {
17710
17766
  const path = this.sessionLogPath(id);
17711
- if (!existsSync32(path))
17767
+ if (!existsSync33(path))
17712
17768
  return [];
17713
17769
  try {
17714
17770
  const raw = readFileSync19(path, "utf-8");
@@ -17736,7 +17792,7 @@ class SessionStore {
17736
17792
  }
17737
17793
  }
17738
17794
  listSessions() {
17739
- if (!existsSync32(this.baseDir))
17795
+ if (!existsSync33(this.baseDir))
17740
17796
  return [];
17741
17797
  const entries = readdirSync12(this.baseDir, { withFileTypes: true });
17742
17798
  const sessions = [];
@@ -17753,7 +17809,7 @@ class SessionStore {
17753
17809
  deleteSession(id) {
17754
17810
  this._metaCache.delete(id);
17755
17811
  const dir = this.sessionDir(id);
17756
- if (existsSync32(dir)) {
17812
+ if (existsSync33(dir)) {
17757
17813
  rmSync2(dir, { recursive: true, force: true });
17758
17814
  }
17759
17815
  }
@@ -17765,7 +17821,7 @@ class SessionStore {
17765
17821
  const updatedAt = new Date(session2.updatedAt);
17766
17822
  if (updatedAt < thirtyDaysAgo) {
17767
17823
  const historyPath = this.historyPath(session2.id);
17768
- if (existsSync32(historyPath)) {
17824
+ if (existsSync33(historyPath)) {
17769
17825
  const content = readFileSync19(historyPath, "utf-8");
17770
17826
  const compressed = gzipSync(content);
17771
17827
  const gzPath = join27(this.baseDir, `${session2.id}.jsonl.gz`);
@@ -17978,7 +18034,7 @@ class ProfileCompressor {
17978
18034
  }
17979
18035
 
17980
18036
  // src/modules/user-profile/profile.ts
17981
- import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync33, mkdirSync as mkdirSync16 } from "fs";
18037
+ import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync34, mkdirSync as mkdirSync16 } from "fs";
17982
18038
  import { join as join28 } from "path";
17983
18039
  import { homedir as homedir9, hostname, platform as platform5, type } from "os";
17984
18040
  import { env } from "process";
@@ -18003,14 +18059,14 @@ class UserProfile {
18003
18059
  return this.info;
18004
18060
  }
18005
18061
  save() {
18006
- if (!existsSync33(this.profileDir)) {
18062
+ if (!existsSync34(this.profileDir)) {
18007
18063
  mkdirSync16(this.profileDir, { recursive: true });
18008
18064
  }
18009
18065
  writeFileSync13(join28(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
18010
18066
  }
18011
18067
  load() {
18012
18068
  const path = join28(this.profileDir, "profile.json");
18013
- if (!existsSync33(path))
18069
+ if (!existsSync34(path))
18014
18070
  return null;
18015
18071
  try {
18016
18072
  const data = JSON.parse(readFileSync20(path, "utf-8"));
@@ -18048,12 +18104,12 @@ class UserProfile {
18048
18104
  var init_profile = () => {};
18049
18105
 
18050
18106
  // src/modules/skills/loader.ts
18051
- import { readdirSync as readdirSync13, readFileSync as readFileSync21, existsSync as existsSync34, statSync as statSync6 } from "fs";
18107
+ import { readdirSync as readdirSync13, readFileSync as readFileSync21, existsSync as existsSync35, statSync as statSync6 } from "fs";
18052
18108
  import { join as join29 } from "path";
18053
18109
 
18054
18110
  class SkillsLoader {
18055
18111
  loadFromDir(dirPath) {
18056
- if (!existsSync34(dirPath))
18112
+ if (!existsSync35(dirPath))
18057
18113
  return [];
18058
18114
  const skills = [];
18059
18115
  this.scanDir(dirPath, skills);
@@ -18307,7 +18363,7 @@ var init_browser2 = __esm(() => {
18307
18363
 
18308
18364
  // src/modules/lsp/command.ts
18309
18365
  import { delimiter, join as join30 } from "path";
18310
- import { existsSync as existsSync35 } from "fs";
18366
+ import { existsSync as existsSync36 } from "fs";
18311
18367
  import { platform as platform6 } from "os";
18312
18368
  function resolveSpawnCommand(command, platformName = platform6(), pathEnv = process.env.PATH ?? "") {
18313
18369
  if (platformName !== "win32")
@@ -18319,7 +18375,7 @@ function resolveSpawnCommand(command, platformName = platform6(), pathEnv = proc
18319
18375
  for (const dir of dirs) {
18320
18376
  for (const ext of WIN_EXTS) {
18321
18377
  const candidate = join30(dir, `${command}${ext}`);
18322
- if (existsSync35(candidate))
18378
+ if (existsSync36(candidate))
18323
18379
  return `${command}${ext}`;
18324
18380
  }
18325
18381
  }
@@ -18341,11 +18397,8 @@ var init_command = __esm(() => {
18341
18397
  });
18342
18398
 
18343
18399
  // src/modules/lsp/client.ts
18344
- import {
18345
- spawn as spawn6,
18346
- execSync as execSync2
18347
- } from "child_process";
18348
- import { resolve as resolve19 } from "path";
18400
+ import { spawn as spawn6, execSync as execSync2 } from "child_process";
18401
+ import { resolve as resolve20 } from "path";
18349
18402
  import { platform as platform7 } from "os";
18350
18403
 
18351
18404
  class LspClient {
@@ -18363,25 +18416,32 @@ class LspClient {
18363
18416
  try {
18364
18417
  await this.startServer(config, projectRoot);
18365
18418
  const rootUri = this.pathToUri(projectRoot);
18366
- const initResult = await this.sendRequest("initialize", {
18419
+ const initParams = {
18367
18420
  processId: process.pid,
18368
18421
  rootUri,
18369
18422
  workspaceFolders: [{ uri: rootUri, name: "workspace" }],
18370
18423
  capabilities: { textDocument: { publishDiagnostics: {} } }
18371
- }, timeout);
18424
+ };
18425
+ try {
18426
+ await this.sendRequest("initialize", initParams, timeout);
18427
+ } catch (e) {
18428
+ if (!(e instanceof Error) || !e.message.includes("initialize"))
18429
+ throw e;
18430
+ await this.shutdown();
18431
+ await this.startServer(config, projectRoot);
18432
+ await this.sendRequest("initialize", initParams, timeout);
18433
+ }
18372
18434
  this.initialized = true;
18373
18435
  this.sendNotification("initialized", {});
18374
- const uri = this.pathToUri(resolve19(filePath));
18436
+ const uri = this.pathToUri(resolve20(filePath));
18375
18437
  const fs2 = await import("fs");
18376
18438
  const content = fs2.readFileSync(filePath, "utf-8");
18377
- const diagPromise = new Promise((resolve20) => {
18378
- this.diagnosticsResolve = resolve20;
18439
+ const diagPromise = new Promise((resolve21) => {
18440
+ this.diagnosticsResolve = resolve21;
18379
18441
  this.diagnostics = [];
18380
18442
  this.diagnosticsTimer = setTimeout(() => {
18381
- if (this.diagnosticsResolve) {
18382
- this.diagnosticsResolve([]);
18383
- this.diagnosticsResolve = null;
18384
- }
18443
+ this.diagnosticsResolve?.([]);
18444
+ this.diagnosticsResolve = null;
18385
18445
  }, timeout);
18386
18446
  });
18387
18447
  this.sendNotification("textDocument/didOpen", {
@@ -18407,7 +18467,7 @@ class LspClient {
18407
18467
  throw new Error(`${config.command} not found in PATH`);
18408
18468
  }
18409
18469
  }
18410
- return new Promise((resolve20, reject) => {
18470
+ return new Promise((resolve21, reject) => {
18411
18471
  const args = config.args ?? [];
18412
18472
  const isWin = platform7() === "win32";
18413
18473
  let spawnCommand = resolveSpawnCommand(config.command);
@@ -18429,13 +18489,12 @@ class LspClient {
18429
18489
  });
18430
18490
  proc.stderr.on("data", () => {});
18431
18491
  proc.once("spawn", () => {
18432
- resolve20();
18492
+ resolve21();
18433
18493
  });
18434
18494
  this.process = proc;
18435
18495
  setTimeout(() => {
18436
- if (!this.initialized && this.process) {
18496
+ if (!this.initialized && this.process)
18437
18497
  reject(new Error("LSP server start timeout"));
18438
- }
18439
18498
  }, config.timeout ?? 1e4);
18440
18499
  });
18441
18500
  }
@@ -18486,10 +18545,8 @@ class LspClient {
18486
18545
  clearTimeout(this.diagnosticsTimer);
18487
18546
  this.diagnosticsTimer = null;
18488
18547
  }
18489
- if (this.diagnosticsResolve) {
18490
- this.diagnosticsResolve(this.diagnostics);
18491
- this.diagnosticsResolve = null;
18492
- }
18548
+ this.diagnosticsResolve?.(this.diagnostics);
18549
+ this.diagnosticsResolve = null;
18493
18550
  }
18494
18551
  return;
18495
18552
  }
@@ -18506,9 +18563,9 @@ class LspClient {
18506
18563
  }
18507
18564
  }
18508
18565
  sendRequest(method, params, timeout) {
18509
- return new Promise((resolve20, reject) => {
18566
+ return new Promise((resolve21, reject) => {
18510
18567
  const id = ++this.requestId;
18511
- this.pending.set(id, { resolve: resolve20, reject });
18568
+ this.pending.set(id, { resolve: resolve21, reject });
18512
18569
  const message = JSON.stringify({ jsonrpc: "2.0", id, method, params });
18513
18570
  this.write(message);
18514
18571
  setTimeout(() => {
@@ -18548,6 +18605,8 @@ class LspClient {
18548
18605
  this.process = null;
18549
18606
  }
18550
18607
  this.initialized = false;
18608
+ this.buffer = "";
18609
+ this.contentLength = -1;
18551
18610
  if (this.diagnosticsTimer) {
18552
18611
  clearTimeout(this.diagnosticsTimer);
18553
18612
  this.diagnosticsTimer = null;
@@ -18556,10 +18615,7 @@ class LspClient {
18556
18615
  }
18557
18616
  pathToUri(filePath) {
18558
18617
  const normalized = filePath.replace(/\\/g, "/");
18559
- if (/^[a-zA-Z]:/.test(normalized)) {
18560
- return `file:///${normalized}`;
18561
- }
18562
- return `file://${normalized}`;
18618
+ return /^[a-zA-Z]:/.test(normalized) ? `file:///${normalized}` : `file://${normalized}`;
18563
18619
  }
18564
18620
  languageFromPath(filePath) {
18565
18621
  const ext = filePath.split(".").pop()?.toLowerCase();
@@ -18588,20 +18644,26 @@ var init_client2 = __esm(() => {
18588
18644
  });
18589
18645
 
18590
18646
  // src/modules/lsp/module.ts
18591
- import { existsSync as existsSync36 } from "fs";
18592
- import { resolve as resolve20 } from "path";
18647
+ import { existsSync as existsSync37 } from "fs";
18648
+ import { resolve as resolve21 } from "path";
18593
18649
 
18594
18650
  class LspModule {
18595
18651
  name = "lsp";
18596
18652
  config;
18597
18653
  client = new LspClient;
18598
- consecutiveFailures = 0;
18599
- lspDisabled = false;
18654
+ failuresByServer = new Map;
18655
+ disabledServers = new Set;
18600
18656
  constructor(config) {
18601
18657
  this.config = { ...DEFAULT_LSP_CONFIG, ...config };
18602
18658
  }
18603
18659
  isLspDisabled() {
18604
- return this.lspDisabled;
18660
+ return this.disabledServers.size > 0;
18661
+ }
18662
+ isServerDisabled(key) {
18663
+ return this.disabledServers.has(key);
18664
+ }
18665
+ serverKey(server) {
18666
+ return `${server.command}:${(server.args ?? []).join(" ")}`;
18605
18667
  }
18606
18668
  getPlugin() {
18607
18669
  const self = this;
@@ -18611,8 +18673,6 @@ class LspModule {
18611
18673
  onAfterTool: async (_ctx, call, result) => {
18612
18674
  if (!self.config.enabled)
18613
18675
  return;
18614
- if (self.lspDisabled)
18615
- return;
18616
18676
  if (call.name !== "write_file" && call.name !== "edit_file")
18617
18677
  return;
18618
18678
  if (!result.success)
@@ -18620,16 +18680,19 @@ class LspModule {
18620
18680
  const filePath = String(call.arguments.path ?? "");
18621
18681
  if (!filePath)
18622
18682
  return;
18623
- const fullPath = resolve20(_ctx.baseDir, filePath);
18624
- if (!existsSync36(fullPath))
18683
+ const fullPath = resolve21(_ctx.baseDir, filePath);
18684
+ if (!existsSync37(fullPath))
18625
18685
  return;
18626
18686
  const serverConfig = getServerForFile(fullPath, self.config);
18627
18687
  if (!serverConfig)
18628
18688
  return;
18689
+ const key = self.serverKey(serverConfig);
18690
+ if (self.disabledServers.has(key))
18691
+ return;
18629
18692
  const projectRoot = findProjectRoot(fullPath, _ctx.baseDir, serverConfig.workspaceMarkers ?? []);
18630
18693
  try {
18631
18694
  const diagnostics = await self.client.checkFile(fullPath, _ctx.baseDir, serverConfig, projectRoot);
18632
- self.consecutiveFailures = 0;
18695
+ self.failuresByServer.set(key, 0);
18633
18696
  const errors = diagnostics.filter((d) => d.severity === 1);
18634
18697
  const warnings = diagnostics.filter((d) => d.severity === 2);
18635
18698
  if (errors.length > 0) {
@@ -18648,12 +18711,13 @@ ${items}`;
18648
18711
  }
18649
18712
  } catch (e) {
18650
18713
  const msg = e instanceof Error ? e.message : String(e);
18651
- self.consecutiveFailures++;
18714
+ const failures = (self.failuresByServer.get(key) ?? 0) + 1;
18715
+ self.failuresByServer.set(key, failures);
18652
18716
  try {
18653
18717
  _ctx.logger?.warn(`LSP check failed for ${filePath}: ${msg}`);
18654
18718
  } catch {}
18655
- if (self.consecutiveFailures >= MAX_CONSECUTIVE_LSP_FAILURES) {
18656
- self.lspDisabled = true;
18719
+ if (failures >= MAX_CONSECUTIVE_LSP_FAILURES) {
18720
+ self.disabledServers.add(key);
18657
18721
  result.output += `
18658
18722
 
18659
18723
  [LSP disabled: ${t("lsp.unavailable")}]`;
@@ -18699,7 +18763,7 @@ var init_lsp = __esm(() => {
18699
18763
  });
18700
18764
 
18701
18765
  // src/modules/indexer/walker.ts
18702
- import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync37, watch } from "fs";
18766
+ import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync38, watch } from "fs";
18703
18767
  import { join as join31, relative as relative2, extname as extname5 } from "path";
18704
18768
 
18705
18769
  class Indexer {
@@ -18727,7 +18791,7 @@ class Indexer {
18727
18791
  let totalSize = 0;
18728
18792
  let count = 0;
18729
18793
  const walkDir = (dir) => {
18730
- if (!existsSync37(dir))
18794
+ if (!existsSync38(dir))
18731
18795
  return;
18732
18796
  let entries;
18733
18797
  try {
@@ -18801,7 +18865,7 @@ var init_walker = __esm(() => {
18801
18865
  });
18802
18866
 
18803
18867
  // src/modules/indexer/cache.ts
18804
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as existsSync38, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
18868
+ import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as existsSync39, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
18805
18869
  import { join as join32 } from "path";
18806
18870
 
18807
18871
  class IndexCache {
@@ -18813,7 +18877,7 @@ class IndexCache {
18813
18877
  load() {
18814
18878
  if (this.cache)
18815
18879
  return this.cache;
18816
- if (!existsSync38(this.cachePath))
18880
+ if (!existsSync39(this.cachePath))
18817
18881
  return null;
18818
18882
  try {
18819
18883
  this.cache = JSON.parse(readFileSync23(this.cachePath, "utf-8"));
@@ -18825,13 +18889,13 @@ class IndexCache {
18825
18889
  save(result) {
18826
18890
  this.cache = result;
18827
18891
  const dir = join32(this.cachePath, "..");
18828
- if (!existsSync38(dir))
18892
+ if (!existsSync39(dir))
18829
18893
  mkdirSync17(dir, { recursive: true });
18830
18894
  writeFileSync14(this.cachePath, JSON.stringify(result), "utf-8");
18831
18895
  }
18832
18896
  invalidate() {
18833
18897
  this.cache = null;
18834
- if (existsSync38(this.cachePath)) {
18898
+ if (existsSync39(this.cachePath)) {
18835
18899
  try {
18836
18900
  rmSync3(this.cachePath);
18837
18901
  } catch {}
@@ -18841,11 +18905,11 @@ class IndexCache {
18841
18905
  var init_cache = () => {};
18842
18906
 
18843
18907
  // src/modules/indexer/project-profile.ts
18844
- import { readFileSync as readFileSync24, existsSync as existsSync39 } from "fs";
18908
+ import { readFileSync as readFileSync24, existsSync as existsSync40 } from "fs";
18845
18909
  import { join as join33 } from "path";
18846
18910
  function detectManifest(baseDir) {
18847
18911
  for (const manifest of MANIFEST_ORDER) {
18848
- if (existsSync39(join33(baseDir, manifest)))
18912
+ if (existsSync40(join33(baseDir, manifest)))
18849
18913
  return manifest;
18850
18914
  }
18851
18915
  return null;
@@ -19009,7 +19073,7 @@ var init_project_profile = __esm(() => {
19009
19073
  });
19010
19074
 
19011
19075
  // src/modules/indexer/module.ts
19012
- import { dirname as dirname11 } from "path";
19076
+ import { dirname as dirname12 } from "path";
19013
19077
 
19014
19078
  class IndexerModule {
19015
19079
  name = "indexer";
@@ -19160,7 +19224,7 @@ ${t("indexer.and_more", { count: result.files.length - 100 })}` : "";
19160
19224
  const counts = {};
19161
19225
  for (const f of result.files) {
19162
19226
  const normalized = f.path.replace(/\\/g, "/");
19163
- const dir = dirname11(normalized);
19227
+ const dir = dirname12(normalized);
19164
19228
  const key = dir === "." ? "(root)" : dir;
19165
19229
  counts[key] = (counts[key] || 0) + 1;
19166
19230
  }
@@ -19499,8 +19563,8 @@ __export(exports_bootstrap, {
19499
19563
  bootstrap: () => bootstrap
19500
19564
  });
19501
19565
  import { homedir as homedir11 } from "os";
19502
- import { join as join35, resolve as resolve21 } from "path";
19503
- import { existsSync as existsSync40, readFileSync as readFileSync25, writeFileSync as writeFileSync15 } from "fs";
19566
+ import { join as join35, resolve as resolve22 } from "path";
19567
+ import { existsSync as existsSync41, readFileSync as readFileSync25, writeFileSync as writeFileSync15 } from "fs";
19504
19568
  function buildSystemInfo(config, baseDir, profileCompressed) {
19505
19569
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
19506
19570
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -19570,7 +19634,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19570
19634
  retry: config.retry,
19571
19635
  rateLimits: config.security?.rateLimits
19572
19636
  });
19573
- const baseDir = projectDir ? resolve21(projectDir) : process.cwd();
19637
+ const baseDir = projectDir ? resolve22(projectDir) : process.cwd();
19574
19638
  const projectMapCacheDir = join35(baseDir, ".mma");
19575
19639
  const indexerModule = new IndexerModule({
19576
19640
  baseDir,
@@ -19599,7 +19663,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19599
19663
  estimatedTokens: Math.ceil(systemInfoContent.length / 4)
19600
19664
  };
19601
19665
  const agentsMdGlobal = join35(dir, "AGENTS.md");
19602
- if (!existsSync40(agentsMdGlobal)) {
19666
+ if (!existsSync41(agentsMdGlobal)) {
19603
19667
  writeFileSync15(agentsMdGlobal, "", "utf-8");
19604
19668
  }
19605
19669
  const sessionDir = join35(dir, "sessions");
@@ -19744,7 +19808,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19744
19808
  join35(dir, "AGENTS.md")
19745
19809
  ];
19746
19810
  for (const p of agentsMdCandidates) {
19747
- if (existsSync40(p)) {
19811
+ if (existsSync41(p)) {
19748
19812
  const content = readFileSync25(p, "utf-8").trim();
19749
19813
  if (content) {
19750
19814
  agentsMdBlocks.push({
@@ -20377,10 +20441,10 @@ function menuList(items) {
20377
20441
  console.log(l);
20378
20442
  }
20379
20443
  function ask(rl, question, defaultValue) {
20380
- return new Promise((resolve22) => {
20444
+ return new Promise((resolve23) => {
20381
20445
  const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
20382
20446
  rl.question(prompt, (answer) => {
20383
- resolve22(answer.trim() || defaultValue || "");
20447
+ resolve23(answer.trim() || defaultValue || "");
20384
20448
  });
20385
20449
  });
20386
20450
  }
@@ -20599,12 +20663,12 @@ __export(exports_manifest, {
20599
20663
  getCertMark: () => getCertMark,
20600
20664
  MANIFEST_PATH: () => MANIFEST_PATH
20601
20665
  });
20602
- import { existsSync as existsSync41, readFileSync as readFileSync26, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
20666
+ import { existsSync as existsSync42, readFileSync as readFileSync26, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
20603
20667
  import { homedir as homedir13 } from "os";
20604
20668
  import { join as join37 } from "path";
20605
20669
  function readManifest(path = MANIFEST_PATH) {
20606
20670
  try {
20607
- if (existsSync41(path)) {
20671
+ if (existsSync42(path)) {
20608
20672
  const raw = JSON.parse(readFileSync26(path, "utf-8"));
20609
20673
  return { version: 1, certifications: raw.certifications ?? [] };
20610
20674
  }
@@ -27770,7 +27834,7 @@ var init_scenarios = __esm(() => {
27770
27834
  });
27771
27835
 
27772
27836
  // src/modules/certification/loader.ts
27773
- import { existsSync as existsSync42, readdirSync as readdirSync15, readFileSync as readFileSync27 } from "fs";
27837
+ import { existsSync as existsSync43, readdirSync as readdirSync15, readFileSync as readFileSync27 } from "fs";
27774
27838
  import { join as join38 } from "path";
27775
27839
  function validateScenario(s) {
27776
27840
  const errors2 = [];
@@ -27820,7 +27884,7 @@ function loadScenarios(userDir) {
27820
27884
  else
27821
27885
  scenarios.push(s);
27822
27886
  }
27823
- if (userDir && existsSync42(userDir)) {
27887
+ if (userDir && existsSync43(userDir)) {
27824
27888
  for (const file of readdirSync15(userDir)) {
27825
27889
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
27826
27890
  continue;
@@ -27878,7 +27942,7 @@ var init_loader3 = __esm(() => {
27878
27942
  });
27879
27943
 
27880
27944
  // src/modules/certification/fact-checker.ts
27881
- import { existsSync as existsSync43, readFileSync as readFileSync28, statSync as statSync8 } from "fs";
27945
+ import { existsSync as existsSync44, readFileSync as readFileSync28, statSync as statSync8 } from "fs";
27882
27946
  import { join as join39 } from "path";
27883
27947
  function checkSandbox(sandboxDir, checks, exitCode, output) {
27884
27948
  const failures = [];
@@ -27898,7 +27962,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
27898
27962
  case "fileExists":
27899
27963
  return isFile(join39(sandboxDir, check.path));
27900
27964
  case "fileNotExists":
27901
- return !existsSync43(join39(sandboxDir, check.path));
27965
+ return !existsSync44(join39(sandboxDir, check.path));
27902
27966
  case "dirExists":
27903
27967
  return isDir(join39(sandboxDir, check.path));
27904
27968
  case "fileContent": {
@@ -27924,14 +27988,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
27924
27988
  }
27925
27989
  function isFile(p) {
27926
27990
  try {
27927
- return existsSync43(p) && statSync8(p).isFile();
27991
+ return existsSync44(p) && statSync8(p).isFile();
27928
27992
  } catch {
27929
27993
  return false;
27930
27994
  }
27931
27995
  }
27932
27996
  function isDir(p) {
27933
27997
  try {
27934
- return existsSync43(p) && statSync8(p).isDirectory();
27998
+ return existsSync44(p) && statSync8(p).isDirectory();
27935
27999
  } catch {
27936
28000
  return false;
27937
28001
  }
@@ -27962,9 +28026,9 @@ var init_fact_checker = () => {};
27962
28026
 
27963
28027
  // src/modules/certification/runner.ts
27964
28028
  import { spawn as spawn7 } from "child_process";
27965
- import { existsSync as existsSync44, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
28029
+ import { existsSync as existsSync45, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
27966
28030
  import { platform as platform8 } from "os";
27967
- import { join as join40, resolve as resolve22, dirname as dirname12 } from "path";
28031
+ import { join as join40, resolve as resolve23, dirname as dirname13 } from "path";
27968
28032
  async function runScenario(scenario, opts) {
27969
28033
  if (scenario.mode === "skip") {
27970
28034
  return {
@@ -28045,27 +28109,27 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
28045
28109
  mkdirSync19(sandbox, { recursive: true });
28046
28110
  for (const f of scenario.fixtures ?? []) {
28047
28111
  const src = join40(mmaRoot, f.source);
28048
- if (!existsSync44(src)) {
28112
+ if (!existsSync45(src)) {
28049
28113
  throw new Error(`fixture missing: ${f.source}`);
28050
28114
  }
28051
28115
  const dest = join40(sandbox, f.dest);
28052
- mkdirSync19(dirname12(dest), { recursive: true });
28116
+ mkdirSync19(dirname13(dest), { recursive: true });
28053
28117
  cpSync2(src, dest);
28054
28118
  }
28055
28119
  }
28056
28120
  function resolveMmaEntry(mmaRoot) {
28057
28121
  const dev = join40(mmaRoot, "src", "cli", "main.ts");
28058
- if (existsSync44(dev))
28122
+ if (existsSync45(dev))
28059
28123
  return dev;
28060
28124
  return join40(mmaRoot, "dist", "main.js");
28061
28125
  }
28062
28126
  function findMmaRoot(fromDir) {
28063
28127
  const candidates = [
28064
- resolve22(fromDir, "..", "..", ".."),
28065
- resolve22(fromDir, "..")
28128
+ resolve23(fromDir, "..", "..", ".."),
28129
+ resolve23(fromDir, "..")
28066
28130
  ];
28067
28131
  for (const c of candidates) {
28068
- if (existsSync44(join40(c, "package.json")))
28132
+ if (existsSync45(join40(c, "package.json")))
28069
28133
  return c;
28070
28134
  }
28071
28135
  return process.cwd();
@@ -28133,13 +28197,13 @@ __export(exports_cli, {
28133
28197
  });
28134
28198
  import { rmSync as rmSync5 } from "fs";
28135
28199
  import { homedir as homedir14 } from "os";
28136
- import { join as join41, dirname as dirname13 } from "path";
28200
+ import { join as join41, dirname as dirname14 } from "path";
28137
28201
  import { fileURLToPath as fileURLToPath2 } from "url";
28138
- import { existsSync as existsSync45, readFileSync as readFileSync29 } from "fs";
28202
+ import { existsSync as existsSync46, readFileSync as readFileSync29 } from "fs";
28139
28203
  function readVersion() {
28140
28204
  const candidates = [join41(MMA_ROOT, "package.json")];
28141
28205
  for (const p of candidates) {
28142
- if (existsSync45(p)) {
28206
+ if (existsSync46(p)) {
28143
28207
  try {
28144
28208
  const raw = JSON.parse(readFileSync29(p, "utf-8"));
28145
28209
  if (raw.version)
@@ -28289,7 +28353,7 @@ var init_cli = __esm(() => {
28289
28353
  init_loader3();
28290
28354
  init_runner2();
28291
28355
  init_manifest();
28292
- HERE = dirname13(fileURLToPath2(import.meta.url));
28356
+ HERE = dirname14(fileURLToPath2(import.meta.url));
28293
28357
  MMA_ROOT = findMmaRoot(HERE);
28294
28358
  USER_SCENARIO_DIR = join41(homedir14(), ".mma", "certification", "scenarios");
28295
28359
  });
@@ -28300,18 +28364,18 @@ __export(exports_repl_commands, {
28300
28364
  registerAllCommands: () => registerAllCommands,
28301
28365
  COMMAND_GROUPS: () => COMMAND_GROUPS
28302
28366
  });
28303
- import { join as join43, dirname as dirname15 } from "path";
28367
+ import { join as join43, dirname as dirname16 } from "path";
28304
28368
  import { homedir as homedir16 } from "os";
28305
- import { existsSync as existsSync47, readFileSync as readFileSync31 } from "fs";
28369
+ import { existsSync as existsSync48, readFileSync as readFileSync31 } from "fs";
28306
28370
  import { fileURLToPath as fileURLToPath4 } from "url";
28307
28371
  function readVersion3() {
28308
- const here = dirname15(fileURLToPath4(import.meta.url));
28372
+ const here = dirname16(fileURLToPath4(import.meta.url));
28309
28373
  const candidates = [
28310
28374
  join43(here, "..", "..", "package.json"),
28311
28375
  join43(here, "..", "package.json")
28312
28376
  ];
28313
28377
  for (const p of candidates) {
28314
- if (existsSync47(p)) {
28378
+ if (existsSync48(p)) {
28315
28379
  try {
28316
28380
  const raw = JSON.parse(readFileSync31(p, "utf8"));
28317
28381
  if (raw.version)
@@ -28377,8 +28441,8 @@ function registerMmaCommands(ctx) {
28377
28441
  }
28378
28442
  try {
28379
28443
  const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
28380
- const { existsSync: existsSync48 } = await import("fs");
28381
- const { resolve: resolve23 } = await import("path");
28444
+ const { existsSync: existsSync49 } = await import("fs");
28445
+ const { resolve: resolve24 } = await import("path");
28382
28446
  let dataUrl;
28383
28447
  let label;
28384
28448
  if (source.toLowerCase() === "clipboard") {
@@ -28396,8 +28460,8 @@ function registerMmaCommands(ctx) {
28396
28460
  dataUrl = result.dataUrl;
28397
28461
  label = source;
28398
28462
  } else {
28399
- const absPath = resolve23(process.cwd(), source);
28400
- if (!existsSync48(absPath)) {
28463
+ const absPath = resolve24(process.cwd(), source);
28464
+ if (!existsSync49(absPath)) {
28401
28465
  console.log(pc2.red(t("image.not_found", { path: source })));
28402
28466
  return;
28403
28467
  }
@@ -28933,9 +28997,9 @@ init_bootstrap();
28933
28997
  init_config2();
28934
28998
  init_setup();
28935
28999
  init_i18n();
28936
- import { join as join42, dirname as dirname14 } from "path";
29000
+ import { join as join42, dirname as dirname15 } from "path";
28937
29001
  import { homedir as homedir15 } from "os";
28938
- import { existsSync as existsSync46, readFileSync as readFileSync30 } from "fs";
29002
+ import { existsSync as existsSync47, readFileSync as readFileSync30 } from "fs";
28939
29003
 
28940
29004
  // src/cli/security-commands.ts
28941
29005
  init_bootstrap();
@@ -29557,13 +29621,13 @@ function createSecurityCommand(program2) {
29557
29621
  // src/cli/commands.ts
29558
29622
  import { fileURLToPath as fileURLToPath3 } from "url";
29559
29623
  function readVersion2() {
29560
- const here = dirname14(fileURLToPath3(import.meta.url));
29624
+ const here = dirname15(fileURLToPath3(import.meta.url));
29561
29625
  const candidates = [
29562
29626
  join42(here, "..", "..", "package.json"),
29563
29627
  join42(here, "..", "package.json")
29564
29628
  ];
29565
29629
  for (const p of candidates) {
29566
- if (existsSync46(p)) {
29630
+ if (existsSync47(p)) {
29567
29631
  try {
29568
29632
  const raw = JSON.parse(readFileSync30(p, "utf8"));
29569
29633
  if (raw.version)
@@ -30510,8 +30574,8 @@ class LineEditor {
30510
30574
  }
30511
30575
 
30512
30576
  // src/cli/repl.ts
30513
- import { existsSync as existsSync48, readFileSync as readFileSync32, writeFileSync as writeFileSync17 } from "fs";
30514
- import { join as join44, dirname as dirname16 } from "path";
30577
+ import { existsSync as existsSync49, readFileSync as readFileSync32, writeFileSync as writeFileSync17 } from "fs";
30578
+ import { join as join44, dirname as dirname17 } from "path";
30515
30579
  import { homedir as homedir17 } from "os";
30516
30580
  import { fileURLToPath as fileURLToPath5 } from "url";
30517
30581
 
@@ -31015,13 +31079,13 @@ init_box();
31015
31079
  init_i18n();
31016
31080
  init_repl_commands();
31017
31081
  function readVersion4() {
31018
- const here = dirname16(fileURLToPath5(import.meta.url));
31082
+ const here = dirname17(fileURLToPath5(import.meta.url));
31019
31083
  const candidates = [
31020
31084
  join44(here, "..", "..", "package.json"),
31021
31085
  join44(here, "..", "package.json")
31022
31086
  ];
31023
31087
  for (const p of candidates) {
31024
- if (existsSync48(p)) {
31088
+ if (existsSync49(p)) {
31025
31089
  try {
31026
31090
  const raw = JSON.parse(readFileSync32(p, "utf8"));
31027
31091
  if (raw.version)
@@ -31115,7 +31179,7 @@ class Repl {
31115
31179
  this.setupListeners();
31116
31180
  }
31117
31181
  loadHistory() {
31118
- if (existsSync48(this.historyPath)) {
31182
+ if (existsSync49(this.historyPath)) {
31119
31183
  try {
31120
31184
  const raw = readFileSync32(this.historyPath, "utf-8");
31121
31185
  this.history = raw.split(`
@@ -31478,7 +31542,7 @@ ${t("image.clipboard_empty")}`));
31478
31542
  join44(this.baseDir, ".mma", "AGENTS.md"),
31479
31543
  join44(this.configDir, "AGENTS.md")
31480
31544
  ];
31481
- const foundAgents = agentsMdCandidates.filter((p) => existsSync48(p));
31545
+ const foundAgents = agentsMdCandidates.filter((p) => existsSync49(p));
31482
31546
  if (foundAgents.length > 0) {
31483
31547
  for (const p of foundAgents) {
31484
31548
  row(t("repl.agents_label"), pc2.dim(p));
@@ -31530,8 +31594,8 @@ init_setup();
31530
31594
  init_config2();
31531
31595
  init_i18n();
31532
31596
  init_colors();
31533
- import { existsSync as existsSync49, readFileSync as readFileSync33 } from "fs";
31534
- import { join as join45, dirname as dirname17 } from "path";
31597
+ import { existsSync as existsSync50, readFileSync as readFileSync33 } from "fs";
31598
+ import { join as join45, dirname as dirname18 } from "path";
31535
31599
  import { homedir as homedir18 } from "os";
31536
31600
  import { fileURLToPath as fileURLToPath6 } from "url";
31537
31601
 
@@ -31540,8 +31604,8 @@ init_command();
31540
31604
  import { platform as platform9 } from "os";
31541
31605
  var defaultRunner2 = async (command, args, options) => {
31542
31606
  const { execFile } = await import("child_process");
31543
- return new Promise((resolve23) => {
31544
- execFile(command, args, options, (err) => resolve23({ error: err?.message }));
31607
+ return new Promise((resolve24) => {
31608
+ execFile(command, args, options, (err) => resolve24({ error: err?.message }));
31545
31609
  });
31546
31610
  };
31547
31611
 
@@ -31693,13 +31757,13 @@ class UpdaterModule {
31693
31757
  }
31694
31758
  // src/cli/main.ts
31695
31759
  function readVersion5() {
31696
- const here = dirname17(fileURLToPath6(import.meta.url));
31760
+ const here = dirname18(fileURLToPath6(import.meta.url));
31697
31761
  const candidates = [
31698
31762
  join45(here, "..", "..", "package.json"),
31699
31763
  join45(here, "..", "package.json")
31700
31764
  ];
31701
31765
  for (const p of candidates) {
31702
- if (existsSync49(p)) {
31766
+ if (existsSync50(p)) {
31703
31767
  try {
31704
31768
  const raw = JSON.parse(readFileSync33(p, "utf8"));
31705
31769
  if (raw.version)
@@ -31773,7 +31837,7 @@ async function main() {
31773
31837
  process.exit(exitCode);
31774
31838
  } else {
31775
31839
  const configPath = join45(homedir18(), ".mma", "config.json");
31776
- if (!existsSync49(configPath)) {
31840
+ if (!existsSync50(configPath)) {
31777
31841
  console.log(pc2.yellow(`
31778
31842
  ` + t("cli.first_run") + `
31779
31843
  `));
package/package.json CHANGED
@@ -1,45 +1,45 @@
1
- {
2
- "name": "micro-models-agent",
3
- "version": "0.36.0",
4
- "description": "Micro Models Agent (MMA) — LLM agent harness for small models (Qwen3.5-9B, 32K-64K context)",
5
- "type": "module",
6
- "bin": {
7
- "mma": "bin/mma.mjs"
8
- },
9
- "files": [
10
- "dist/",
11
- "bin/"
12
- ],
13
- "engines": {
14
- "node": ">=20"
15
- },
16
- "scripts": {
17
- "mma": "bun run src/cli/main.ts",
18
- "build": "bun run build:tsc && bun run build:copy-assets",
19
- "build:tsc": "tsc -p tsconfig.build.json",
20
- "build:copy-assets": "bun run scripts/copy-assets.ts",
21
- "build:prod": "bun run 'build:bundle' && bun run 'build:copy-assets'",
22
- "build:clean": "cmd /c \"if exist dist rmdir /s /q dist\"",
23
- "build:bundle": "bun build ./src/cli/main.ts --outfile ./dist/main.js --target node --format esm --external playwright",
24
- "dev": "bun --watch src/cli/main.ts",
25
- "typecheck": "tsc --noEmit",
26
- "test": "bun test",
27
- "test:watch": "bun test --watch",
28
- "test:integration": "vitest run --config vitest.integration.config.ts"
29
- },
30
- "dependencies": {
31
- "commander": "^12.0.0",
32
- "js-tiktoken": "^1.0.0",
33
- "jsonrepair": "^3.15.0",
34
- "picocolors": "^1.1.1",
35
- "playwright": "^1.62.0",
36
- "string-width": "^8.2.2",
37
- "yaml": "^2.9.0"
38
- },
39
- "devDependencies": {
40
- "@types/bun": "^1.3.14",
41
- "@types/node": "^22.20.1",
42
- "typescript": "^5.9.3",
43
- "vitest": "^4.1.10"
44
- }
45
- }
1
+ {
2
+ "name": "micro-models-agent",
3
+ "version": "0.36.1",
4
+ "description": "Micro Models Agent (MMA) — LLM agent harness for small models (Qwen3.5-9B, 32K-64K context)",
5
+ "type": "module",
6
+ "bin": {
7
+ "mma": "bin/mma.mjs"
8
+ },
9
+ "files": [
10
+ "dist/",
11
+ "bin/"
12
+ ],
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "scripts": {
17
+ "mma": "bun run src/cli/main.ts",
18
+ "build": "bun run build:tsc && bun run build:copy-assets",
19
+ "build:tsc": "tsc -p tsconfig.build.json",
20
+ "build:copy-assets": "bun run scripts/copy-assets.ts",
21
+ "build:prod": "bun run 'build:bundle' && bun run 'build:copy-assets'",
22
+ "build:clean": "cmd /c \"if exist dist rmdir /s /q dist\"",
23
+ "build:bundle": "bun build ./src/cli/main.ts --outfile ./dist/main.js --target node --format esm --external playwright",
24
+ "dev": "bun --watch src/cli/main.ts",
25
+ "typecheck": "tsc --noEmit",
26
+ "test": "bun test",
27
+ "test:watch": "bun test --watch",
28
+ "test:integration": "vitest run --config vitest.integration.config.ts"
29
+ },
30
+ "dependencies": {
31
+ "commander": "^12.0.0",
32
+ "js-tiktoken": "^1.0.0",
33
+ "jsonrepair": "^3.15.0",
34
+ "picocolors": "^1.1.1",
35
+ "playwright": "^1.62.0",
36
+ "string-width": "^8.2.2",
37
+ "yaml": "^2.9.0"
38
+ },
39
+ "devDependencies": {
40
+ "@types/bun": "^1.3.14",
41
+ "@types/node": "^22.20.1",
42
+ "typescript": "^5.9.3",
43
+ "vitest": "^4.1.10"
44
+ }
45
+ }