micro-models-agent 0.35.2 → 0.35.4

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 +595 -435
  2. package/package.json +3 -3
package/dist/main.js CHANGED
@@ -2096,47 +2096,55 @@ var init_config = __esm(() => {
2096
2096
  command: "npx",
2097
2097
  args: ["typescript-language-server", "--stdio"],
2098
2098
  timeout: 20000,
2099
- autoInstall: true
2099
+ autoInstall: true,
2100
+ workspaceMarkers: ["package.json", "tsconfig.json"]
2100
2101
  },
2101
2102
  javascript: {
2102
2103
  command: "npx",
2103
2104
  args: ["typescript-language-server", "--stdio"],
2104
2105
  timeout: 15000,
2105
- autoInstall: true
2106
+ autoInstall: true,
2107
+ workspaceMarkers: ["package.json", "tsconfig.json"]
2106
2108
  },
2107
2109
  python: {
2108
2110
  command: "npx",
2109
2111
  args: ["pyright", "--stdio"],
2110
2112
  timeout: 15000,
2111
- autoInstall: true
2113
+ autoInstall: true,
2114
+ workspaceMarkers: ["pyproject.toml", "setup.py", "requirements.txt"]
2112
2115
  },
2113
2116
  rust: {
2114
2117
  command: "rust-analyzer",
2115
2118
  timeout: 15000,
2116
- autoInstall: false
2119
+ autoInstall: false,
2120
+ workspaceMarkers: ["Cargo.toml"]
2117
2121
  },
2118
2122
  go: {
2119
2123
  command: "gopls",
2120
2124
  timeout: 15000,
2121
- autoInstall: false
2125
+ autoInstall: false,
2126
+ workspaceMarkers: ["go.mod"]
2122
2127
  },
2123
2128
  json: {
2124
2129
  command: "npx",
2125
2130
  args: ["vscode-json-languageserver", "--stdio"],
2126
2131
  timeout: 1e4,
2127
- autoInstall: true
2132
+ autoInstall: true,
2133
+ workspaceMarkers: ["package.json"]
2128
2134
  },
2129
2135
  html: {
2130
2136
  command: "npx",
2131
2137
  args: ["vscode-html-languageserver", "--stdio"],
2132
2138
  timeout: 1e4,
2133
- autoInstall: true
2139
+ autoInstall: true,
2140
+ workspaceMarkers: ["package.json"]
2134
2141
  },
2135
2142
  css: {
2136
2143
  command: "npx",
2137
2144
  args: ["vscode-css-languageserver", "--stdio"],
2138
2145
  timeout: 1e4,
2139
- autoInstall: true
2146
+ autoInstall: true,
2147
+ workspaceMarkers: ["package.json"]
2140
2148
  }
2141
2149
  }
2142
2150
  };
@@ -2487,6 +2495,7 @@ Command: {command}`,
2487
2495
  "verify.script_passed": "Script '{script}' passed",
2488
2496
  "verify.script_failed": "Script '{script}' failed: {message}",
2489
2497
  "verify.syntax_error": "Syntax error in: {path}",
2498
+ "lsp.unavailable": "static checks are unavailable (server not found). Verify via the project's own build/test instead.",
2490
2499
  "cli.description": "Micro Models Agent — AI coding agent for small models",
2491
2500
  "cli.init": "Run interactive setup wizard",
2492
2501
  "cli.config_saved": "Configuration saved to ~/.mma/config.json",
@@ -2830,6 +2839,7 @@ Use this knowledge to answer the user's question.`,
2830
2839
  "indexer.find_results": `Found {count} matching files:
2831
2840
  {results}`,
2832
2841
  "indexer.no_matches": 'No matching files for "{query}"',
2842
+ "indexer.duplicates": "Duplicate basenames (verify which file is the real source): {names}",
2833
2843
  "indexer.stack_deps": "deps",
2834
2844
  "indexer.stack_dev": "dev",
2835
2845
  "indexer.stack_scripts": "scripts",
@@ -3077,6 +3087,7 @@ var init_ru = __esm(() => {
3077
3087
  "verify.script_passed": "Скрипт '{script}' пройден",
3078
3088
  "verify.script_failed": "Скрипт '{script}' не пройден: {message}",
3079
3089
  "verify.syntax_error": "Синтаксическая ошибка в: {path}",
3090
+ "lsp.unavailable": "статические проверки недоступны (сервер не найден). Проверяйте через собственный build/test проекта.",
3080
3091
  "cli.description": "Micro Models Agent — ИИ-агент для кодинга на малых моделях",
3081
3092
  "cli.init": "Запустить мастер настройки",
3082
3093
  "cli.config_saved": "Конфигурация сохранена в ~/.mma/config.json",
@@ -3420,6 +3431,7 @@ var init_ru = __esm(() => {
3420
3431
  "indexer.find_results": `Найдено {count} совпадающих файлов:
3421
3432
  {results}`,
3422
3433
  "indexer.no_matches": 'Нет совпадающих файлов для "{query}"',
3434
+ "indexer.duplicates": "Дубликаты basename (проверьте, какой файл реально используется): {names}",
3423
3435
  "indexer.stack_deps": "зависимости",
3424
3436
  "indexer.stack_dev": "dev",
3425
3437
  "indexer.stack_scripts": "скрипты",
@@ -5351,7 +5363,8 @@ class ToolRegistry {
5351
5363
  return tools.map((t2) => ({
5352
5364
  name: t2.name,
5353
5365
  description: t2.description,
5354
- parameters: t2.parameters
5366
+ parameters: t2.parameters,
5367
+ boundedOutput: t2.boundedOutput
5355
5368
  }));
5356
5369
  }
5357
5370
  }
@@ -6056,6 +6069,7 @@ var init_read_file = __esm(() => {
6056
6069
  name: "read_file",
6057
6070
  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.`,
6058
6071
  tags: ["file", "code"],
6072
+ boundedOutput: true,
6059
6073
  parameters: {
6060
6074
  type: "object",
6061
6075
  properties: {
@@ -6688,6 +6702,7 @@ var init_list_dir = __esm(() => {
6688
6702
  name: "list_dir",
6689
6703
  description: `List files and directories in a given path. Shows up to ${MAX_PREVIEW_LINES} entries by default.`,
6690
6704
  tags: ["file"],
6705
+ boundedOutput: true,
6691
6706
  parameters: {
6692
6707
  type: "object",
6693
6708
  properties: {
@@ -6932,6 +6947,7 @@ var init_file_info = __esm(() => {
6932
6947
  name: "file_info",
6933
6948
  description: "Get metadata about a file or directory (size, creation date, modification date).",
6934
6949
  tags: ["file"],
6950
+ boundedOutput: true,
6935
6951
  parameters: {
6936
6952
  type: "object",
6937
6953
  properties: {
@@ -7290,7 +7306,7 @@ class ProcessRegistry {
7290
7306
  entry.status = "killed";
7291
7307
  }
7292
7308
  entry.spawnError = err.message;
7293
- append(Buffer.from(`[process error] ${err.message}`));
7309
+ pushLine(`[process error] ${err.message}`);
7294
7310
  resolveExit();
7295
7311
  });
7296
7312
  child.on("close", (code) => {
@@ -7689,19 +7705,19 @@ ${output2}`;
7689
7705
  output2 = `(exit code ${code})`;
7690
7706
  }
7691
7707
  if (platform2() === "win32") {
7692
- const firstWord = command.trim().split(/\s+/)[0]?.split(/[\\/]/).pop();
7693
- if (firstWord && firstWord in UNIX_TO_WIN_HINTS) {
7708
+ const originalFirstWord = originalCommand.trim().split(/\s+/)[0]?.split(/[\\/]/).pop();
7709
+ if (originalFirstWord && originalFirstWord in UNIX_TO_WIN_HINTS) {
7694
7710
  if (code === 0) {
7695
- FAILING_FIRST_WORDS.delete(firstWord);
7711
+ FAILING_FIRST_WORDS.delete(originalFirstWord);
7696
7712
  } else {
7697
- const failures = (FAILING_FIRST_WORDS.get(firstWord) || 0) + 1;
7698
- FAILING_FIRST_WORDS.set(firstWord, failures);
7713
+ const failures = (FAILING_FIRST_WORDS.get(originalFirstWord) || 0) + 1;
7714
+ FAILING_FIRST_WORDS.set(originalFirstWord, failures);
7699
7715
  if (failures >= HARD_BLOCK_THRESHOLD) {
7700
- output2 = `STOP using "${firstWord}" — it does not work in this cmd.exe shell and has failed ${failures} times in a row. ${UNIX_TO_WIN_HINTS[firstWord]}`;
7716
+ output2 = `STOP using "${originalFirstWord}" — it does not work in this cmd.exe shell and has failed ${failures} times in a row. ${UNIX_TO_WIN_HINTS[originalFirstWord]}`;
7701
7717
  } else {
7702
7718
  output2 = `${output2}
7703
7719
 
7704
- Hint: "${firstWord}" may not work on Windows. ${UNIX_TO_WIN_HINTS[firstWord]}`;
7720
+ Hint: "${originalFirstWord}" may not work on Windows. ${UNIX_TO_WIN_HINTS[originalFirstWord]}`;
7705
7721
  }
7706
7722
  }
7707
7723
  }
@@ -7801,6 +7817,7 @@ var init_process_log = __esm(() => {
7801
7817
  name: "process_log",
7802
7818
  description: `Show the buffered output of a background process started via bash. Shows the last ${DEFAULT_TAIL} lines by default. Use after starting a dev server to verify it came up without errors, and while it runs to check its state.`,
7803
7819
  tags: ["shell"],
7820
+ boundedOutput: true,
7804
7821
  parameters: {
7805
7822
  type: "object",
7806
7823
  properties: {
@@ -9941,9 +9958,31 @@ var init_moe_executor = __esm(() => {
9941
9958
  ];
9942
9959
  });
9943
9960
 
9944
- // src/modules/execution/verifier.ts
9961
+ // src/modules/lsp/project-root.ts
9945
9962
  import { existsSync as existsSync19 } from "fs";
9946
- import { resolve as resolve11, extname as extname2 } from "path";
9963
+ import { dirname as dirname6, join as join10 } from "path";
9964
+ function findProjectRoot(filePath, baseDir, markers) {
9965
+ if (!markers || markers.length === 0)
9966
+ return baseDir;
9967
+ let dir = dirname6(filePath);
9968
+ const root = baseDir.replace(/[\\/]+$/, "");
9969
+ while (true) {
9970
+ if (markers.some((m) => existsSync19(join10(dir, m)))) {
9971
+ return dir;
9972
+ }
9973
+ if (dir === root)
9974
+ return dir;
9975
+ const parent = dirname6(dir);
9976
+ if (parent === dir)
9977
+ return root;
9978
+ dir = parent;
9979
+ }
9980
+ }
9981
+ var init_project_root = () => {};
9982
+
9983
+ // src/modules/execution/verifier.ts
9984
+ import { existsSync as existsSync20 } from "fs";
9985
+ import { resolve as resolve11, extname as extname2, join as join11 } from "path";
9947
9986
  import { spawn as spawn2 } from "child_process";
9948
9987
 
9949
9988
  class StepVerifier {
@@ -9953,7 +9992,7 @@ class StepVerifier {
9953
9992
  }
9954
9993
  async checkFileExists(path) {
9955
9994
  const resolved = resolve11(this.baseDir, path);
9956
- const exists = existsSync19(resolved);
9995
+ const exists = existsSync20(resolved);
9957
9996
  return {
9958
9997
  passed: exists,
9959
9998
  message: exists ? t("verify.file_exists", { path }) : t("verify.file_not_found", { path })
@@ -9969,7 +10008,7 @@ class StepVerifier {
9969
10008
  }
9970
10009
  async runTypeCheck() {
9971
10010
  const tsconfigPath = resolve11(this.baseDir, "tsconfig.json");
9972
- if (!existsSync19(tsconfigPath)) {
10011
+ if (!existsSync20(tsconfigPath)) {
9973
10012
  return { passed: true, message: "No tsconfig.json found — skipping type check" };
9974
10013
  }
9975
10014
  try {
@@ -9980,9 +10019,26 @@ class StepVerifier {
9980
10019
  return { passed: false, message: `TypeScript type check failed: ${stderr.slice(0, 500)}` };
9981
10020
  }
9982
10021
  }
10022
+ async runTypeCheckForFile(filePath) {
10023
+ const projectRoot = findProjectRoot(filePath, this.baseDir, [
10024
+ "tsconfig.json",
10025
+ "package.json"
10026
+ ]);
10027
+ const tsconfigPath = join11(projectRoot, "tsconfig.json");
10028
+ if (!existsSync20(tsconfigPath)) {
10029
+ return { passed: true, message: "No tsconfig.json found — skipping type check" };
10030
+ }
10031
+ try {
10032
+ await this.runAsync("npx tsc --noEmit --skipLibCheck", projectRoot, 60000);
10033
+ return { passed: true, message: "TypeScript type check passed" };
10034
+ } catch (e) {
10035
+ const stderr = e.stderr?.toString() || e.stdout?.toString() || e.message;
10036
+ return { passed: false, message: `TypeScript type check failed: ${stderr.slice(0, 500)}` };
10037
+ }
10038
+ }
9983
10039
  async runTests() {
9984
10040
  const pkgPath = resolve11(this.baseDir, "package.json");
9985
- if (!existsSync19(pkgPath)) {
10041
+ if (!existsSync20(pkgPath)) {
9986
10042
  return { passed: true, message: "No package.json found — skipping tests" };
9987
10043
  }
9988
10044
  try {
@@ -10115,6 +10171,7 @@ class StepVerifier {
10115
10171
  }
10116
10172
  var init_verifier = __esm(() => {
10117
10173
  init_i18n();
10174
+ init_project_root();
10118
10175
  });
10119
10176
 
10120
10177
  // src/core/agent-moe.ts
@@ -10231,132 +10288,7 @@ var init_agent_moe = __esm(() => {
10231
10288
  init_verifier();
10232
10289
  });
10233
10290
 
10234
- // src/modules/memory/search.ts
10235
- import { readFileSync as readFileSync10, existsSync as existsSync20 } from "fs";
10236
- import { join as join10 } from "path";
10237
-
10238
- class MemorySearch {
10239
- memoryDir;
10240
- constructor(memoryDir) {
10241
- this.memoryDir = memoryDir;
10242
- }
10243
- query(query) {
10244
- const results = [];
10245
- const lowerQuery = query.toLowerCase();
10246
- for (const name of MEMORY_FILES) {
10247
- const path = join10(this.memoryDir, `${name}.md`);
10248
- if (!existsSync20(path))
10249
- continue;
10250
- const content = readFileSync10(path, "utf-8");
10251
- const lines = content.split(`
10252
- `);
10253
- for (const line of lines) {
10254
- if (line.toLowerCase().includes(lowerQuery)) {
10255
- results.push({ file: name, match: line.trim() });
10256
- }
10257
- }
10258
- }
10259
- const prefsPath = join10(this.memoryDir, "preferences.json");
10260
- if (existsSync20(prefsPath)) {
10261
- try {
10262
- const prefs = JSON.parse(readFileSync10(prefsPath, "utf-8"));
10263
- for (const [key, value] of Object.entries(prefs)) {
10264
- const searchStr = `${key}=${value}`;
10265
- if (searchStr.toLowerCase().includes(lowerQuery)) {
10266
- results.push({ file: "preferences", match: `${key} = ${value}` });
10267
- }
10268
- }
10269
- } catch {}
10270
- }
10271
- return results;
10272
- }
10273
- }
10274
- var MEMORY_FILES;
10275
- var init_search = __esm(() => {
10276
- MEMORY_FILES = ["conventions", "decisions", "errors", "facts"];
10277
- });
10278
-
10279
- // src/modules/memory/store.ts
10280
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, appendFileSync as appendFileSync5, existsSync as existsSync21, mkdirSync as mkdirSync12 } from "fs";
10281
- import { join as join11 } from "path";
10282
-
10283
- class MemoryStore {
10284
- memoryDir;
10285
- constructor(memoryDir) {
10286
- this.memoryDir = memoryDir;
10287
- this.ensureDir();
10288
- for (const name of MEMORY_FILES2) {
10289
- const path = join11(this.memoryDir, `${name}.md`);
10290
- if (!existsSync21(path)) {
10291
- writeFileSync8(path, `# ${name.charAt(0).toUpperCase() + name.slice(1)}
10292
-
10293
- `, "utf-8");
10294
- }
10295
- }
10296
- }
10297
- ensureDir() {
10298
- if (!existsSync21(this.memoryDir)) {
10299
- mkdirSync12(this.memoryDir, { recursive: true });
10300
- }
10301
- }
10302
- read(name) {
10303
- const path = join11(this.memoryDir, `${name}.md`);
10304
- if (!existsSync21(path))
10305
- return "";
10306
- return readFileSync11(path, "utf-8");
10307
- }
10308
- append(name, entry) {
10309
- const path = join11(this.memoryDir, `${name}.md`);
10310
- const timestamp = new Date().toISOString().replace("T", " ").slice(0, 19);
10311
- const formatted = `- **${timestamp}** — ${entry}
10312
- `;
10313
- appendFileSync5(path, formatted, "utf-8");
10314
- }
10315
- search(query) {
10316
- const searchModule = new MemorySearch(this.memoryDir);
10317
- return searchModule.query(query);
10318
- }
10319
- prefsPath() {
10320
- return join11(this.memoryDir, "preferences.json");
10321
- }
10322
- getPreferences() {
10323
- const path = this.prefsPath();
10324
- if (!existsSync21(path))
10325
- return {};
10326
- try {
10327
- return JSON.parse(readFileSync11(path, "utf-8"));
10328
- } catch {
10329
- return {};
10330
- }
10331
- }
10332
- setPreference(key, value) {
10333
- const prefs = this.getPreferences();
10334
- prefs[key] = value;
10335
- writeFileSync8(this.prefsPath(), JSON.stringify(prefs, null, 2), "utf-8");
10336
- }
10337
- deletePreference(key) {
10338
- const prefs = this.getPreferences();
10339
- if (!(key in prefs))
10340
- return false;
10341
- delete prefs[key];
10342
- writeFileSync8(this.prefsPath(), JSON.stringify(prefs, null, 2), "utf-8");
10343
- return true;
10344
- }
10345
- appendRule(category, pattern, cause, solution) {
10346
- const entry = `**pattern:** ${pattern}
10347
- **cause:** ${cause}
10348
- **solution:** ${solution}`;
10349
- this.append(category, entry);
10350
- }
10351
- }
10352
- var MEMORY_FILES2;
10353
- var init_store2 = __esm(() => {
10354
- init_search();
10355
- MEMORY_FILES2 = ["conventions", "decisions", "errors", "facts"];
10356
- });
10357
-
10358
10291
  // src/core/agent.ts
10359
- import { join as join12 } from "path";
10360
10292
  function isToolCallJson(text) {
10361
10293
  const trimmed = text.trim();
10362
10294
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
@@ -10369,6 +10301,12 @@ function isToolCallJson(text) {
10369
10301
  }
10370
10302
  return false;
10371
10303
  }
10304
+ function toolOutputCharLimit(remainingBudget, historyBudget, bounded) {
10305
+ if (bounded)
10306
+ return Number.MAX_SAFE_INTEGER;
10307
+ const maxCharsByRatio = Math.floor(historyBudget * TOOL_RESULT_MAX_TOKENS_RATIO * 2);
10308
+ return Math.min(remainingBudget, maxCharsByRatio, TOOL_RESULT_ABSOLUTE_MAX_CHARS);
10309
+ }
10372
10310
 
10373
10311
  class Agent {
10374
10312
  deps;
@@ -10432,11 +10370,9 @@ class Agent {
10432
10370
  this.deps.contextManager.updateSystemPrompt?.(prompt);
10433
10371
  }
10434
10372
  }
10435
- truncateToolOutput(output, budget, currentTokens) {
10436
- const remainingBudget = budget.history - currentTokens;
10437
- const maxCharsByBudget = Math.floor(remainingBudget * 0.5 * 2);
10438
- const maxCharsByRatio = Math.floor(budget.history * TOOL_RESULT_MAX_TOKENS_RATIO * 2);
10439
- const maxChars = Math.min(maxCharsByBudget, maxCharsByRatio, TOOL_RESULT_ABSOLUTE_MAX_CHARS);
10373
+ truncateToolOutput(output, budget, currentTokens, bounded) {
10374
+ const remainingBudget = Math.max(0, budget.history - currentTokens);
10375
+ const maxChars = toolOutputCharLimit(remainingBudget, budget.history, bounded);
10440
10376
  if (output.length <= maxChars)
10441
10377
  return output;
10442
10378
  const truncated = output.slice(0, maxChars);
@@ -10546,6 +10482,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
10546
10482
  let repeatedToolCount = 0;
10547
10483
  const MAX_REPEATED_TOOL_CALLS = 2;
10548
10484
  const allToolsForBudget = toolExecutor.getToolDefinitions(this.deps.toolTags);
10485
+ const boundedToolNames = new Set(allToolsForBudget.filter((t2) => t2.boundedOutput).map((t2) => t2.name));
10549
10486
  const toolTokenEstimate = allToolsForBudget.reduce((sum, t2) => sum + Math.ceil((t2.description.length + JSON.stringify(t2.parameters).length) / 4), 0);
10550
10487
  contextManager.setToolTokens(toolTokenEstimate);
10551
10488
  while (iteration < config.maxToolIterations && !this.shutdownRequested) {
@@ -10748,7 +10685,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
10748
10685
  }
10749
10686
  const currentTokens2 = contextManager.getEstimatedTokens();
10750
10687
  const budget3 = contextManager.getBudget();
10751
- const truncatedOutput = this.truncateToolOutput(result.output, budget3, currentTokens2);
10688
+ const truncatedOutput = this.truncateToolOutput(result.output, budget3, currentTokens2, boundedToolNames.has(call.name));
10752
10689
  contextManager.addMessage({
10753
10690
  role: "tool",
10754
10691
  content: truncatedOutput,
@@ -10782,14 +10719,10 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
10782
10719
  toolFailureCounts.set(key, prev);
10783
10720
  if (prev.count >= MIN_REPEATED_TOOL_FAILURES && !memoryRuleRecorded.has(key)) {
10784
10721
  memoryRuleRecorded.add(key);
10785
- if (sessionManager) {
10786
- const activeSession = sessionManager.getActiveMeta();
10787
- if (activeSession) {
10788
- const memDir = join12(baseDir, ".mma", "memory");
10789
- const memStore = new MemoryStore(memDir);
10790
- 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");
10791
- logger.warn(`Recorded repeated ${key} failures to memory (${prev.count}x)`);
10792
- }
10722
+ const memStore = this.deps.memoryStore;
10723
+ if (memStore) {
10724
+ 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");
10725
+ logger.warn(`Recorded repeated ${key} failures to memory (${prev.count}x)`);
10793
10726
  }
10794
10727
  }
10795
10728
  }
@@ -10811,13 +10744,9 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
10811
10744
  content: `<system-summary>${recoveryMsg}
10812
10745
  ${taskReminder}</system-summary>`
10813
10746
  });
10814
- if (sessionManager) {
10815
- const activeSession = sessionManager.getActiveMeta();
10816
- if (activeSession) {
10817
- const memDir = join12(baseDir, ".mma", "memory");
10818
- const memStore = new MemoryStore(memDir);
10819
- memStore.appendRule("errors", `${consecutiveToolFailures} consecutive tool failures`, "Multiple tools failing suggests environment or configuration issue", "Check dependencies, verify file paths, try write_file directly instead of shell commands");
10820
- }
10747
+ const memStore = this.deps.memoryStore;
10748
+ if (memStore) {
10749
+ memStore.appendRule("errors", `${consecutiveToolFailures} consecutive tool failures`, "Multiple tools failing suggests environment or configuration issue", "Check dependencies, verify file paths, try write_file directly instead of shell commands");
10821
10750
  }
10822
10751
  }
10823
10752
  contextManager.addMessage({
@@ -11077,7 +11006,6 @@ var init_agent = __esm(() => {
11077
11006
  init_processes();
11078
11007
  init_session_logger();
11079
11008
  init_agent_moe();
11080
- init_store2();
11081
11009
  init_verifier();
11082
11010
  });
11083
11011
 
@@ -11705,8 +11633,8 @@ var init_js_identifiers = __esm(() => {
11705
11633
  });
11706
11634
 
11707
11635
  // src/modules/hallucination/factual.ts
11708
- import { existsSync as existsSync22, readdirSync as readdirSync5 } from "fs";
11709
- import { resolve as resolve12, isAbsolute as isAbsolute2, join as join13 } from "path";
11636
+ import { existsSync as existsSync21, readdirSync as readdirSync5 } from "fs";
11637
+ import { resolve as resolve12, isAbsolute as isAbsolute2, join as join12 } from "path";
11710
11638
 
11711
11639
  class FactualCheck {
11712
11640
  baseDir;
@@ -11741,14 +11669,14 @@ class FactualCheck {
11741
11669
  }
11742
11670
  pathExists(fp) {
11743
11671
  if (isAbsolute2(fp))
11744
- return existsSync22(fp);
11672
+ return existsSync21(fp);
11745
11673
  if (!fp.includes("/") && !fp.includes("\\")) {
11746
11674
  return this.bareNameExists(fp);
11747
11675
  }
11748
- return existsSync22(resolve12(this.baseDir, fp));
11676
+ return existsSync21(resolve12(this.baseDir, fp));
11749
11677
  }
11750
11678
  bareNameExists(name) {
11751
- if (existsSync22(resolve12(this.baseDir, name)))
11679
+ if (existsSync21(resolve12(this.baseDir, name)))
11752
11680
  return true;
11753
11681
  if (this.indexHas(name))
11754
11682
  return true;
@@ -11788,7 +11716,7 @@ class FactualCheck {
11788
11716
  for (const entry of entries) {
11789
11717
  if (count >= FactualCheck.MAX_INDEXED_FILES)
11790
11718
  break;
11791
- const full = join13(dir, entry.name);
11719
+ const full = join12(dir, entry.name);
11792
11720
  if (entry.isDirectory()) {
11793
11721
  if (!IGNORED_DIRS.has(entry.name)) {
11794
11722
  count = this.scanDir(full, index, count);
@@ -12418,7 +12346,7 @@ ${joined}` }
12418
12346
  var DEFAULT_CHUNK_SYSTEM_PROMPT = 'Answer the query using ONLY the provided text. Be concise. If the text does not contain the answer, say "NO_EVIDENCE".', DEFAULT_SYNTHESIS_SYSTEM_PROMPT = "You are given a query and per-chunk answers over a large text. Produce the final answer to the query, combining evidence from the chunks. If no chunk had evidence, say so.";
12419
12347
 
12420
12348
  // src/tools/chunk-query.ts
12421
- import { readFileSync as readFileSync12 } from "node:fs";
12349
+ import { readFileSync as readFileSync10 } from "node:fs";
12422
12350
  import { resolve as resolve14 } from "node:path";
12423
12351
  var chunkQueryTool;
12424
12352
  var init_chunk_query = __esm(() => {
@@ -12487,7 +12415,7 @@ var init_chunk_query = __esm(() => {
12487
12415
  return { success: false, output: `[SCOPE] ${check.reason || "Path not allowed"}` };
12488
12416
  }
12489
12417
  try {
12490
- content = readFileSync12(resolve14(ctx.baseDir, inputPath), "utf8");
12418
+ content = readFileSync10(resolve14(ctx.baseDir, inputPath), "utf8");
12491
12419
  } catch (e) {
12492
12420
  return { success: false, output: `Cannot read ${inputPath}: ${e.message}` };
12493
12421
  }
@@ -12836,8 +12764,8 @@ var init_web_browse = __esm(() => {
12836
12764
  });
12837
12765
 
12838
12766
  // src/tools/download-file.ts
12839
- import { writeFileSync as writeFileSync9, mkdirSync as mkdirSync13 } from "fs";
12840
- import { dirname as dirname6 } from "path";
12767
+ import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync12 } from "fs";
12768
+ import { dirname as dirname8 } from "path";
12841
12769
  var MAX_DOWNLOAD_BYTES, downloadFileTool;
12842
12770
  var init_download_file = __esm(() => {
12843
12771
  init_i18n();
@@ -12924,8 +12852,8 @@ var init_download_file = __esm(() => {
12924
12852
  output: t("tool.download_too_large", { max: String(maxBytes) })
12925
12853
  };
12926
12854
  }
12927
- mkdirSync13(dirname6(resolved), { recursive: true });
12928
- writeFileSync9(resolved, buffer);
12855
+ mkdirSync12(dirname8(resolved), { recursive: true });
12856
+ writeFileSync8(resolved, buffer);
12929
12857
  const contentType = response.headers.get("content-type")?.split(";")[0]?.trim() || "unknown";
12930
12858
  logNetworkRequest(ctx.sessionId, sanitizeUrl(url), true, `Status: ${response.status}`);
12931
12859
  logFileWrite(ctx.sessionId, resolved, true, `Downloaded ${buffer.byteLength} bytes`);
@@ -13760,7 +13688,7 @@ ${JSON.stringify(result, null, 2)}`
13760
13688
 
13761
13689
  // src/tools/search-history.ts
13762
13690
  import * as fs from "fs";
13763
- import { join as join14 } from "path";
13691
+ import { join as join13 } from "path";
13764
13692
  import { homedir as homedir5 } from "os";
13765
13693
  function searchFile(filePath, query, maxResults, results) {
13766
13694
  if (!fs.existsSync(filePath))
@@ -13804,7 +13732,7 @@ var init_search_history = __esm(() => {
13804
13732
  const query = String(args.query || "").toLowerCase();
13805
13733
  const maxResults = Number(args.maxResults) || 5;
13806
13734
  const sessionId = args.sessionId ? String(args.sessionId) : null;
13807
- const sessionDir = join14(homedir5(), ".mma", "sessions");
13735
+ const sessionDir = join13(homedir5(), ".mma", "sessions");
13808
13736
  const results = [];
13809
13737
  try {
13810
13738
  if (!fs.existsSync(sessionDir)) {
@@ -13819,7 +13747,7 @@ var init_search_history = __esm(() => {
13819
13747
  continue;
13820
13748
  if (sessionId && entry.name !== sessionId)
13821
13749
  continue;
13822
- const historyFile = join14(sessionDir, entry.name, "history.jsonl");
13750
+ const historyFile = join13(sessionDir, entry.name, "history.jsonl");
13823
13751
  searchFile(historyFile, query, maxResults, results);
13824
13752
  if (results.length >= maxResults)
13825
13753
  break;
@@ -13845,9 +13773,133 @@ var init_search_history = __esm(() => {
13845
13773
  };
13846
13774
  });
13847
13775
 
13776
+ // src/modules/memory/search.ts
13777
+ import { readFileSync as readFileSync12, existsSync as existsSync23 } from "fs";
13778
+ import { join as join14 } from "path";
13779
+
13780
+ class MemorySearch {
13781
+ memoryDir;
13782
+ constructor(memoryDir) {
13783
+ this.memoryDir = memoryDir;
13784
+ }
13785
+ query(query) {
13786
+ const results = [];
13787
+ const lowerQuery = query.toLowerCase();
13788
+ for (const name of MEMORY_FILES) {
13789
+ const path = join14(this.memoryDir, `${name}.md`);
13790
+ if (!existsSync23(path))
13791
+ continue;
13792
+ const content = readFileSync12(path, "utf-8");
13793
+ const lines = content.split(`
13794
+ `);
13795
+ for (const line of lines) {
13796
+ if (line.toLowerCase().includes(lowerQuery)) {
13797
+ results.push({ file: name, match: line.trim() });
13798
+ }
13799
+ }
13800
+ }
13801
+ const prefsPath = join14(this.memoryDir, "preferences.json");
13802
+ if (existsSync23(prefsPath)) {
13803
+ try {
13804
+ const prefs = JSON.parse(readFileSync12(prefsPath, "utf-8"));
13805
+ for (const [key, value] of Object.entries(prefs)) {
13806
+ const searchStr = `${key}=${value}`;
13807
+ if (searchStr.toLowerCase().includes(lowerQuery)) {
13808
+ results.push({ file: "preferences", match: `${key} = ${value}` });
13809
+ }
13810
+ }
13811
+ } catch {}
13812
+ }
13813
+ return results;
13814
+ }
13815
+ }
13816
+ var MEMORY_FILES;
13817
+ var init_search = __esm(() => {
13818
+ MEMORY_FILES = ["conventions", "decisions", "errors", "facts"];
13819
+ });
13820
+
13821
+ // src/modules/memory/store.ts
13822
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync24, mkdirSync as mkdirSync13 } from "fs";
13823
+ import { join as join15 } from "path";
13824
+
13825
+ class MemoryStore {
13826
+ memoryDir;
13827
+ constructor(memoryDir) {
13828
+ this.memoryDir = memoryDir;
13829
+ this.ensureDir();
13830
+ for (const name of MEMORY_FILES2) {
13831
+ const path = join15(this.memoryDir, `${name}.md`);
13832
+ if (!existsSync24(path)) {
13833
+ writeFileSync9(path, `# ${name.charAt(0).toUpperCase() + name.slice(1)}
13834
+
13835
+ `, "utf-8");
13836
+ }
13837
+ }
13838
+ }
13839
+ ensureDir() {
13840
+ if (!existsSync24(this.memoryDir)) {
13841
+ mkdirSync13(this.memoryDir, { recursive: true });
13842
+ }
13843
+ }
13844
+ read(name) {
13845
+ const path = join15(this.memoryDir, `${name}.md`);
13846
+ if (!existsSync24(path))
13847
+ return "";
13848
+ return readFileSync13(path, "utf-8");
13849
+ }
13850
+ append(name, entry) {
13851
+ const path = join15(this.memoryDir, `${name}.md`);
13852
+ const timestamp = new Date().toISOString().replace("T", " ").slice(0, 19);
13853
+ const formatted = `- **${timestamp}** — ${entry}
13854
+ `;
13855
+ appendFileSync5(path, formatted, "utf-8");
13856
+ }
13857
+ search(query) {
13858
+ const searchModule = new MemorySearch(this.memoryDir);
13859
+ return searchModule.query(query);
13860
+ }
13861
+ prefsPath() {
13862
+ return join15(this.memoryDir, "preferences.json");
13863
+ }
13864
+ getPreferences() {
13865
+ const path = this.prefsPath();
13866
+ if (!existsSync24(path))
13867
+ return {};
13868
+ try {
13869
+ return JSON.parse(readFileSync13(path, "utf-8"));
13870
+ } catch {
13871
+ return {};
13872
+ }
13873
+ }
13874
+ setPreference(key, value) {
13875
+ const prefs = this.getPreferences();
13876
+ prefs[key] = value;
13877
+ writeFileSync9(this.prefsPath(), JSON.stringify(prefs, null, 2), "utf-8");
13878
+ }
13879
+ deletePreference(key) {
13880
+ const prefs = this.getPreferences();
13881
+ if (!(key in prefs))
13882
+ return false;
13883
+ delete prefs[key];
13884
+ writeFileSync9(this.prefsPath(), JSON.stringify(prefs, null, 2), "utf-8");
13885
+ return true;
13886
+ }
13887
+ appendRule(category, pattern, cause, solution) {
13888
+ const entry = `**pattern:** ${pattern}
13889
+ **cause:** ${cause}
13890
+ **solution:** ${solution}`;
13891
+ this.append(category, entry);
13892
+ }
13893
+ }
13894
+ var MEMORY_FILES2;
13895
+ var init_store2 = __esm(() => {
13896
+ init_search();
13897
+ MEMORY_FILES2 = ["conventions", "decisions", "errors", "facts"];
13898
+ });
13899
+
13848
13900
  // src/tools/remember.ts
13849
13901
  import { homedir as homedir6 } from "os";
13850
- import { join as join15 } from "path";
13902
+ import { join as join16 } from "path";
13851
13903
  var CATEGORIES, rememberTool;
13852
13904
  var init_remember = __esm(() => {
13853
13905
  init_i18n();
@@ -13885,7 +13937,7 @@ var init_remember = __esm(() => {
13885
13937
  if (!CATEGORIES.includes(category)) {
13886
13938
  return { success: false, output: t("tool.invalid_params") };
13887
13939
  }
13888
- const memoryDir = join15(homedir6(), ".mma", "memory");
13940
+ const memoryDir = join16(homedir6(), ".mma", "memory");
13889
13941
  const store = new MemoryStore(memoryDir);
13890
13942
  try {
13891
13943
  if (category === "preferences") {
@@ -13918,7 +13970,7 @@ var init_remember = __esm(() => {
13918
13970
 
13919
13971
  // src/tools/recall.ts
13920
13972
  import { homedir as homedir7 } from "os";
13921
- import { join as join16 } from "path";
13973
+ import { join as join17 } from "path";
13922
13974
  function formatAll(store) {
13923
13975
  const parts = [];
13924
13976
  const prefs = store.getPreferences();
@@ -14001,7 +14053,7 @@ var init_recall = __esm(() => {
14001
14053
  handler: async (_ctx, args) => {
14002
14054
  const query = args.query ? String(args.query) : "";
14003
14055
  const category = args.category ? String(args.category) : "";
14004
- const memoryDir = join16(homedir7(), ".mma", "memory");
14056
+ const memoryDir = join17(homedir7(), ".mma", "memory");
14005
14057
  const store = new MemoryStore(memoryDir);
14006
14058
  try {
14007
14059
  if (!query && !category) {
@@ -14039,10 +14091,10 @@ __export(exports_bridge_client, {
14039
14091
  });
14040
14092
  import { spawn as spawn4 } from "child_process";
14041
14093
  import { createInterface } from "readline";
14042
- import { dirname as dirname7, join as join17 } from "path";
14094
+ import { dirname as dirname9, join as join18 } from "path";
14043
14095
  import { fileURLToPath } from "url";
14044
14096
  function bridgeScriptPath() {
14045
- return join17(dirname7(fileURLToPath(import.meta.url)), "bridge-server.mjs");
14097
+ return join18(dirname9(fileURLToPath(import.meta.url)), "bridge-server.mjs");
14046
14098
  }
14047
14099
 
14048
14100
  class BridgeDriver {
@@ -14578,15 +14630,15 @@ function buildTextExtractionScript() {
14578
14630
 
14579
14631
  // src/modules/browser/cookie-store.ts
14580
14632
  import { readFile, writeFile, mkdir } from "fs/promises";
14581
- import { join as join18 } from "path";
14633
+ import { join as join19 } from "path";
14582
14634
 
14583
14635
  class CookieStore {
14584
14636
  filePath;
14585
14637
  constructor(cookieDir) {
14586
- this.filePath = join18(cookieDir, "cookies.json");
14638
+ this.filePath = join19(cookieDir, "cookies.json");
14587
14639
  }
14588
14640
  async save(cookies) {
14589
- await mkdir(join18(this.filePath, ".."), { recursive: true });
14641
+ await mkdir(join19(this.filePath, ".."), { recursive: true });
14590
14642
  await writeFile(this.filePath, JSON.stringify(cookies, null, 2), "utf-8");
14591
14643
  }
14592
14644
  async load() {
@@ -14941,10 +14993,10 @@ var init_session = __esm(() => {
14941
14993
  });
14942
14994
 
14943
14995
  // src/tools/browser.ts
14944
- import { join as join19 } from "path";
14996
+ import { join as join20 } from "path";
14945
14997
  function getSession(ctx) {
14946
14998
  if (!session) {
14947
- const cookieDir = join19(ctx.baseDir, ".mma", "browser");
14999
+ const cookieDir = join20(ctx.baseDir, ".mma", "browser");
14948
15000
  session = new BrowserSession({
14949
15001
  ...DEFAULT_BROWSER_CONFIG,
14950
15002
  headless: ctx.config.browser?.headless ?? true,
@@ -15080,8 +15132,8 @@ async function readClipboardFallback() {
15080
15132
  const { platform: platform3 } = await import("os");
15081
15133
  const { execSync } = await import("child_process");
15082
15134
  const { readFileSync: readFileSync15, unlinkSync: unlinkSync4 } = await import("fs");
15083
- const { join: join20 } = await import("path");
15084
- const tmpPath = join20(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
15135
+ const { join: join21 } = await import("path");
15136
+ const tmpPath = join21(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
15085
15137
  try {
15086
15138
  if (platform3() === "linux") {
15087
15139
  execSync(`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`, { timeout: 5000 });
@@ -15159,7 +15211,7 @@ var init_image_utils = __esm(() => {
15159
15211
  });
15160
15212
 
15161
15213
  // src/tools/attach-image.ts
15162
- import { existsSync as existsSync24 } from "fs";
15214
+ import { existsSync as existsSync25 } from "fs";
15163
15215
  import { resolve as resolve15 } from "path";
15164
15216
  var attachImageTool;
15165
15217
  var init_attach_image = __esm(() => {
@@ -15202,7 +15254,7 @@ var init_attach_image = __esm(() => {
15202
15254
  dataUrl = result.dataUrl;
15203
15255
  } else {
15204
15256
  const absPath = resolve15(ctx.baseDir, source);
15205
- if (!existsSync24(absPath)) {
15257
+ if (!existsSync25(absPath)) {
15206
15258
  return {
15207
15259
  success: false,
15208
15260
  output: t("image.not_found", { path: source })
@@ -15364,16 +15416,16 @@ class ModuleRegistry {
15364
15416
  }
15365
15417
 
15366
15418
  // src/modules/plugins/loader.ts
15367
- import { readdirSync as readdirSync7, existsSync as existsSync25, statSync as statSync5 } from "fs";
15368
- import { join as join20 } from "path";
15419
+ import { readdirSync as readdirSync7, existsSync as existsSync26, statSync as statSync5 } from "fs";
15420
+ import { join as join21 } from "path";
15369
15421
 
15370
15422
  class PluginLoader {
15371
15423
  loadFromDir(dirPath, pluginManager, logger) {
15372
- if (!existsSync25(dirPath))
15424
+ if (!existsSync26(dirPath))
15373
15425
  return;
15374
15426
  const entries = readdirSync7(dirPath);
15375
15427
  for (const entry of entries) {
15376
- const fullPath = join20(dirPath, entry);
15428
+ const fullPath = join21(dirPath, entry);
15377
15429
  if (!statSync5(fullPath).isFile())
15378
15430
  continue;
15379
15431
  if (!entry.endsWith(".ts") && !entry.endsWith(".js"))
@@ -15397,8 +15449,8 @@ var init_loader = __esm(() => {
15397
15449
 
15398
15450
  // src/modules/plugins/builtin/lint-on-write.ts
15399
15451
  import { spawn as spawn5, execSync } from "child_process";
15400
- import { existsSync as existsSync26, readFileSync as readFileSync15 } from "fs";
15401
- import { resolve as resolve16, extname as extname4, join as join21 } from "path";
15452
+ import { existsSync as existsSync27, readFileSync as readFileSync15 } from "fs";
15453
+ import { resolve as resolve16, extname as extname4, join as join22 } from "path";
15402
15454
  import { platform as platform3 } from "os";
15403
15455
  function contentHash(content) {
15404
15456
  let h = 5381;
@@ -15444,7 +15496,7 @@ class LintOnWritePlugin {
15444
15496
  if (!path)
15445
15497
  return;
15446
15498
  const fullPath = resolve16(ctx.baseDir, path);
15447
- if (!existsSync26(fullPath))
15499
+ if (!existsSync27(fullPath))
15448
15500
  return;
15449
15501
  const ext = extname4(fullPath);
15450
15502
  const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir);
@@ -15455,7 +15507,7 @@ class LintOnWritePlugin {
15455
15507
  return;
15456
15508
  }
15457
15509
  await this.runProjectLint(ctx, result);
15458
- await this.runProjectTypeCheck(ctx, result);
15510
+ await this.runProjectTypeCheck(fullPath, ctx.baseDir, result);
15459
15511
  }
15460
15512
  async checkSyntax(filePath, ext, baseDir) {
15461
15513
  if (ext === ".ts" || ext === ".tsx") {
@@ -15500,8 +15552,8 @@ class LintOnWritePlugin {
15500
15552
  }
15501
15553
  async runProjectLint(ctx, result) {
15502
15554
  try {
15503
- const packageJsonPath = join21(ctx.baseDir, "package.json");
15504
- if (!existsSync26(packageJsonPath)) {
15555
+ const packageJsonPath = join22(ctx.baseDir, "package.json");
15556
+ if (!existsSync27(packageJsonPath)) {
15505
15557
  return;
15506
15558
  }
15507
15559
  const packageJson = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
@@ -15519,9 +15571,13 @@ class LintOnWritePlugin {
15519
15571
  [Project lint failed]: ${err.message}`;
15520
15572
  }
15521
15573
  }
15522
- async runProjectTypeCheck(ctx, result) {
15523
- const tsconfigPath = join21(ctx.baseDir, "tsconfig.json");
15524
- if (!existsSync26(tsconfigPath)) {
15574
+ async runProjectTypeCheck(filePath, baseDir, result) {
15575
+ const projectRoot = findProjectRoot(filePath, baseDir, [
15576
+ "tsconfig.json",
15577
+ "package.json"
15578
+ ]);
15579
+ const tsconfigPath = join22(projectRoot, "tsconfig.json");
15580
+ if (!existsSync27(tsconfigPath)) {
15525
15581
  return;
15526
15582
  }
15527
15583
  const now = Date.now();
@@ -15535,7 +15591,7 @@ class LintOnWritePlugin {
15535
15591
  return;
15536
15592
  }
15537
15593
  this._checkTimestamp = now;
15538
- this._checkPromise = this.runTscCheck(ctx.baseDir);
15594
+ this._checkPromise = this.runTscCheck(projectRoot);
15539
15595
  const error = await this._checkPromise;
15540
15596
  if (error) {
15541
15597
  result.output += `
@@ -15604,6 +15660,7 @@ function runAsync(command, cwd, timeoutMs) {
15604
15660
  }
15605
15661
  var TYPE_CHECK_DEBOUNCE_MS = 2000, syntaxCache, _winDecoder, plugin;
15606
15662
  var init_lint_on_write = __esm(() => {
15663
+ init_project_root();
15607
15664
  syntaxCache = new Map;
15608
15665
  plugin = new LintOnWritePlugin;
15609
15666
  });
@@ -15766,11 +15823,11 @@ class PlanTracker {
15766
15823
  var init_tracker = () => {};
15767
15824
 
15768
15825
  // src/modules/execution/auditor.ts
15769
- import { existsSync as existsSync27, readdirSync as readdirSync8 } from "fs";
15770
- import { resolve as resolve17, join as join22, basename as basename2 } from "path";
15826
+ import { existsSync as existsSync28, readdirSync as readdirSync8 } from "fs";
15827
+ import { resolve as resolve17, join as join23, basename as basename2 } from "path";
15771
15828
  function findExistingFile(baseDir, filePath) {
15772
15829
  const direct = resolve17(baseDir, filePath);
15773
- if (existsSync27(direct))
15830
+ if (existsSync28(direct))
15774
15831
  return direct;
15775
15832
  const name = basename2(filePath).toLowerCase();
15776
15833
  const suffix = filePath.replace(/\\/g, "/").toLowerCase();
@@ -15787,7 +15844,7 @@ function findExistingFile(baseDir, filePath) {
15787
15844
  for (const e of entries) {
15788
15845
  if (found)
15789
15846
  return;
15790
- const full = join22(dir, e.name);
15847
+ const full = join23(dir, e.name);
15791
15848
  if (e.isDirectory()) {
15792
15849
  if (SKIP_DIRS.has(e.name))
15793
15850
  continue;
@@ -15811,7 +15868,7 @@ function findTestFile(dir, depth = 0) {
15811
15868
  return null;
15812
15869
  }
15813
15870
  for (const e of entries) {
15814
- const full = join22(dir, e.name);
15871
+ const full = join23(dir, e.name);
15815
15872
  if (e.isDirectory()) {
15816
15873
  if (SKIP_DIRS.has(e.name))
15817
15874
  continue;
@@ -15882,7 +15939,7 @@ class Auditor {
15882
15939
  this.baseDir = baseDir;
15883
15940
  }
15884
15941
  async audit(plan) {
15885
- const allStepText = plan.steps.map((s) => s.description.replace(/\([^)]*\)/g, " ")).join(" ");
15942
+ const allStepText = plan.steps.filter((s) => s.status === "done").map((s) => s.description.replace(/\([^)]*\)/g, " ")).join(" ");
15886
15943
  const uniqueFiles = extractFileLikeTokens(stripUrls(allStepText));
15887
15944
  const missingFiles = [];
15888
15945
  const existingFiles = [];
@@ -15903,6 +15960,7 @@ class Auditor {
15903
15960
  }
15904
15961
  }
15905
15962
  const doneSteps = plan.steps.filter((s) => s.status === "done").length;
15963
+ const terminalSteps = plan.steps.filter((s) => s.status === "done" || s.status === "skipped").length;
15906
15964
  const totalSteps = plan.steps.length;
15907
15965
  let massEditWarning = null;
15908
15966
  if (uniqueFiles.length > MASS_EDIT_THRESHOLD) {
@@ -15912,7 +15970,7 @@ class Auditor {
15912
15970
  }
15913
15971
  const testsFailing = testRun !== null && testRun.failed > 0;
15914
15972
  const passed = missingFiles.length === 0 && !testsFailing;
15915
- const stepsPending = doneSteps < totalSteps;
15973
+ const stepsPending = terminalSteps < totalSteps;
15916
15974
  let summary;
15917
15975
  if (missingFiles.length > 0) {
15918
15976
  summary = t("exec.audit_fail", {
@@ -15973,8 +16031,8 @@ var init_auditor = __esm(() => {
15973
16031
  });
15974
16032
 
15975
16033
  // src/modules/execution/plan-store.ts
15976
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync28, readdirSync as readdirSync9, rmSync } from "fs";
15977
- import { join as join23 } from "path";
16034
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync29, readdirSync as readdirSync9, rmSync } from "fs";
16035
+ import { join as join24 } from "path";
15978
16036
  function readPlanFile(path, fallbackBaseDir) {
15979
16037
  try {
15980
16038
  const raw = readFileSync16(path, "utf-8");
@@ -15999,10 +16057,10 @@ function writePlanFile(path, plan) {
15999
16057
  writeFileSync10(path, JSON.stringify(plan, null, 2), "utf-8");
16000
16058
  }
16001
16059
  function listDir(dir, baseDir) {
16002
- if (!existsSync28(dir))
16060
+ if (!existsSync29(dir))
16003
16061
  return [];
16004
16062
  const files = readdirSync9(dir).filter((f) => f.endsWith(".json"));
16005
- return files.map((f) => readPlanFile(join23(dir, f), baseDir)).filter((p) => p !== null);
16063
+ return files.map((f) => readPlanFile(join24(dir, f), baseDir)).filter((p) => p !== null);
16006
16064
  }
16007
16065
  function toMeta(plan, status) {
16008
16066
  return {
@@ -16023,33 +16081,33 @@ class PlanStore {
16023
16081
  archiveDir;
16024
16082
  legacyPath;
16025
16083
  constructor(baseDir) {
16026
- const mmaDir = join23(baseDir, ".mma");
16027
- if (!existsSync28(mmaDir))
16084
+ const mmaDir = join24(baseDir, ".mma");
16085
+ if (!existsSync29(mmaDir))
16028
16086
  mkdirSync14(mmaDir, { recursive: true });
16029
16087
  this.baseDir = baseDir;
16030
- this.plansDir = join23(mmaDir, "plans");
16031
- this.draftsDir = join23(this.plansDir, "drafts");
16032
- this.archiveDir = join23(this.plansDir, "archive");
16033
- this.legacyPath = join23(mmaDir, LEGACY_FILE);
16088
+ this.plansDir = join24(mmaDir, "plans");
16089
+ this.draftsDir = join24(this.plansDir, "drafts");
16090
+ this.archiveDir = join24(this.plansDir, "archive");
16091
+ this.legacyPath = join24(mmaDir, LEGACY_FILE);
16034
16092
  for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
16035
- if (!existsSync28(dir))
16093
+ if (!existsSync29(dir))
16036
16094
  mkdirSync14(dir, { recursive: true });
16037
16095
  }
16038
16096
  }
16039
16097
  activePath() {
16040
- return join23(this.plansDir, "active.json");
16098
+ return join24(this.plansDir, "active.json");
16041
16099
  }
16042
16100
  saveActive(plan) {
16043
16101
  writePlanFile(this.activePath(), plan);
16044
16102
  }
16045
16103
  loadActive() {
16046
16104
  const activePath = this.activePath();
16047
- if (existsSync28(activePath)) {
16105
+ if (existsSync29(activePath)) {
16048
16106
  const plan = readPlanFile(activePath, this.baseDir);
16049
16107
  if (plan)
16050
16108
  return plan;
16051
16109
  }
16052
- if (existsSync28(this.legacyPath)) {
16110
+ if (existsSync29(this.legacyPath)) {
16053
16111
  const legacy = readPlanFile(this.legacyPath, this.baseDir);
16054
16112
  if (legacy) {
16055
16113
  this.saveActive(legacy);
@@ -16063,26 +16121,26 @@ class PlanStore {
16063
16121
  }
16064
16122
  clearActive() {
16065
16123
  const p = this.activePath();
16066
- if (existsSync28(p))
16124
+ if (existsSync29(p))
16067
16125
  rmSync(p, { force: true });
16068
16126
  }
16069
16127
  saveDraft(plan) {
16070
- writePlanFile(join23(this.draftsDir, `${plan.id}.json`), plan);
16128
+ writePlanFile(join24(this.draftsDir, `${plan.id}.json`), plan);
16071
16129
  }
16072
16130
  loadDraft(id) {
16073
- const p = join23(this.draftsDir, `${id}.json`);
16074
- return existsSync28(p) ? readPlanFile(p, this.baseDir) : null;
16131
+ const p = join24(this.draftsDir, `${id}.json`);
16132
+ return existsSync29(p) ? readPlanFile(p, this.baseDir) : null;
16075
16133
  }
16076
16134
  removeDraft(id) {
16077
- const p = join23(this.draftsDir, `${id}.json`);
16078
- if (existsSync28(p))
16135
+ const p = join24(this.draftsDir, `${id}.json`);
16136
+ if (existsSync29(p))
16079
16137
  rmSync(p, { force: true });
16080
16138
  }
16081
16139
  listDrafts() {
16082
16140
  return listDir(this.draftsDir, this.baseDir);
16083
16141
  }
16084
16142
  archivePlan(plan) {
16085
- writePlanFile(join23(this.archiveDir, `${plan.id}.json`), plan);
16143
+ writePlanFile(join24(this.archiveDir, `${plan.id}.json`), plan);
16086
16144
  this.removeDraft(plan.id);
16087
16145
  const active = this.loadActive();
16088
16146
  if (active && active.id === plan.id) {
@@ -16093,8 +16151,8 @@ class PlanStore {
16093
16151
  return listDir(this.archiveDir, this.baseDir);
16094
16152
  }
16095
16153
  removeArchived(id) {
16096
- const p = join23(this.archiveDir, `${id}.json`);
16097
- if (existsSync28(p))
16154
+ const p = join24(this.archiveDir, `${id}.json`);
16155
+ if (existsSync29(p))
16098
16156
  rmSync(p, { force: true });
16099
16157
  }
16100
16158
  listAll() {
@@ -16188,7 +16246,7 @@ var init_plan_coverage = __esm(() => {
16188
16246
  });
16189
16247
 
16190
16248
  // src/modules/execution/module.ts
16191
- import { existsSync as existsSync29, readFileSync as readFileSync17 } from "fs";
16249
+ import { existsSync as existsSync30, readFileSync as readFileSync17 } from "fs";
16192
16250
  import { resolve as resolve18 } from "path";
16193
16251
 
16194
16252
  class ExecutionModule {
@@ -16936,7 +16994,7 @@ Tool "${this.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
16936
16994
  "poetry.lock",
16937
16995
  "requirements.txt"
16938
16996
  ];
16939
- const hasLockFile = lockFiles.some((f) => existsSync29(resolve18(this.baseDir, f)));
16997
+ const hasLockFile = lockFiles.some((f) => existsSync30(resolve18(this.baseDir, f)));
16940
16998
  if (!hasLockFile) {
16941
16999
  if (contextManager) {
16942
17000
  const hints = this.depsGateHints.get(step.id) || 0;
@@ -16956,7 +17014,7 @@ Tool "${this.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
16956
17014
  }
16957
17015
  if (stepPaths.length === 0)
16958
17016
  return;
16959
- const allExist = stepPaths.every((p) => existsSync29(resolve18(this.baseDir, p)));
17017
+ const allExist = stepPaths.every((p) => existsSync30(resolve18(this.baseDir, p)));
16960
17018
  if (!allExist)
16961
17019
  return;
16962
17020
  const emptyFiles = [];
@@ -17028,11 +17086,11 @@ var init_module = __esm(() => {
17028
17086
  import {
17029
17087
  readFileSync as readFileSync18,
17030
17088
  writeFileSync as writeFileSync11,
17031
- existsSync as existsSync30,
17089
+ existsSync as existsSync31,
17032
17090
  readdirSync as readdirSync10,
17033
17091
  unlinkSync as unlinkSync4
17034
17092
  } from "fs";
17035
- import { join as join24 } from "path";
17093
+ import { join as join25 } from "path";
17036
17094
  import { homedir as homedir8 } from "os";
17037
17095
 
17038
17096
  class SessionFileEncryptor {
@@ -17041,7 +17099,7 @@ class SessionFileEncryptor {
17041
17099
  constructor(config) {
17042
17100
  this.config = { ...DEFAULT_SESSION_ENCRYPTION, ...config };
17043
17101
  this.encryptor = new ConfigEncryptor({
17044
- keyPath: config?.keyPath || join24(homedir8(), ".mma", ".session-encryption-key")
17102
+ keyPath: config?.keyPath || join25(homedir8(), ".mma", ".session-encryption-key")
17045
17103
  });
17046
17104
  }
17047
17105
  isEnabled() {
@@ -17127,8 +17185,8 @@ class SessionFileEncryptor {
17127
17185
  return;
17128
17186
  const files = readdirSync10(sessionDir);
17129
17187
  for (const file of files) {
17130
- const filePath = join24(sessionDir, file);
17131
- if (existsSync30(filePath) && !file.endsWith(".enc")) {
17188
+ const filePath = join25(sessionDir, file);
17189
+ if (existsSync31(filePath) && !file.endsWith(".enc")) {
17132
17190
  try {
17133
17191
  const content = readFileSync18(filePath, "utf8");
17134
17192
  const encrypted = this.encryptFileContent(content);
@@ -17144,7 +17202,7 @@ class SessionFileEncryptor {
17144
17202
  const files = readdirSync10(sessionDir);
17145
17203
  for (const file of files) {
17146
17204
  if (file.endsWith(".enc")) {
17147
- const encFilePath = join24(sessionDir, file);
17205
+ const encFilePath = join25(sessionDir, file);
17148
17206
  const decFilePath = encFilePath.slice(0, -4);
17149
17207
  try {
17150
17208
  const content = readFileSync18(encFilePath, "utf8");
@@ -17169,7 +17227,7 @@ var init_session_encryption = __esm(() => {
17169
17227
 
17170
17228
  // src/modules/session/store.ts
17171
17229
  import {
17172
- existsSync as existsSync31,
17230
+ existsSync as existsSync32,
17173
17231
  mkdirSync as mkdirSync15,
17174
17232
  readdirSync as readdirSync11,
17175
17233
  readFileSync as readFileSync19,
@@ -17177,7 +17235,7 @@ import {
17177
17235
  writeFileSync as writeFileSync12,
17178
17236
  appendFileSync as appendFileSync6
17179
17237
  } from "fs";
17180
- import { join as join25 } from "path";
17238
+ import { join as join26 } from "path";
17181
17239
  import { gzipSync } from "zlib";
17182
17240
 
17183
17241
  class SessionStore {
@@ -17191,7 +17249,7 @@ class SessionStore {
17191
17249
  }
17192
17250
  }
17193
17251
  getSessionDir(id) {
17194
- return join25(this.baseDir, id);
17252
+ return join26(this.baseDir, id);
17195
17253
  }
17196
17254
  updateEncryption(config) {
17197
17255
  if (config?.enabled) {
@@ -17207,19 +17265,19 @@ class SessionStore {
17207
17265
  mkdirSync15(this.baseDir, { recursive: true });
17208
17266
  }
17209
17267
  sessionDir(id) {
17210
- return join25(this.baseDir, id);
17268
+ return join26(this.baseDir, id);
17211
17269
  }
17212
17270
  metaPath(id) {
17213
- return join25(this.sessionDir(id), "meta.json");
17271
+ return join26(this.sessionDir(id), "meta.json");
17214
17272
  }
17215
17273
  historyPath(id) {
17216
- return join25(this.sessionDir(id), "history.jsonl");
17274
+ return join26(this.sessionDir(id), "history.jsonl");
17217
17275
  }
17218
17276
  sessionLogPath(id) {
17219
- return join25(this.sessionDir(id), "session.jsonl");
17277
+ return join26(this.sessionDir(id), "session.jsonl");
17220
17278
  }
17221
17279
  sessionExists(id) {
17222
- return existsSync31(this.metaPath(id));
17280
+ return existsSync32(this.metaPath(id));
17223
17281
  }
17224
17282
  saveMeta(id, meta) {
17225
17283
  this._metaCache.set(id, meta);
@@ -17237,7 +17295,7 @@ class SessionStore {
17237
17295
  if (cached)
17238
17296
  return cached;
17239
17297
  const path = this.metaPath(id);
17240
- if (!existsSync31(path))
17298
+ if (!existsSync32(path))
17241
17299
  return null;
17242
17300
  try {
17243
17301
  const raw = readFileSync19(path, "utf-8");
@@ -17269,7 +17327,7 @@ class SessionStore {
17269
17327
  }
17270
17328
  loadHistory(id) {
17271
17329
  const path = this.historyPath(id);
17272
- if (!existsSync31(path))
17330
+ if (!existsSync32(path))
17273
17331
  return [];
17274
17332
  try {
17275
17333
  const raw = readFileSync19(path, "utf-8");
@@ -17310,7 +17368,7 @@ class SessionStore {
17310
17368
  }
17311
17369
  loadSessionLog(id) {
17312
17370
  const path = this.sessionLogPath(id);
17313
- if (!existsSync31(path))
17371
+ if (!existsSync32(path))
17314
17372
  return [];
17315
17373
  try {
17316
17374
  const raw = readFileSync19(path, "utf-8");
@@ -17338,7 +17396,7 @@ class SessionStore {
17338
17396
  }
17339
17397
  }
17340
17398
  listSessions() {
17341
- if (!existsSync31(this.baseDir))
17399
+ if (!existsSync32(this.baseDir))
17342
17400
  return [];
17343
17401
  const entries = readdirSync11(this.baseDir, { withFileTypes: true });
17344
17402
  const sessions = [];
@@ -17355,7 +17413,7 @@ class SessionStore {
17355
17413
  deleteSession(id) {
17356
17414
  this._metaCache.delete(id);
17357
17415
  const dir = this.sessionDir(id);
17358
- if (existsSync31(dir)) {
17416
+ if (existsSync32(dir)) {
17359
17417
  rmSync2(dir, { recursive: true, force: true });
17360
17418
  }
17361
17419
  }
@@ -17367,10 +17425,10 @@ class SessionStore {
17367
17425
  const updatedAt = new Date(session2.updatedAt);
17368
17426
  if (updatedAt < thirtyDaysAgo) {
17369
17427
  const historyPath = this.historyPath(session2.id);
17370
- if (existsSync31(historyPath)) {
17428
+ if (existsSync32(historyPath)) {
17371
17429
  const content = readFileSync19(historyPath, "utf-8");
17372
17430
  const compressed = gzipSync(content);
17373
- const gzPath = join25(this.baseDir, `${session2.id}.jsonl.gz`);
17431
+ const gzPath = join26(this.baseDir, `${session2.id}.jsonl.gz`);
17374
17432
  writeFileSync12(gzPath, compressed);
17375
17433
  rmSync2(historyPath);
17376
17434
  }
@@ -17580,8 +17638,8 @@ class ProfileCompressor {
17580
17638
  }
17581
17639
 
17582
17640
  // src/modules/user-profile/profile.ts
17583
- import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync32, mkdirSync as mkdirSync16 } from "fs";
17584
- import { join as join26 } from "path";
17641
+ import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync33, mkdirSync as mkdirSync16 } from "fs";
17642
+ import { join as join27 } from "path";
17585
17643
  import { homedir as homedir9, hostname, platform as platform4, type } from "os";
17586
17644
  import { env } from "process";
17587
17645
 
@@ -17605,14 +17663,14 @@ class UserProfile {
17605
17663
  return this.info;
17606
17664
  }
17607
17665
  save() {
17608
- if (!existsSync32(this.profileDir)) {
17666
+ if (!existsSync33(this.profileDir)) {
17609
17667
  mkdirSync16(this.profileDir, { recursive: true });
17610
17668
  }
17611
- writeFileSync13(join26(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
17669
+ writeFileSync13(join27(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
17612
17670
  }
17613
17671
  load() {
17614
- const path = join26(this.profileDir, "profile.json");
17615
- if (!existsSync32(path))
17672
+ const path = join27(this.profileDir, "profile.json");
17673
+ if (!existsSync33(path))
17616
17674
  return null;
17617
17675
  try {
17618
17676
  const data = JSON.parse(readFileSync20(path, "utf-8"));
@@ -17650,12 +17708,12 @@ class UserProfile {
17650
17708
  var init_profile = () => {};
17651
17709
 
17652
17710
  // src/modules/skills/loader.ts
17653
- import { readdirSync as readdirSync12, readFileSync as readFileSync21, existsSync as existsSync33, statSync as statSync6 } from "fs";
17654
- import { join as join27 } from "path";
17711
+ import { readdirSync as readdirSync12, readFileSync as readFileSync21, existsSync as existsSync34, statSync as statSync6 } from "fs";
17712
+ import { join as join28 } from "path";
17655
17713
 
17656
17714
  class SkillsLoader {
17657
17715
  loadFromDir(dirPath) {
17658
- if (!existsSync33(dirPath))
17716
+ if (!existsSync34(dirPath))
17659
17717
  return [];
17660
17718
  const skills = [];
17661
17719
  this.scanDir(dirPath, skills);
@@ -17664,7 +17722,7 @@ class SkillsLoader {
17664
17722
  scanDir(dirPath, skills) {
17665
17723
  const entries = readdirSync12(dirPath);
17666
17724
  for (const entry of entries) {
17667
- const fullPath = join27(dirPath, entry);
17725
+ const fullPath = join28(dirPath, entry);
17668
17726
  const stat = statSync6(fullPath);
17669
17727
  if (stat.isDirectory()) {
17670
17728
  this.scanDir(fullPath, skills);
@@ -17908,8 +17966,8 @@ var init_browser2 = __esm(() => {
17908
17966
  });
17909
17967
 
17910
17968
  // src/modules/lsp/command.ts
17911
- import { delimiter, join as join28 } from "path";
17912
- import { existsSync as existsSync34 } from "fs";
17969
+ import { delimiter, join as join29 } from "path";
17970
+ import { existsSync as existsSync35 } from "fs";
17913
17971
  import { platform as platform5 } from "os";
17914
17972
  function resolveSpawnCommand(command, platformName = platform5(), pathEnv = process.env.PATH ?? "") {
17915
17973
  if (platformName !== "win32")
@@ -17920,8 +17978,8 @@ function resolveSpawnCommand(command, platformName = platform5(), pathEnv = proc
17920
17978
  const dirs = pathEnv.split(delimiter).filter(Boolean);
17921
17979
  for (const dir of dirs) {
17922
17980
  for (const ext of WIN_EXTS) {
17923
- const candidate = join28(dir, `${command}${ext}`);
17924
- if (existsSync34(candidate))
17981
+ const candidate = join29(dir, `${command}${ext}`);
17982
+ if (existsSync35(candidate))
17925
17983
  return `${command}${ext}`;
17926
17984
  }
17927
17985
  }
@@ -17960,11 +18018,11 @@ class LspClient {
17960
18018
  diagnosticsResolve = null;
17961
18019
  diagnosticsTimer = null;
17962
18020
  initialized = false;
17963
- async checkFile(filePath, baseDir, config) {
18021
+ async checkFile(filePath, baseDir, config, projectRoot = baseDir) {
17964
18022
  const timeout = config.timeout ?? DEFAULT_TIMEOUT;
17965
18023
  try {
17966
- await this.startServer(config, baseDir);
17967
- const rootUri = this.pathToUri(resolve19(baseDir));
18024
+ await this.startServer(config, projectRoot);
18025
+ const rootUri = this.pathToUri(projectRoot);
17968
18026
  const initResult = await this.sendRequest("initialize", {
17969
18027
  processId: process.pid,
17970
18028
  rootUri,
@@ -18001,7 +18059,7 @@ class LspClient {
18001
18059
  await this.shutdown();
18002
18060
  }
18003
18061
  }
18004
- async startServer(config, baseDir) {
18062
+ async startServer(config, projectRoot) {
18005
18063
  if (config.autoInstall === false) {
18006
18064
  try {
18007
18065
  execSync2(`where ${config.command}`, { stdio: "pipe", timeout: 3000 });
@@ -18017,7 +18075,7 @@ class LspClient {
18017
18075
  const spawnOpts = {
18018
18076
  stdio: ["pipe", "pipe", "pipe"],
18019
18077
  env: { ...process.env, ...config.env },
18020
- cwd: baseDir
18078
+ cwd: projectRoot
18021
18079
  };
18022
18080
  if (isWin) {
18023
18081
  spawnCommand = buildWinCommandLine(spawnCommand, args);
@@ -18190,16 +18248,21 @@ var init_client2 = __esm(() => {
18190
18248
  });
18191
18249
 
18192
18250
  // src/modules/lsp/module.ts
18193
- import { existsSync as existsSync35 } from "fs";
18251
+ import { existsSync as existsSync36 } from "fs";
18194
18252
  import { resolve as resolve20 } from "path";
18195
18253
 
18196
18254
  class LspModule {
18197
18255
  name = "lsp";
18198
18256
  config;
18199
18257
  client = new LspClient;
18258
+ consecutiveFailures = 0;
18259
+ lspDisabled = false;
18200
18260
  constructor(config) {
18201
18261
  this.config = { ...DEFAULT_LSP_CONFIG, ...config };
18202
18262
  }
18263
+ isLspDisabled() {
18264
+ return this.lspDisabled;
18265
+ }
18203
18266
  getPlugin() {
18204
18267
  const self = this;
18205
18268
  return {
@@ -18208,6 +18271,8 @@ class LspModule {
18208
18271
  onAfterTool: async (_ctx, call, result) => {
18209
18272
  if (!self.config.enabled)
18210
18273
  return;
18274
+ if (self.lspDisabled)
18275
+ return;
18211
18276
  if (call.name !== "write_file" && call.name !== "edit_file")
18212
18277
  return;
18213
18278
  if (!result.success)
@@ -18216,13 +18281,15 @@ class LspModule {
18216
18281
  if (!filePath)
18217
18282
  return;
18218
18283
  const fullPath = resolve20(_ctx.baseDir, filePath);
18219
- if (!existsSync35(fullPath))
18284
+ if (!existsSync36(fullPath))
18220
18285
  return;
18221
18286
  const serverConfig = getServerForFile(fullPath, self.config);
18222
18287
  if (!serverConfig)
18223
18288
  return;
18289
+ const projectRoot = findProjectRoot(fullPath, _ctx.baseDir, serverConfig.workspaceMarkers ?? []);
18224
18290
  try {
18225
- const diagnostics = await self.client.checkFile(fullPath, _ctx.baseDir, serverConfig);
18291
+ const diagnostics = await self.client.checkFile(fullPath, _ctx.baseDir, serverConfig, projectRoot);
18292
+ self.consecutiveFailures = 0;
18226
18293
  const errors = diagnostics.filter((d) => d.severity === 1);
18227
18294
  const warnings = diagnostics.filter((d) => d.severity === 2);
18228
18295
  if (errors.length > 0) {
@@ -18241,12 +18308,20 @@ ${items}`;
18241
18308
  }
18242
18309
  } catch (e) {
18243
18310
  const msg = e instanceof Error ? e.message : String(e);
18311
+ self.consecutiveFailures++;
18244
18312
  try {
18245
18313
  _ctx.logger?.warn(`LSP check failed for ${filePath}: ${msg}`);
18246
18314
  } catch {}
18247
- result.output += `
18315
+ if (self.consecutiveFailures >= MAX_CONSECUTIVE_LSP_FAILURES) {
18316
+ self.lspDisabled = true;
18317
+ result.output += `
18318
+
18319
+ [LSP disabled: ${t("lsp.unavailable")}]`;
18320
+ } else {
18321
+ result.output += `
18248
18322
 
18249
18323
  [LSP check failed]: ${msg}`;
18324
+ }
18250
18325
  }
18251
18326
  }
18252
18327
  };
@@ -18262,10 +18337,12 @@ function formatDiagnostics(diagnostics, filePath) {
18262
18337
  }).join(`
18263
18338
  `);
18264
18339
  }
18265
- var severityLabels;
18340
+ var severityLabels, MAX_CONSECUTIVE_LSP_FAILURES = 3;
18266
18341
  var init_module5 = __esm(() => {
18267
18342
  init_client2();
18268
18343
  init_config();
18344
+ init_project_root();
18345
+ init_i18n();
18269
18346
  severityLabels = {
18270
18347
  1: "error",
18271
18348
  2: "warning",
@@ -18282,8 +18359,8 @@ var init_lsp = __esm(() => {
18282
18359
  });
18283
18360
 
18284
18361
  // src/modules/indexer/walker.ts
18285
- import { readdirSync as readdirSync13, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync36, watch } from "fs";
18286
- import { join as join29, relative as relative2, extname as extname5 } from "path";
18362
+ import { readdirSync as readdirSync13, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync37, watch } from "fs";
18363
+ import { join as join30, relative as relative2, extname as extname5 } from "path";
18287
18364
 
18288
18365
  class Indexer {
18289
18366
  baseDir;
@@ -18310,7 +18387,7 @@ class Indexer {
18310
18387
  let totalSize = 0;
18311
18388
  let count = 0;
18312
18389
  const walkDir = (dir) => {
18313
- if (!existsSync36(dir))
18390
+ if (!existsSync37(dir))
18314
18391
  return;
18315
18392
  let entries;
18316
18393
  try {
@@ -18321,7 +18398,7 @@ class Indexer {
18321
18398
  for (const entry of entries) {
18322
18399
  if (count >= this.MAX_FILES)
18323
18400
  return;
18324
- const fullPath = join29(dir, entry);
18401
+ const fullPath = join30(dir, entry);
18325
18402
  const relPath = relative2(this.baseDir, fullPath);
18326
18403
  const stat = statSync7(fullPath);
18327
18404
  if (stat.isDirectory()) {
@@ -18384,19 +18461,19 @@ var init_walker = __esm(() => {
18384
18461
  });
18385
18462
 
18386
18463
  // src/modules/indexer/cache.ts
18387
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as existsSync37, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
18388
- import { join as join30 } from "path";
18464
+ import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as existsSync38, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
18465
+ import { join as join31 } from "path";
18389
18466
 
18390
18467
  class IndexCache {
18391
18468
  cachePath;
18392
18469
  cache = null;
18393
18470
  constructor(cacheDir) {
18394
- this.cachePath = join30(cacheDir, "index-cache.json");
18471
+ this.cachePath = join31(cacheDir, "index-cache.json");
18395
18472
  }
18396
18473
  load() {
18397
18474
  if (this.cache)
18398
18475
  return this.cache;
18399
- if (!existsSync37(this.cachePath))
18476
+ if (!existsSync38(this.cachePath))
18400
18477
  return null;
18401
18478
  try {
18402
18479
  this.cache = JSON.parse(readFileSync23(this.cachePath, "utf-8"));
@@ -18407,14 +18484,14 @@ class IndexCache {
18407
18484
  }
18408
18485
  save(result) {
18409
18486
  this.cache = result;
18410
- const dir = join30(this.cachePath, "..");
18411
- if (!existsSync37(dir))
18487
+ const dir = join31(this.cachePath, "..");
18488
+ if (!existsSync38(dir))
18412
18489
  mkdirSync17(dir, { recursive: true });
18413
18490
  writeFileSync14(this.cachePath, JSON.stringify(result), "utf-8");
18414
18491
  }
18415
18492
  invalidate() {
18416
18493
  this.cache = null;
18417
- if (existsSync37(this.cachePath)) {
18494
+ if (existsSync38(this.cachePath)) {
18418
18495
  try {
18419
18496
  rmSync3(this.cachePath);
18420
18497
  } catch {}
@@ -18424,11 +18501,11 @@ class IndexCache {
18424
18501
  var init_cache = () => {};
18425
18502
 
18426
18503
  // src/modules/indexer/project-profile.ts
18427
- import { readFileSync as readFileSync24, existsSync as existsSync38 } from "fs";
18428
- import { join as join31 } from "path";
18504
+ import { readFileSync as readFileSync24, existsSync as existsSync39 } from "fs";
18505
+ import { join as join32 } from "path";
18429
18506
  function detectManifest(baseDir) {
18430
18507
  for (const manifest of MANIFEST_ORDER) {
18431
- if (existsSync38(join31(baseDir, manifest)))
18508
+ if (existsSync39(join32(baseDir, manifest)))
18432
18509
  return manifest;
18433
18510
  }
18434
18511
  return null;
@@ -18445,7 +18522,7 @@ function cleanDependency(entry) {
18445
18522
  }
18446
18523
  function readPackageJson(baseDir) {
18447
18524
  try {
18448
- const raw = JSON.parse(readFileSync24(join31(baseDir, "package.json"), "utf-8"));
18525
+ const raw = JSON.parse(readFileSync24(join32(baseDir, "package.json"), "utf-8"));
18449
18526
  if (!raw || typeof raw !== "object")
18450
18527
  return null;
18451
18528
  const profile = {
@@ -18469,7 +18546,7 @@ function readPackageJson(baseDir) {
18469
18546
  }
18470
18547
  function readPyproject(baseDir) {
18471
18548
  try {
18472
- const content = readFileSync24(join31(baseDir, "pyproject.toml"), "utf-8");
18549
+ const content = readFileSync24(join32(baseDir, "pyproject.toml"), "utf-8");
18473
18550
  const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
18474
18551
  const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
18475
18552
  if (nameMatch)
@@ -18485,7 +18562,7 @@ function readPyproject(baseDir) {
18485
18562
  }
18486
18563
  function readCargo(baseDir) {
18487
18564
  try {
18488
- const content = readFileSync24(join31(baseDir, "Cargo.toml"), "utf-8");
18565
+ const content = readFileSync24(join32(baseDir, "Cargo.toml"), "utf-8");
18489
18566
  const profile = { runtime: "rust", deps: [], devDeps: [], scripts: {} };
18490
18567
  const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
18491
18568
  if (nameMatch)
@@ -18509,7 +18586,7 @@ function readCargo(baseDir) {
18509
18586
  }
18510
18587
  function readGoMod(baseDir) {
18511
18588
  try {
18512
- const content = readFileSync24(join31(baseDir, "go.mod"), "utf-8");
18589
+ const content = readFileSync24(join32(baseDir, "go.mod"), "utf-8");
18513
18590
  const profile = { runtime: "go", deps: [], devDeps: [], scripts: {} };
18514
18591
  const moduleMatch = content.match(/^module\s+(\S+)/m);
18515
18592
  if (moduleMatch)
@@ -18527,7 +18604,7 @@ function readGoMod(baseDir) {
18527
18604
  }
18528
18605
  function readRequirements(baseDir) {
18529
18606
  try {
18530
- const content = readFileSync24(join31(baseDir, "requirements.txt"), "utf-8");
18607
+ const content = readFileSync24(join32(baseDir, "requirements.txt"), "utf-8");
18531
18608
  const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
18532
18609
  for (const line of content.split(`
18533
18610
  `)) {
@@ -18592,7 +18669,7 @@ var init_project_profile = __esm(() => {
18592
18669
  });
18593
18670
 
18594
18671
  // src/modules/indexer/module.ts
18595
- import { dirname as dirname9 } from "path";
18672
+ import { dirname as dirname11 } from "path";
18596
18673
 
18597
18674
  class IndexerModule {
18598
18675
  name = "indexer";
@@ -18696,22 +18773,54 @@ class IndexerModule {
18696
18773
  });
18697
18774
  const more = result.files.length > 100 ? `
18698
18775
  ${t("indexer.and_more", { count: result.files.length - 100 })}` : "";
18776
+ const duplicates = this.findDuplicateBasenames(result);
18699
18777
  return [
18700
18778
  `${t("indexer.map_header")} (${this.baseDir})`,
18701
18779
  summary,
18702
18780
  ...stackLine ? [stackLine] : [],
18703
18781
  `${t("indexer.top_directories")}: ${topDirs}`,
18782
+ ...duplicates.length > 0 ? [t("indexer.duplicates", { names: duplicates.join(", ") })] : [],
18704
18783
  `${t("indexer.files")}:` + (fileLines.length > 0 ? "" : " " + t("indexer.empty")),
18705
18784
  ...fileLines,
18706
18785
  more
18707
18786
  ].join(`
18708
18787
  `);
18709
18788
  }
18789
+ findDuplicateBasenames(result) {
18790
+ const byDir = {};
18791
+ for (const f of result.files) {
18792
+ const path = f.path.replace(/\\/g, "/");
18793
+ const idx = path.lastIndexOf("/");
18794
+ const dir = idx >= 0 ? path.slice(0, idx) : "";
18795
+ const name = path.slice(idx + 1);
18796
+ const dot = name.lastIndexOf(".");
18797
+ if (dot <= 0)
18798
+ continue;
18799
+ const base = name.slice(0, dot);
18800
+ const ext = name.slice(dot + 1);
18801
+ if (!byDir[dir])
18802
+ byDir[dir] = new Map;
18803
+ const list = byDir[dir].get(base) ?? [];
18804
+ list.push(ext);
18805
+ byDir[dir].set(base, list);
18806
+ }
18807
+ const dups = [];
18808
+ for (const dir of Object.keys(byDir).sort()) {
18809
+ for (const [base, exts] of byDir[dir]) {
18810
+ if (exts.length < 2)
18811
+ continue;
18812
+ const uniqueExts = [...new Set(exts)].sort();
18813
+ const dirPrefix = dir ? `${dir}/` : "";
18814
+ dups.push(`${dirPrefix}${base}.{${uniqueExts.join(",")}}`);
18815
+ }
18816
+ }
18817
+ return dups;
18818
+ }
18710
18819
  getDirectoryCounts(result) {
18711
18820
  const counts = {};
18712
18821
  for (const f of result.files) {
18713
18822
  const normalized = f.path.replace(/\\/g, "/");
18714
- const dir = dirname9(normalized);
18823
+ const dir = dirname11(normalized);
18715
18824
  const key = dir === "." ? "(root)" : dir;
18716
18825
  counts[key] = (counts[key] || 0) + 1;
18717
18826
  }
@@ -18949,27 +19058,65 @@ var init_mcp = __esm(() => {
18949
19058
 
18950
19059
  // src/modules/memory/module.ts
18951
19060
  import { homedir as homedir10 } from "os";
18952
- import { join as join32 } from "path";
19061
+ import { join as join33 } from "path";
18953
19062
 
18954
19063
  class MemoryModule {
18955
19064
  name = "memory";
18956
19065
  store;
18957
- constructor(memoryDir) {
18958
- const dir = memoryDir || join32(homedir10(), ".mma", "memory");
18959
- this.store = new MemoryStore(dir);
19066
+ constructor(storeOrDir) {
19067
+ if (storeOrDir instanceof MemoryStore) {
19068
+ this.store = storeOrDir;
19069
+ } else {
19070
+ const dir = storeOrDir || join33(homedir10(), ".mma", "memory");
19071
+ this.store = new MemoryStore(dir);
19072
+ }
18960
19073
  }
18961
19074
  getSystemPromptBlock() {
19075
+ const parts = [];
18962
19076
  const prefs = this.store.getPreferences();
18963
- if (Object.keys(prefs).length === 0)
19077
+ if (Object.keys(prefs).length > 0) {
19078
+ const prefStr = Object.entries(prefs).map(([k, v]) => `${k}=${v}`).join(", ");
19079
+ parts.push(`User preferences: ${prefStr}`);
19080
+ }
19081
+ const memoryTail = this.getMemoryTail();
19082
+ if (memoryTail)
19083
+ parts.push(memoryTail);
19084
+ if (parts.length === 0)
18964
19085
  return null;
18965
- const prefStr = Object.entries(prefs).map(([k, v]) => `${k}=${v}`).join(", ");
19086
+ const content = parts.join(`
19087
+
19088
+ `);
18966
19089
  return {
18967
- content: `User preferences: ${prefStr}`,
19090
+ content,
18968
19091
  priority: "normal",
18969
19092
  essential: false,
18970
- estimatedTokens: Math.ceil(prefStr.length / 4) + 10
19093
+ estimatedTokens: Math.ceil(content.length / 4) + 10
18971
19094
  };
18972
19095
  }
19096
+ getMemoryTail() {
19097
+ const sections = [];
19098
+ const tailPerFile = 3;
19099
+ for (const name of MEMORY_MD_FILES) {
19100
+ const content = this.store.read(name).trim();
19101
+ if (!content)
19102
+ continue;
19103
+ const entries = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- ")).slice(-tailPerFile);
19104
+ if (entries.length === 0)
19105
+ continue;
19106
+ sections.push(`[Memory ${name}]:
19107
+ ${entries.join(`
19108
+ `)}`);
19109
+ }
19110
+ if (sections.length === 0)
19111
+ return null;
19112
+ let joined = sections.join(`
19113
+
19114
+ `);
19115
+ if (joined.length > 1200)
19116
+ joined = joined.slice(0, 1200) + `
19117
+ …`;
19118
+ return joined;
19119
+ }
18973
19120
  getToolDefinitions() {
18974
19121
  return [rememberTool, recallTool];
18975
19122
  }
@@ -18978,11 +19125,18 @@ class MemoryModule {
18978
19125
  name: "memory",
18979
19126
  isBuiltin: true,
18980
19127
  onBuildPrompt: () => {
19128
+ const parts = [];
18981
19129
  const prefs = this.store.getPreferences();
18982
- if (Object.keys(prefs).length === 0)
18983
- return null;
18984
- const prefStr = Object.entries(prefs).map(([k, v]) => `${k}=${v}`).join(", ");
18985
- return `User preferences: ${prefStr}`;
19130
+ if (Object.keys(prefs).length > 0) {
19131
+ const prefStr = Object.entries(prefs).map(([k, v]) => `${k}=${v}`).join(", ");
19132
+ parts.push(`User preferences: ${prefStr}`);
19133
+ }
19134
+ const memoryTail = this.getMemoryTail();
19135
+ if (memoryTail)
19136
+ parts.push(memoryTail);
19137
+ return parts.length > 0 ? parts.join(`
19138
+
19139
+ `) : null;
18986
19140
  }
18987
19141
  };
18988
19142
  }
@@ -18990,10 +19144,12 @@ class MemoryModule {
18990
19144
  return this.store;
18991
19145
  }
18992
19146
  }
19147
+ var MEMORY_MD_FILES;
18993
19148
  var init_module8 = __esm(() => {
18994
19149
  init_store2();
18995
19150
  init_remember();
18996
19151
  init_recall();
19152
+ MEMORY_MD_FILES = ["errors", "conventions", "decisions", "facts"];
18997
19153
  });
18998
19154
 
18999
19155
  // src/core/bootstrap.ts
@@ -19003,8 +19159,8 @@ __export(exports_bootstrap, {
19003
19159
  bootstrap: () => bootstrap
19004
19160
  });
19005
19161
  import { homedir as homedir11 } from "os";
19006
- import { join as join33, resolve as resolve21 } from "path";
19007
- import { existsSync as existsSync39, readFileSync as readFileSync25, writeFileSync as writeFileSync15 } from "fs";
19162
+ import { join as join34, resolve as resolve21 } from "path";
19163
+ import { existsSync as existsSync40, readFileSync as readFileSync25, writeFileSync as writeFileSync15 } from "fs";
19008
19164
  function buildSystemInfo(config, baseDir, profileCompressed) {
19009
19165
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
19010
19166
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -19021,6 +19177,7 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
19021
19177
  if (config.autoPlan) {
19022
19178
  lines.push(`Plan rule (MANDATORY): any task creating files, installing packages, or requiring multiple actions MUST create a plan with the "plan" tool BEFORE starting. Each step = a concrete deliverable.`);
19023
19179
  }
19180
+ lines.push(`Runtime verification: when a bug is described in terms of runtime behavior (what happens when the app runs), reproduce it — run the app / build / browser tool — and confirm the fix against actual runtime output before calling "plan update step=N status=done".`);
19024
19181
  const hasMCP = config.mcpServers && Object.values(config.mcpServers).some((s) => s.enabled !== false);
19025
19182
  if (hasMCP) {
19026
19183
  lines.push(`MCP servers are available — use the named MCP tools (prefixed mcp__) to query external services.`);
@@ -19029,8 +19186,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
19029
19186
  `);
19030
19187
  }
19031
19188
  async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19032
- const dir = configDir || join33(homedir11(), ".mma");
19033
- const projectConfigPath = projectDir ? join33(projectDir, ".mmrc") : join33(process.cwd(), ".mmrc");
19189
+ const dir = configDir || join34(homedir11(), ".mma");
19190
+ const projectConfigPath = projectDir ? join34(projectDir, ".mmrc") : join34(process.cwd(), ".mmrc");
19034
19191
  const config = loadConfig({ configDir: dir, projectConfigPath });
19035
19192
  setLocale(config.locale);
19036
19193
  try {
@@ -19040,7 +19197,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19040
19197
  }
19041
19198
  } catch {}
19042
19199
  const logger = new Logger(config.logLevel);
19043
- logger.setLogDir(join33(dir, "logs"));
19200
+ logger.setLogDir(join34(dir, "logs"));
19044
19201
  logger.debug("MMA bootstrap", {
19045
19202
  version: config.version,
19046
19203
  model: config.model
@@ -19062,7 +19219,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19062
19219
  logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
19063
19220
  }
19064
19221
  }
19065
- const profile = new UserProfile(join33(dir));
19222
+ const profile = new UserProfile(join34(dir));
19066
19223
  profile.load() || profile.collect();
19067
19224
  profile.save();
19068
19225
  const llmProvider = new OpenAICompatProvider({
@@ -19074,7 +19231,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19074
19231
  rateLimits: config.security?.rateLimits
19075
19232
  });
19076
19233
  const baseDir = projectDir ? resolve21(projectDir) : process.cwd();
19077
- const projectMapCacheDir = join33(baseDir, ".mma");
19234
+ const projectMapCacheDir = join34(baseDir, ".mma");
19078
19235
  const indexerModule = new IndexerModule({
19079
19236
  baseDir,
19080
19237
  cacheDir: projectMapCacheDir
@@ -19085,9 +19242,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19085
19242
  logger.warn(`Project indexing failed: ${err.message}`);
19086
19243
  }
19087
19244
  const skillsLoader = new SkillsLoader;
19088
- const builtinDir = join33(import.meta.dirname, "skills", "builtin");
19089
- const globalDir = join33(homedir11(), ".agents", "skills");
19090
- const projectSkillsDir = join33(baseDir, ".mma", "skills");
19245
+ const builtinDir = join34(import.meta.dirname, "skills", "builtin");
19246
+ const globalDir = join34(homedir11(), ".agents", "skills");
19247
+ const projectSkillsDir = join34(baseDir, ".mma", "skills");
19091
19248
  const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
19092
19249
  const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
19093
19250
  const skillsModule = new SkillsModule(availableSkills, skillsBudget);
@@ -19101,11 +19258,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19101
19258
  essential: true,
19102
19259
  estimatedTokens: Math.ceil(systemInfoContent.length / 4)
19103
19260
  };
19104
- const agentsMdGlobal = join33(dir, "AGENTS.md");
19105
- if (!existsSync39(agentsMdGlobal)) {
19261
+ const agentsMdGlobal = join34(dir, "AGENTS.md");
19262
+ if (!existsSync40(agentsMdGlobal)) {
19106
19263
  writeFileSync15(agentsMdGlobal, "", "utf-8");
19107
19264
  }
19108
- const sessionDir = join33(dir, "sessions");
19265
+ const sessionDir = join34(dir, "sessions");
19109
19266
  const sessionStore = new SessionStore(sessionDir);
19110
19267
  sessionStore.init();
19111
19268
  const sessionManager = new SessionManager(sessionStore, {
@@ -19172,7 +19329,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19172
19329
  const mcpModule = new MCPModule(config);
19173
19330
  await mcpModule.initialize();
19174
19331
  moduleRegistry.register(mcpModule);
19175
- const memoryModule = new MemoryModule(join33(dir, "memory"));
19332
+ const memoryStore = new MemoryStore(join34(dir, "memory"));
19333
+ const memoryModule = new MemoryModule(memoryStore);
19176
19334
  moduleRegistry.register(memoryModule);
19177
19335
  if (config.browser.enabled) {
19178
19336
  const browserModule = new BrowserModule;
@@ -19222,8 +19380,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19222
19380
  pluginManager.register(plugin);
19223
19381
  pluginManager.register(plugin2);
19224
19382
  const pluginLoader = new PluginLoader;
19225
- const globalPluginsDir = join33(homedir11(), ".mma", "plugins");
19226
- const projectPluginsDir = join33(baseDir, ".mma", "plugins");
19383
+ const globalPluginsDir = join34(homedir11(), ".mma", "plugins");
19384
+ const projectPluginsDir = join34(baseDir, ".mma", "plugins");
19227
19385
  pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger);
19228
19386
  pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger);
19229
19387
  contextManager.onCompact = (summary) => {
@@ -19241,12 +19399,12 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19241
19399
  const skipAgentsMd = noAgentsMd === true;
19242
19400
  if (!skipAgentsMd) {
19243
19401
  const agentsMdCandidates = [
19244
- join33(baseDir, "AGENTS.md"),
19245
- join33(baseDir, ".mma", "AGENTS.md"),
19246
- join33(dir, "AGENTS.md")
19402
+ join34(baseDir, "AGENTS.md"),
19403
+ join34(baseDir, ".mma", "AGENTS.md"),
19404
+ join34(dir, "AGENTS.md")
19247
19405
  ];
19248
19406
  for (const p of agentsMdCandidates) {
19249
- if (existsSync39(p)) {
19407
+ if (existsSync40(p)) {
19250
19408
  const content = readFileSync25(p, "utf-8").trim();
19251
19409
  if (content) {
19252
19410
  agentsMdBlocks.push({
@@ -19289,6 +19447,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
19289
19447
  },
19290
19448
  finalAudit: () => execModule.runFinalAudit(),
19291
19449
  sessionManager,
19450
+ memoryStore,
19292
19451
  exitOnComplete
19293
19452
  };
19294
19453
  const agent = new Agent(agentDeps);
@@ -19325,6 +19484,7 @@ var init_bootstrap = __esm(() => {
19325
19484
  init_indexer();
19326
19485
  init_mcp();
19327
19486
  init_module8();
19487
+ init_store2();
19328
19488
  init_i18n();
19329
19489
  init_agent();
19330
19490
  });
@@ -20099,12 +20259,12 @@ __export(exports_manifest, {
20099
20259
  getCertMark: () => getCertMark,
20100
20260
  MANIFEST_PATH: () => MANIFEST_PATH
20101
20261
  });
20102
- import { existsSync as existsSync40, readFileSync as readFileSync26, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
20262
+ import { existsSync as existsSync41, readFileSync as readFileSync26, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
20103
20263
  import { homedir as homedir13 } from "os";
20104
- import { join as join35 } from "path";
20264
+ import { join as join36 } from "path";
20105
20265
  function readManifest(path = MANIFEST_PATH) {
20106
20266
  try {
20107
- if (existsSync40(path)) {
20267
+ if (existsSync41(path)) {
20108
20268
  const raw = JSON.parse(readFileSync26(path, "utf-8"));
20109
20269
  return { version: 1, certifications: raw.certifications ?? [] };
20110
20270
  }
@@ -20112,7 +20272,7 @@ function readManifest(path = MANIFEST_PATH) {
20112
20272
  return { version: 1, certifications: [] };
20113
20273
  }
20114
20274
  function saveManifest(m, path = MANIFEST_PATH) {
20115
- mkdirSync18(join35(homedir13(), ".mma"), { recursive: true });
20275
+ mkdirSync18(join36(homedir13(), ".mma"), { recursive: true });
20116
20276
  writeFileSync16(path, JSON.stringify(m, null, 2), "utf-8");
20117
20277
  }
20118
20278
  function upsertCertification(entry, path = MANIFEST_PATH) {
@@ -20147,7 +20307,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
20147
20307
  }
20148
20308
  var MANIFEST_PATH;
20149
20309
  var init_manifest = __esm(() => {
20150
- MANIFEST_PATH = join35(homedir13(), ".mma", "certifications.json");
20310
+ MANIFEST_PATH = join36(homedir13(), ".mma", "certifications.json");
20151
20311
  });
20152
20312
 
20153
20313
  // node_modules/yaml/dist/nodes/identity.js
@@ -27270,8 +27430,8 @@ var init_scenarios = __esm(() => {
27270
27430
  });
27271
27431
 
27272
27432
  // src/modules/certification/loader.ts
27273
- import { existsSync as existsSync41, readdirSync as readdirSync14, readFileSync as readFileSync27 } from "fs";
27274
- import { join as join36 } from "path";
27433
+ import { existsSync as existsSync42, readdirSync as readdirSync14, readFileSync as readFileSync27 } from "fs";
27434
+ import { join as join37 } from "path";
27275
27435
  function validateScenario(s) {
27276
27436
  const errors2 = [];
27277
27437
  const isSkip = s.mode === "skip";
@@ -27320,12 +27480,12 @@ function loadScenarios(userDir) {
27320
27480
  else
27321
27481
  scenarios.push(s);
27322
27482
  }
27323
- if (userDir && existsSync41(userDir)) {
27483
+ if (userDir && existsSync42(userDir)) {
27324
27484
  for (const file of readdirSync14(userDir)) {
27325
27485
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
27326
27486
  continue;
27327
27487
  try {
27328
- const raw = readFileSync27(join36(userDir, file), "utf-8");
27488
+ const raw = readFileSync27(join37(userDir, file), "utf-8");
27329
27489
  const data = $parse(raw);
27330
27490
  const parsed = normalizeScenario(data, file);
27331
27491
  const errs = validateScenario(parsed);
@@ -27378,8 +27538,8 @@ var init_loader3 = __esm(() => {
27378
27538
  });
27379
27539
 
27380
27540
  // src/modules/certification/fact-checker.ts
27381
- import { existsSync as existsSync42, readFileSync as readFileSync28, statSync as statSync8 } from "fs";
27382
- import { join as join37 } from "path";
27541
+ import { existsSync as existsSync43, readFileSync as readFileSync28, statSync as statSync8 } from "fs";
27542
+ import { join as join38 } from "path";
27383
27543
  function checkSandbox(sandboxDir, checks, exitCode, output) {
27384
27544
  const failures = [];
27385
27545
  for (const check of checks) {
@@ -27396,13 +27556,13 @@ function runCheck(sandboxDir, check, exitCode, output) {
27396
27556
  case "outputContains":
27397
27557
  return output.includes(check.text);
27398
27558
  case "fileExists":
27399
- return isFile(join37(sandboxDir, check.path));
27559
+ return isFile(join38(sandboxDir, check.path));
27400
27560
  case "fileNotExists":
27401
- return !existsSync42(join37(sandboxDir, check.path));
27561
+ return !existsSync43(join38(sandboxDir, check.path));
27402
27562
  case "dirExists":
27403
- return isDir(join37(sandboxDir, check.path));
27563
+ return isDir(join38(sandboxDir, check.path));
27404
27564
  case "fileContent": {
27405
- const abs = join37(sandboxDir, check.path);
27565
+ const abs = join38(sandboxDir, check.path);
27406
27566
  if (!isFile(abs))
27407
27567
  return false;
27408
27568
  const content = readFileSync28(abs, "utf-8");
@@ -27413,7 +27573,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
27413
27573
  return false;
27414
27574
  }
27415
27575
  case "fileRegex": {
27416
- const abs = join37(sandboxDir, check.path);
27576
+ const abs = join38(sandboxDir, check.path);
27417
27577
  if (!isFile(abs))
27418
27578
  return false;
27419
27579
  return new RegExp(check.pattern).test(readFileSync28(abs, "utf-8"));
@@ -27424,14 +27584,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
27424
27584
  }
27425
27585
  function isFile(p) {
27426
27586
  try {
27427
- return existsSync42(p) && statSync8(p).isFile();
27587
+ return existsSync43(p) && statSync8(p).isFile();
27428
27588
  } catch {
27429
27589
  return false;
27430
27590
  }
27431
27591
  }
27432
27592
  function isDir(p) {
27433
27593
  try {
27434
- return existsSync42(p) && statSync8(p).isDirectory();
27594
+ return existsSync43(p) && statSync8(p).isDirectory();
27435
27595
  } catch {
27436
27596
  return false;
27437
27597
  }
@@ -27462,9 +27622,9 @@ var init_fact_checker = () => {};
27462
27622
 
27463
27623
  // src/modules/certification/runner.ts
27464
27624
  import { spawn as spawn7 } from "child_process";
27465
- import { existsSync as existsSync43, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
27625
+ import { existsSync as existsSync44, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
27466
27626
  import { platform as platform7 } from "os";
27467
- import { join as join38, resolve as resolve22, dirname as dirname10 } from "path";
27627
+ import { join as join39, resolve as resolve22, dirname as dirname12 } from "path";
27468
27628
  async function runScenario(scenario, opts) {
27469
27629
  if (scenario.mode === "skip") {
27470
27630
  return {
@@ -27483,7 +27643,7 @@ async function runScenario(scenario, opts) {
27483
27643
  let passed = 0;
27484
27644
  let firstError;
27485
27645
  for (let i = 1;i <= reps; i++) {
27486
- const sandbox = join38(opts.sandboxBase, `run-${scenario.id}-${i}`);
27646
+ const sandbox = join39(opts.sandboxBase, `run-${scenario.id}-${i}`);
27487
27647
  let failures = [];
27488
27648
  let exitCode = -1;
27489
27649
  let output = "";
@@ -27544,20 +27704,20 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
27544
27704
  rmSync4(sandbox, { recursive: true, force: true });
27545
27705
  mkdirSync19(sandbox, { recursive: true });
27546
27706
  for (const f of scenario.fixtures ?? []) {
27547
- const src = join38(mmaRoot, f.source);
27548
- if (!existsSync43(src)) {
27707
+ const src = join39(mmaRoot, f.source);
27708
+ if (!existsSync44(src)) {
27549
27709
  throw new Error(`fixture missing: ${f.source}`);
27550
27710
  }
27551
- const dest = join38(sandbox, f.dest);
27552
- mkdirSync19(dirname10(dest), { recursive: true });
27711
+ const dest = join39(sandbox, f.dest);
27712
+ mkdirSync19(dirname12(dest), { recursive: true });
27553
27713
  cpSync2(src, dest);
27554
27714
  }
27555
27715
  }
27556
27716
  function resolveMmaEntry(mmaRoot) {
27557
- const dev = join38(mmaRoot, "src", "cli", "main.ts");
27558
- if (existsSync43(dev))
27717
+ const dev = join39(mmaRoot, "src", "cli", "main.ts");
27718
+ if (existsSync44(dev))
27559
27719
  return dev;
27560
- return join38(mmaRoot, "dist", "main.js");
27720
+ return join39(mmaRoot, "dist", "main.js");
27561
27721
  }
27562
27722
  function findMmaRoot(fromDir) {
27563
27723
  const candidates = [
@@ -27565,7 +27725,7 @@ function findMmaRoot(fromDir) {
27565
27725
  resolve22(fromDir, "..")
27566
27726
  ];
27567
27727
  for (const c of candidates) {
27568
- if (existsSync43(join38(c, "package.json")))
27728
+ if (existsSync44(join39(c, "package.json")))
27569
27729
  return c;
27570
27730
  }
27571
27731
  return process.cwd();
@@ -27633,13 +27793,13 @@ __export(exports_cli, {
27633
27793
  });
27634
27794
  import { rmSync as rmSync5 } from "fs";
27635
27795
  import { homedir as homedir14 } from "os";
27636
- import { join as join39, dirname as dirname11 } from "path";
27796
+ import { join as join40, dirname as dirname13 } from "path";
27637
27797
  import { fileURLToPath as fileURLToPath2 } from "url";
27638
- import { existsSync as existsSync44, readFileSync as readFileSync29 } from "fs";
27798
+ import { existsSync as existsSync45, readFileSync as readFileSync29 } from "fs";
27639
27799
  function readVersion() {
27640
- const candidates = [join39(MMA_ROOT, "package.json")];
27800
+ const candidates = [join40(MMA_ROOT, "package.json")];
27641
27801
  for (const p of candidates) {
27642
- if (existsSync44(p)) {
27802
+ if (existsSync45(p)) {
27643
27803
  try {
27644
27804
  const raw = JSON.parse(readFileSync29(p, "utf-8"));
27645
27805
  if (raw.version)
@@ -27677,7 +27837,7 @@ async function certify(opts) {
27677
27837
  return;
27678
27838
  }
27679
27839
  console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
27680
- const sandboxBase = join39(process.cwd(), ".mma", "certification");
27840
+ const sandboxBase = join40(process.cwd(), ".mma", "certification");
27681
27841
  const results = [];
27682
27842
  const total = selected.length;
27683
27843
  let idx = 0;
@@ -27789,9 +27949,9 @@ var init_cli = __esm(() => {
27789
27949
  init_loader3();
27790
27950
  init_runner2();
27791
27951
  init_manifest();
27792
- HERE = dirname11(fileURLToPath2(import.meta.url));
27952
+ HERE = dirname13(fileURLToPath2(import.meta.url));
27793
27953
  MMA_ROOT = findMmaRoot(HERE);
27794
- USER_SCENARIO_DIR = join39(homedir14(), ".mma", "certification", "scenarios");
27954
+ USER_SCENARIO_DIR = join40(homedir14(), ".mma", "certification", "scenarios");
27795
27955
  });
27796
27956
 
27797
27957
  // src/cli/repl-commands.ts
@@ -27800,18 +27960,18 @@ __export(exports_repl_commands, {
27800
27960
  registerAllCommands: () => registerAllCommands,
27801
27961
  COMMAND_GROUPS: () => COMMAND_GROUPS
27802
27962
  });
27803
- import { join as join41, dirname as dirname13 } from "path";
27963
+ import { join as join42, dirname as dirname15 } from "path";
27804
27964
  import { homedir as homedir16 } from "os";
27805
- import { existsSync as existsSync46, readFileSync as readFileSync31 } from "fs";
27965
+ import { existsSync as existsSync47, readFileSync as readFileSync31 } from "fs";
27806
27966
  import { fileURLToPath as fileURLToPath4 } from "url";
27807
27967
  function readVersion3() {
27808
- const here = dirname13(fileURLToPath4(import.meta.url));
27968
+ const here = dirname15(fileURLToPath4(import.meta.url));
27809
27969
  const candidates = [
27810
- join41(here, "..", "..", "package.json"),
27811
- join41(here, "..", "package.json")
27970
+ join42(here, "..", "..", "package.json"),
27971
+ join42(here, "..", "package.json")
27812
27972
  ];
27813
27973
  for (const p of candidates) {
27814
- if (existsSync46(p)) {
27974
+ if (existsSync47(p)) {
27815
27975
  try {
27816
27976
  const raw = JSON.parse(readFileSync31(p, "utf8"));
27817
27977
  if (raw.version)
@@ -27877,7 +28037,7 @@ function registerMmaCommands(ctx) {
27877
28037
  }
27878
28038
  try {
27879
28039
  const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
27880
- const { existsSync: existsSync47 } = await import("fs");
28040
+ const { existsSync: existsSync48 } = await import("fs");
27881
28041
  const { resolve: resolve23 } = await import("path");
27882
28042
  let dataUrl;
27883
28043
  let label;
@@ -27897,7 +28057,7 @@ function registerMmaCommands(ctx) {
27897
28057
  label = source;
27898
28058
  } else {
27899
28059
  const absPath = resolve23(process.cwd(), source);
27900
- if (!existsSync47(absPath)) {
28060
+ if (!existsSync48(absPath)) {
27901
28061
  console.log(pc2.red(t("image.not_found", { path: source })));
27902
28062
  return;
27903
28063
  }
@@ -27976,7 +28136,7 @@ function registerMmaCommands(ctx) {
27976
28136
  console.log(pc2.yellow(t("repl.wizard_running")));
27977
28137
  await ctx.withExclusiveInput(async () => {
27978
28138
  const answers = await runSetup(ctx.rl);
27979
- const configPath = join41(homedir16(), ".mma", "config.json");
28139
+ const configPath = join42(homedir16(), ".mma", "config.json");
27980
28140
  ctx.config.provider.type = answers.provider;
27981
28141
  ctx.config.provider.baseUrl = answers.apiBase;
27982
28142
  ctx.config.provider.apiKey = answers.apiKey;
@@ -28030,7 +28190,7 @@ Excluded blocks: ${info.excluded.length}`));
28030
28190
  return;
28031
28191
  }
28032
28192
  ctx.config.provider.type = name;
28033
- const configPath = join41(homedir16(), ".mma", "config.json");
28193
+ const configPath = join42(homedir16(), ".mma", "config.json");
28034
28194
  saveConfig(ctx.config, configPath);
28035
28195
  await ctx.agent.reconfigure(ctx.config);
28036
28196
  console.log(pc2.green(t("repl.provider_set", { name })));
@@ -28086,7 +28246,7 @@ Excluded blocks: ${info.excluded.length}`));
28086
28246
  return;
28087
28247
  }
28088
28248
  ctx.config.model = name;
28089
- const configPath = join41(homedir16(), ".mma", "config.json");
28249
+ const configPath = join42(homedir16(), ".mma", "config.json");
28090
28250
  saveConfig(ctx.config, configPath);
28091
28251
  await ctx.agent.reconfigure(ctx.config);
28092
28252
  console.log(pc2.green(t("repl.model_set", { name })));
@@ -28111,7 +28271,7 @@ Excluded blocks: ${info.excluded.length}`));
28111
28271
  return;
28112
28272
  }
28113
28273
  ctx.config.contextWindow = size;
28114
- const configPath = join41(homedir16(), ".mma", "config.json");
28274
+ const configPath = join42(homedir16(), ".mma", "config.json");
28115
28275
  saveConfig(ctx.config, configPath);
28116
28276
  await ctx.agent.reconfigure(ctx.config);
28117
28277
  console.log(pc2.green(t("cli.context_set", { size })));
@@ -28130,10 +28290,10 @@ Excluded blocks: ${info.excluded.length}`));
28130
28290
  ctx.agent.shutdown();
28131
28291
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
28132
28292
  const { homedir: homedir17 } = await import("os");
28133
- const { join: join42 } = await import("path");
28293
+ const { join: join43 } = await import("path");
28134
28294
  const configDir = ctx.configDir;
28135
28295
  const baseDir = ctx.baseDir;
28136
- const projectConfigPath = join42(baseDir, ".mmrc");
28296
+ const projectConfigPath = join43(baseDir, ".mmrc");
28137
28297
  const freshConfig = loadConfig2({ configDir, projectConfigPath });
28138
28298
  Object.assign(ctx.config, freshConfig);
28139
28299
  const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
@@ -28433,14 +28593,14 @@ init_bootstrap();
28433
28593
  init_config2();
28434
28594
  init_setup();
28435
28595
  init_i18n();
28436
- import { join as join40, dirname as dirname12 } from "path";
28596
+ import { join as join41, dirname as dirname14 } from "path";
28437
28597
  import { homedir as homedir15 } from "os";
28438
- import { existsSync as existsSync45, readFileSync as readFileSync30 } from "fs";
28598
+ import { existsSync as existsSync46, readFileSync as readFileSync30 } from "fs";
28439
28599
 
28440
28600
  // src/cli/security-commands.ts
28441
28601
  init_bootstrap();
28442
28602
  init_config2();
28443
- import { join as join34 } from "path";
28603
+ import { join as join35 } from "path";
28444
28604
  import { homedir as homedir12 } from "os";
28445
28605
 
28446
28606
  // src/modules/security/security-policies.ts
@@ -28970,7 +29130,7 @@ function createSecurityCommand(program2) {
28970
29130
  }
28971
29131
  });
28972
29132
  securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
28973
- const configPath = join34(homedir12(), ".mma", "config.json");
29133
+ const configPath = join35(homedir12(), ".mma", "config.json");
28974
29134
  const { config: appConfig } = await bootstrap();
28975
29135
  const validPresets = ["strict", "balanced", "permissive"];
28976
29136
  if (!validPresets.includes(preset)) {
@@ -28985,7 +29145,7 @@ function createSecurityCommand(program2) {
28985
29145
  console.log(t("cli.security.policy_description", { description: policy.description }));
28986
29146
  });
28987
29147
  securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
28988
- const configPath = join34(homedir12(), ".mma", "config.json");
29148
+ const configPath = join35(homedir12(), ".mma", "config.json");
28989
29149
  const { config: appConfig } = await bootstrap();
28990
29150
  appConfig.security = appConfig.security || {};
28991
29151
  appConfig.security.sessionEncryption = {
@@ -28997,7 +29157,7 @@ function createSecurityCommand(program2) {
28997
29157
  console.log(t("cli.security.encryption_enabled"));
28998
29158
  });
28999
29159
  securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
29000
- const configPath = join34(homedir12(), ".mma", "config.json");
29160
+ const configPath = join35(homedir12(), ".mma", "config.json");
29001
29161
  const { config: appConfig } = await bootstrap();
29002
29162
  appConfig.security = appConfig.security || {};
29003
29163
  appConfig.security.sessionEncryption = {
@@ -29009,7 +29169,7 @@ function createSecurityCommand(program2) {
29009
29169
  console.log(t("cli.security.encryption_disabled"));
29010
29170
  });
29011
29171
  securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
29012
- const configPath = join34(homedir12(), ".mma", "config.json");
29172
+ const configPath = join35(homedir12(), ".mma", "config.json");
29013
29173
  const { config: appConfig } = await bootstrap();
29014
29174
  appConfig.security = appConfig.security || {};
29015
29175
  appConfig.security.auditNotifier = {
@@ -29023,7 +29183,7 @@ function createSecurityCommand(program2) {
29023
29183
  console.log(t("cli.security.audit_enabled"));
29024
29184
  });
29025
29185
  securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
29026
- const configPath = join34(homedir12(), ".mma", "config.json");
29186
+ const configPath = join35(homedir12(), ".mma", "config.json");
29027
29187
  const { config: appConfig } = await bootstrap();
29028
29188
  appConfig.security = appConfig.security || {};
29029
29189
  appConfig.security.auditNotifier = {
@@ -29057,13 +29217,13 @@ function createSecurityCommand(program2) {
29057
29217
  // src/cli/commands.ts
29058
29218
  import { fileURLToPath as fileURLToPath3 } from "url";
29059
29219
  function readVersion2() {
29060
- const here = dirname12(fileURLToPath3(import.meta.url));
29220
+ const here = dirname14(fileURLToPath3(import.meta.url));
29061
29221
  const candidates = [
29062
- join40(here, "..", "..", "package.json"),
29063
- join40(here, "..", "package.json")
29222
+ join41(here, "..", "..", "package.json"),
29223
+ join41(here, "..", "package.json")
29064
29224
  ];
29065
29225
  for (const p of candidates) {
29066
- if (existsSync45(p)) {
29226
+ if (existsSync46(p)) {
29067
29227
  try {
29068
29228
  const raw = JSON.parse(readFileSync30(p, "utf8"));
29069
29229
  if (raw.version)
@@ -29078,7 +29238,7 @@ function createProgram() {
29078
29238
  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"));
29079
29239
  program2.command("init").description(t("cli.init")).action(async () => {
29080
29240
  const answers = await runSetup();
29081
- const configPath = join40(homedir15(), ".mma", "config.json");
29241
+ const configPath = join41(homedir15(), ".mma", "config.json");
29082
29242
  const { config } = await bootstrap();
29083
29243
  config.provider.type = answers.provider;
29084
29244
  config.provider.baseUrl = answers.apiBase;
@@ -29123,7 +29283,7 @@ function createProgram() {
29123
29283
  });
29124
29284
  const configCmd = program2.command("config").description(t("cli.manage_config"));
29125
29285
  configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
29126
- const configPath = join40(homedir15(), ".mma", "config.json");
29286
+ const configPath = join41(homedir15(), ".mma", "config.json");
29127
29287
  const { config } = await bootstrap();
29128
29288
  const keys = key.split(".");
29129
29289
  let obj = config;
@@ -29186,7 +29346,7 @@ function createProgram() {
29186
29346
  console.log(t("cli.model_hint"));
29187
29347
  });
29188
29348
  model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
29189
- const configPath = join40(homedir15(), ".mma", "config.json");
29349
+ const configPath = join41(homedir15(), ".mma", "config.json");
29190
29350
  const { config } = await bootstrap();
29191
29351
  config.model = name;
29192
29352
  saveConfig(config, configPath);
@@ -29222,7 +29382,7 @@ function createProgram() {
29222
29382
  await uncertify2(name, config);
29223
29383
  });
29224
29384
  program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
29225
- const configPath = join40(homedir15(), ".mma", "config.json");
29385
+ const configPath = join41(homedir15(), ".mma", "config.json");
29226
29386
  const { config } = await bootstrap();
29227
29387
  const contextWindow = parseInt(size, 10);
29228
29388
  if (isNaN(contextWindow) || contextWindow < 1024) {
@@ -29240,7 +29400,7 @@ function createProgram() {
29240
29400
  console.log(t("cli.base_url"), config.provider.baseUrl);
29241
29401
  });
29242
29402
  provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
29243
- const configPath = join40(homedir15(), ".mma", "config.json");
29403
+ const configPath = join41(homedir15(), ".mma", "config.json");
29244
29404
  const { config } = await bootstrap();
29245
29405
  config.provider.type = name;
29246
29406
  saveConfig(config, configPath);
@@ -30010,8 +30170,8 @@ class LineEditor {
30010
30170
  }
30011
30171
 
30012
30172
  // src/cli/repl.ts
30013
- import { existsSync as existsSync47, readFileSync as readFileSync32, writeFileSync as writeFileSync17 } from "fs";
30014
- import { join as join42, dirname as dirname14 } from "path";
30173
+ import { existsSync as existsSync48, readFileSync as readFileSync32, writeFileSync as writeFileSync17 } from "fs";
30174
+ import { join as join43, dirname as dirname16 } from "path";
30015
30175
  import { homedir as homedir17 } from "os";
30016
30176
  import { fileURLToPath as fileURLToPath5 } from "url";
30017
30177
 
@@ -30515,13 +30675,13 @@ init_box();
30515
30675
  init_i18n();
30516
30676
  init_repl_commands();
30517
30677
  function readVersion4() {
30518
- const here = dirname14(fileURLToPath5(import.meta.url));
30678
+ const here = dirname16(fileURLToPath5(import.meta.url));
30519
30679
  const candidates = [
30520
- join42(here, "..", "..", "package.json"),
30521
- join42(here, "..", "package.json")
30680
+ join43(here, "..", "..", "package.json"),
30681
+ join43(here, "..", "package.json")
30522
30682
  ];
30523
30683
  for (const p of candidates) {
30524
- if (existsSync47(p)) {
30684
+ if (existsSync48(p)) {
30525
30685
  try {
30526
30686
  const raw = JSON.parse(readFileSync32(p, "utf8"));
30527
30687
  if (raw.version)
@@ -30579,10 +30739,10 @@ class Repl {
30579
30739
  this.skillsModule = skillsModule;
30580
30740
  this.pluginManager = pluginManager;
30581
30741
  this.logger = logger;
30582
- this.configDir = configDir || join42(homedir17(), ".mma");
30742
+ this.configDir = configDir || join43(homedir17(), ".mma");
30583
30743
  this.baseDir = baseDir || process.cwd();
30584
30744
  this.noAgentsMd = noAgentsMd === true;
30585
- this.historyPath = join42(homedir17(), ".mma", "repl-history");
30745
+ this.historyPath = join43(homedir17(), ".mma", "repl-history");
30586
30746
  this.loadHistory();
30587
30747
  this.rl = process.stdin.isTTY ? new LineEditor({
30588
30748
  input: process.stdin,
@@ -30615,7 +30775,7 @@ class Repl {
30615
30775
  this.setupListeners();
30616
30776
  }
30617
30777
  loadHistory() {
30618
- if (existsSync47(this.historyPath)) {
30778
+ if (existsSync48(this.historyPath)) {
30619
30779
  try {
30620
30780
  const raw = readFileSync32(this.historyPath, "utf-8");
30621
30781
  this.history = raw.split(`
@@ -30974,11 +31134,11 @@ ${t("image.clipboard_empty")}`));
30974
31134
  row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
30975
31135
  } else {
30976
31136
  const agentsMdCandidates = [
30977
- join42(this.baseDir, "AGENTS.md"),
30978
- join42(this.baseDir, ".mma", "AGENTS.md"),
30979
- join42(this.configDir, "AGENTS.md")
31137
+ join43(this.baseDir, "AGENTS.md"),
31138
+ join43(this.baseDir, ".mma", "AGENTS.md"),
31139
+ join43(this.configDir, "AGENTS.md")
30980
31140
  ];
30981
- const foundAgents = agentsMdCandidates.filter((p) => existsSync47(p));
31141
+ const foundAgents = agentsMdCandidates.filter((p) => existsSync48(p));
30982
31142
  if (foundAgents.length > 0) {
30983
31143
  for (const p of foundAgents) {
30984
31144
  row(t("repl.agents_label"), pc2.dim(p));
@@ -30989,7 +31149,7 @@ ${t("image.clipboard_empty")}`));
30989
31149
  }
30990
31150
  const meta = this.sessionManager?.getActiveMeta();
30991
31151
  if (meta) {
30992
- const sessionPath = join42(this.configDir, "sessions", meta.id);
31152
+ const sessionPath = join43(this.configDir, "sessions", meta.id);
30993
31153
  row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
30994
31154
  }
30995
31155
  const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
@@ -31030,8 +31190,8 @@ init_setup();
31030
31190
  init_config2();
31031
31191
  init_i18n();
31032
31192
  init_colors();
31033
- import { existsSync as existsSync48, readFileSync as readFileSync33 } from "fs";
31034
- import { join as join43, dirname as dirname15 } from "path";
31193
+ import { existsSync as existsSync49, readFileSync as readFileSync33 } from "fs";
31194
+ import { join as join44, dirname as dirname17 } from "path";
31035
31195
  import { homedir as homedir18 } from "os";
31036
31196
  import { fileURLToPath as fileURLToPath6 } from "url";
31037
31197
 
@@ -31193,13 +31353,13 @@ class UpdaterModule {
31193
31353
  }
31194
31354
  // src/cli/main.ts
31195
31355
  function readVersion5() {
31196
- const here = dirname15(fileURLToPath6(import.meta.url));
31356
+ const here = dirname17(fileURLToPath6(import.meta.url));
31197
31357
  const candidates = [
31198
- join43(here, "..", "..", "package.json"),
31199
- join43(here, "..", "package.json")
31358
+ join44(here, "..", "..", "package.json"),
31359
+ join44(here, "..", "package.json")
31200
31360
  ];
31201
31361
  for (const p of candidates) {
31202
- if (existsSync48(p)) {
31362
+ if (existsSync49(p)) {
31203
31363
  try {
31204
31364
  const raw = JSON.parse(readFileSync33(p, "utf8"));
31205
31365
  if (raw.version)
@@ -31272,15 +31432,15 @@ async function main() {
31272
31432
  agent.shutdown();
31273
31433
  process.exit(exitCode);
31274
31434
  } else {
31275
- const configPath = join43(homedir18(), ".mma", "config.json");
31276
- if (!existsSync48(configPath)) {
31435
+ const configPath = join44(homedir18(), ".mma", "config.json");
31436
+ if (!existsSync49(configPath)) {
31277
31437
  console.log(pc2.yellow(`
31278
31438
  ` + t("cli.first_run") + `
31279
31439
  `));
31280
31440
  const answers = await runSetup();
31281
31441
  const config2 = loadConfig({
31282
- configDir: join43(homedir18(), ".mma"),
31283
- projectConfigPath: projectDir ? join43(projectDir, ".mmrc") : join43(process.cwd(), ".mmrc")
31442
+ configDir: join44(homedir18(), ".mma"),
31443
+ projectConfigPath: projectDir ? join44(projectDir, ".mmrc") : join44(process.cwd(), ".mmrc")
31284
31444
  });
31285
31445
  config2.provider.type = answers.provider;
31286
31446
  config2.provider.baseUrl = answers.apiBase;