micro-models-agent 0.42.0 → 0.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +400 -149
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2552,6 +2552,15 @@ Command: {command}`,
2552
2552
  "plan.active_in_progress": 'Cannot create a new plan: active plan {id} already has progress ({done}/{total} done, current: step {current}). Resume it — use "plan show" to view, then continue working. To replace it, call "plan abort" first, then "plan create" again.',
2553
2553
  "plan.id_ignored": 'note: plan ids are auto-generated; use "plan switch" to activate an existing plan by id.',
2554
2554
  "plan.existing_fresh": "note: the previous active plan had no progress and was preserved as a draft.",
2555
+ "plan.already_active": "Plan {id} is already active — nothing to switch.",
2556
+ "plan.already_archived": "Plan {id} is already archived — nothing to abort.",
2557
+ "plan.aborted_id": "Plan {id} aborted and archived.",
2558
+ "plan.delete_no_id": "Provide a plan id to delete (plan delete id=plan_xxx).",
2559
+ "plan.deleted": "Plan {id} deleted permanently.",
2560
+ "plan.purged": "Deleted {count} plan(s). Plan storage is empty.",
2561
+ "plan.no_deliverables": "note: step {step} names no files — its completion cannot be auto-verified; run an explicit check (e.g. build/tests) before your final answer.",
2562
+ "plan.list_legend": "[*] active · [ ] draft · [-] archived",
2563
+ "exec.plan_nudge": "You made {count} file-changing tool call(s) without a plan. For tasks that create or modify files, or span multiple steps, create a plan first (plan create) with concrete steps (exact filenames, commands, deliverables), then continue.",
2555
2564
  "todo.added": "Added {count} todo(s): {items}",
2556
2565
  "todo.marked_done": "Marked {count} item(s) as done",
2557
2566
  "todo.no_active": "No active todos",
@@ -3195,6 +3204,15 @@ var init_ru = __esm(() => {
3195
3204
  "plan.active_in_progress": 'Нельзя создать новый план: активный план {id} уже имеет прогресс ({done}/{total} выполнено, текущий: шаг {current}). Продолжай его — вызови "plan show", чтобы увидеть, и продолжай работу. Чтобы заменить план, сначала вызови "plan abort", затем "plan create".',
3196
3205
  "plan.id_ignored": 'примечание: id плана генерируется автоматически; используй "plan switch", чтобы активировать существующий план по id.',
3197
3206
  "plan.existing_fresh": "примечание: предыдущий активный план не имел прогресса и сохранён как черновик.",
3207
+ "plan.already_active": "План {id} уже активен — переключаться некуда.",
3208
+ "plan.already_archived": "План {id} уже в архиве — отменять нечего.",
3209
+ "plan.aborted_id": "План {id} отменён и архивирован.",
3210
+ "plan.delete_no_id": "Укажите id плана для удаления (plan delete id=plan_xxx).",
3211
+ "plan.deleted": "План {id} удалён окончательно.",
3212
+ "plan.purged": "Удалено планов: {count}. Хранилище планов пусто.",
3213
+ "plan.no_deliverables": "примечание: шаг {step} не называет файлов — его выполнение нельзя проверить автоматически; перед финальным ответом явно проверь результат (например, запусти сборку/тесты).",
3214
+ "plan.list_legend": "[*] активный · [ ] черновик · [-] архив",
3215
+ "exec.plan_nudge": "Ты сделал(а) {count} вызов(ов), изменяющих файлы, без плана. Для задач, создающих/изменяющих файлы или состоящих из нескольких шагов, сначала создай план (plan create) с конкретными шагами (точные имена файлов, команды, результаты), а потом продолжай.",
3198
3216
  "todo.added": "Добавлено {count} задач: {items}",
3199
3217
  "todo.marked_done": "Отмечено выполненными: {count}",
3200
3218
  "todo.no_active": "Нет активных задач",
@@ -5679,12 +5697,17 @@ class ToolExecutor {
5679
5697
  toolCallId: call.id
5680
5698
  };
5681
5699
  }
5682
- for (const plugin of this.pluginManager.getAllPlugins()) {
5683
- if (plugin.onAfterTool) {
5684
- try {
5685
- await plugin.onAfterTool(this.ctx, call, result);
5686
- } catch (e) {
5687
- this.ctx.logger.warn(`Plugin onAfterTool error: ${e.message}`);
5700
+ if (signal?.aborted) {
5701
+ this.ctx.logger.debug(`Tool ${call.name}: abort, skipping onAfterTool plugins`);
5702
+ } else {
5703
+ const pluginCtx = signal ? { ...this.ctx, signal } : this.ctx;
5704
+ for (const plugin of this.pluginManager.getAllPlugins()) {
5705
+ if (plugin.onAfterTool) {
5706
+ try {
5707
+ await plugin.onAfterTool(pluginCtx, call, result);
5708
+ } catch (e) {
5709
+ this.ctx.logger.warn(`Plugin onAfterTool error: ${e.message}`);
5710
+ }
5688
5711
  }
5689
5712
  }
5690
5713
  }
@@ -10598,8 +10621,46 @@ var init_js_identifiers = __esm(() => {
10598
10621
  });
10599
10622
 
10600
10623
  // src/modules/execution/audit-runners.ts
10601
- import { existsSync as existsSync20, readdirSync as readdirSync5 } from "fs";
10624
+ import { existsSync as existsSync20, readdirSync as readdirSync5, readFileSync as readFileSync10 } from "fs";
10602
10625
  import { dirname as dirname7, join as join11, resolve as resolve11 } from "path";
10626
+ function resolveTestCommand(dir) {
10627
+ const pkgPath = join11(dir, "package.json");
10628
+ if (existsSync20(pkgPath)) {
10629
+ try {
10630
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
10631
+ const script = pkg?.scripts?.test;
10632
+ if (typeof script === "string" && script.trim())
10633
+ return script.trim();
10634
+ } catch {}
10635
+ }
10636
+ for (const f of [
10637
+ "vitest.config.ts",
10638
+ "vitest.config.js",
10639
+ "vitest.config.mjs",
10640
+ "jest.config.js",
10641
+ "jest.config.ts",
10642
+ "jest.config.mjs",
10643
+ "jest.config.cjs",
10644
+ "bunfig.toml"
10645
+ ]) {
10646
+ if (existsSync20(join11(dir, f))) {
10647
+ if (f.startsWith("vitest"))
10648
+ return "bunx vitest run";
10649
+ if (f.startsWith("jest"))
10650
+ return "npx --no-install jest";
10651
+ if (f === "bunfig.toml")
10652
+ return "bun test";
10653
+ }
10654
+ }
10655
+ if (existsSync20(join11(dir, "pyproject.toml")) || existsSync20(join11(dir, "pytest.ini")) || existsSync20(join11(dir, "conftest.py"))) {
10656
+ return "python -m pytest -q";
10657
+ }
10658
+ if (existsSync20(join11(dir, "go.mod")))
10659
+ return "go test ./...";
10660
+ if (existsSync20(join11(dir, "Cargo.toml")))
10661
+ return "cargo test";
10662
+ return "bun test";
10663
+ }
10603
10664
  function findTestFile(dir, depth = 0) {
10604
10665
  if (depth > 5)
10605
10666
  return null;
@@ -10617,7 +10678,7 @@ function findTestFile(dir, depth = 0) {
10617
10678
  const found = findTestFile(full, depth + 1);
10618
10679
  if (found)
10619
10680
  return found;
10620
- } else if (TEST_EXT_RE.test(e.name)) {
10681
+ } else if (TEST_EXT_RE.test(e.name) || PY_TEST_RE.test(e.name)) {
10621
10682
  return full;
10622
10683
  }
10623
10684
  }
@@ -10638,7 +10699,8 @@ function extractFailingNames(output, limit = 5) {
10638
10699
  return names;
10639
10700
  }
10640
10701
  async function runTests(baseDir) {
10641
- const entry = processRegistry.start("bun test", baseDir);
10702
+ const command = resolveTestCommand(baseDir);
10703
+ const entry = processRegistry.start(command, baseDir);
10642
10704
  const exited = await processRegistry.waitForExit(entry.id, 90000);
10643
10705
  const output = entry.log.join(`
10644
10706
  `);
@@ -10649,8 +10711,8 @@ async function runTests(baseDir) {
10649
10711
  passed: true,
10650
10712
  failed: 0,
10651
10713
  passedCount: 0,
10652
- detail: "test run timed out after 90s — result unknown",
10653
- command: "bun test"
10714
+ detail: `test run timed out after 90s — result unknown`,
10715
+ command
10654
10716
  };
10655
10717
  }
10656
10718
  const run = detectTestResults(output);
@@ -10661,7 +10723,7 @@ async function runTests(baseDir) {
10661
10723
  failed: entry.exitCode === 0 ? 0 : 1,
10662
10724
  passedCount: 0,
10663
10725
  detail: output.slice(0, 200).trim(),
10664
- command: "bun test"
10726
+ command
10665
10727
  };
10666
10728
  }
10667
10729
  const names = extractFailingNames(output);
@@ -10671,7 +10733,7 @@ async function runTests(baseDir) {
10671
10733
  failed: run.failed,
10672
10734
  passedCount: run.passed,
10673
10735
  detail: names.length ? names.join("; ") : run.summary || `${run.failed} failed / ${run.passed} passed`,
10674
- command: "bun test"
10736
+ command
10675
10737
  };
10676
10738
  }
10677
10739
  function parseTypecheckErrors(output) {
@@ -10708,7 +10770,7 @@ async function runTypecheck(baseDir) {
10708
10770
  return null;
10709
10771
  return parseTypecheckErrors(output);
10710
10772
  }
10711
- var SKIP_DIRS, TEST_EXT_RE, TEST_STEP_RE;
10773
+ var SKIP_DIRS, TEST_EXT_RE, PY_TEST_RE, TEST_STEP_RE;
10712
10774
  var init_audit_runners = __esm(() => {
10713
10775
  init_bash();
10714
10776
  init_processes();
@@ -10724,6 +10786,7 @@ var init_audit_runners = __esm(() => {
10724
10786
  "vendor"
10725
10787
  ]);
10726
10788
  TEST_EXT_RE = /\.(test|spec)\.[jt]sx?$/i;
10789
+ PY_TEST_RE = /^test_.*\.py$|^.*_test\.py$/i;
10727
10790
  TEST_STEP_RE = /\b(test(ing|s)?|тест(ы|ирование|ировать)?|провер\w*\s+тест|запустить\s+тест)\b|bun test|npm test|vitest|pytest|go test|jest|mocha/i;
10728
10791
  });
10729
10792
 
@@ -11639,6 +11702,8 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
11639
11702
  slog.logToolCall(call, iteration);
11640
11703
  const tokensBeforeTool = contextManager.getEstimatedTokens();
11641
11704
  const result = await toolExecutor.execute(call, this.abortController?.signal);
11705
+ if (this.shutdownRequested)
11706
+ break;
11642
11707
  const duration = Date.now() - startTime;
11643
11708
  if (!result.success)
11644
11709
  anyToolFailed = true;
@@ -11717,6 +11782,8 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
11717
11782
  }
11718
11783
  }
11719
11784
  }
11785
+ if (this.shutdownRequested)
11786
+ break;
11720
11787
  if (anyToolFailed) {
11721
11788
  consecutiveToolFailures++;
11722
11789
  } else {
@@ -13408,7 +13475,7 @@ ${joined}` }
13408
13475
  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.";
13409
13476
 
13410
13477
  // src/tools/chunk-query.ts
13411
- import { readFileSync as readFileSync10 } from "node:fs";
13478
+ import { readFileSync as readFileSync11 } from "node:fs";
13412
13479
  import { resolve as resolve16 } from "node:path";
13413
13480
  var chunkQueryTool;
13414
13481
  var init_chunk_query = __esm(() => {
@@ -13477,7 +13544,7 @@ var init_chunk_query = __esm(() => {
13477
13544
  return { success: false, output: `[SCOPE] ${check.reason || "Path not allowed"}` };
13478
13545
  }
13479
13546
  try {
13480
- content = readFileSync10(resolve16(ctx.baseDir, inputPath), "utf8");
13547
+ content = readFileSync11(resolve16(ctx.baseDir, inputPath), "utf8");
13481
13548
  } catch (e) {
13482
13549
  return { success: false, output: `Cannot read ${inputPath}: ${e.message}` };
13483
13550
  }
@@ -14849,7 +14916,7 @@ var init_search_history = __esm(() => {
14849
14916
  });
14850
14917
 
14851
14918
  // src/modules/memory/search.ts
14852
- import { readFileSync as readFileSync12, existsSync as existsSync26 } from "fs";
14919
+ import { readFileSync as readFileSync13, existsSync as existsSync26 } from "fs";
14853
14920
  import { join as join17 } from "path";
14854
14921
 
14855
14922
  class MemorySearch {
@@ -14864,7 +14931,7 @@ class MemorySearch {
14864
14931
  const path = join17(this.memoryDir, `${name}.md`);
14865
14932
  if (!existsSync26(path))
14866
14933
  continue;
14867
- const content = readFileSync12(path, "utf-8");
14934
+ const content = readFileSync13(path, "utf-8");
14868
14935
  const lines = content.split(`
14869
14936
  `);
14870
14937
  for (const line of lines) {
@@ -14876,7 +14943,7 @@ class MemorySearch {
14876
14943
  const prefsPath = join17(this.memoryDir, "preferences.json");
14877
14944
  if (existsSync26(prefsPath)) {
14878
14945
  try {
14879
- const prefs = JSON.parse(readFileSync12(prefsPath, "utf-8"));
14946
+ const prefs = JSON.parse(readFileSync13(prefsPath, "utf-8"));
14880
14947
  for (const [key, value] of Object.entries(prefs)) {
14881
14948
  const searchStr = `${key}=${value}`;
14882
14949
  if (searchStr.toLowerCase().includes(lowerQuery)) {
@@ -14894,7 +14961,7 @@ var init_search = __esm(() => {
14894
14961
  });
14895
14962
 
14896
14963
  // src/modules/memory/store.ts
14897
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync27, mkdirSync as mkdirSync13 } from "fs";
14964
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync27, mkdirSync as mkdirSync13 } from "fs";
14898
14965
  import { join as join18 } from "path";
14899
14966
 
14900
14967
  class MemoryStore {
@@ -14920,7 +14987,7 @@ class MemoryStore {
14920
14987
  const path = join18(this.memoryDir, `${name}.md`);
14921
14988
  if (!existsSync27(path))
14922
14989
  return "";
14923
- return readFileSync13(path, "utf-8");
14990
+ return readFileSync14(path, "utf-8");
14924
14991
  }
14925
14992
  append(name, entry) {
14926
14993
  const path = join18(this.memoryDir, `${name}.md`);
@@ -14941,7 +15008,7 @@ class MemoryStore {
14941
15008
  if (!existsSync27(path))
14942
15009
  return {};
14943
15010
  try {
14944
- return JSON.parse(readFileSync13(path, "utf-8"));
15011
+ return JSON.parse(readFileSync14(path, "utf-8"));
14945
15012
  } catch {
14946
15013
  return {};
14947
15014
  }
@@ -16230,7 +16297,7 @@ __export(exports_image_utils, {
16230
16297
  detectMime: () => detectMime,
16231
16298
  bufferToDataUrl: () => bufferToDataUrl
16232
16299
  });
16233
- import { readFileSync as readFileSync14 } from "fs";
16300
+ import { readFileSync as readFileSync15 } from "fs";
16234
16301
  import { extname as extname3 } from "path";
16235
16302
  function detectMime(filePath) {
16236
16303
  const ext = extname3(filePath).toLowerCase();
@@ -16251,7 +16318,7 @@ async function readClipboardImage() {
16251
16318
  async function readClipboardFallback() {
16252
16319
  const { platform: platform5 } = await import("os");
16253
16320
  const { execSync } = await import("child_process");
16254
- const { readFileSync: readFileSync15, unlinkSync: unlinkSync4 } = await import("fs");
16321
+ const { readFileSync: readFileSync16, unlinkSync: unlinkSync4 } = await import("fs");
16255
16322
  const { join: join24 } = await import("path");
16256
16323
  const tmpPath = join24(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
16257
16324
  try {
@@ -16262,7 +16329,7 @@ async function readClipboardFallback() {
16262
16329
  } else {
16263
16330
  return null;
16264
16331
  }
16265
- const buf = readFileSync15(tmpPath);
16332
+ const buf = readFileSync16(tmpPath);
16266
16333
  unlinkSync4(tmpPath);
16267
16334
  return buf.length > 0 ? buf : null;
16268
16335
  } catch {
@@ -16273,7 +16340,7 @@ async function readClipboardFallback() {
16273
16340
  }
16274
16341
  }
16275
16342
  async function loadFileAsDataUrl(filePath) {
16276
- const buf = readFileSync14(filePath);
16343
+ const buf = readFileSync15(filePath);
16277
16344
  if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
16278
16345
  try {
16279
16346
  const img = new Bun.Image(buf);
@@ -16700,7 +16767,7 @@ var init_loader = __esm(() => {
16700
16767
 
16701
16768
  // src/modules/plugins/builtin/lint-on-write.ts
16702
16769
  import { spawn as spawn5, execSync } from "child_process";
16703
- import { existsSync as existsSync31, readFileSync as readFileSync15 } from "fs";
16770
+ import { existsSync as existsSync31, readFileSync as readFileSync16 } from "fs";
16704
16771
  import { resolve as resolve18, extname as extname4, join as join25 } from "path";
16705
16772
  import { platform as platform5 } from "os";
16706
16773
  function contentHash(content) {
@@ -16750,22 +16817,29 @@ class LintOnWritePlugin {
16750
16817
  const fullPath = resolve18(ctx.baseDir, path);
16751
16818
  if (!existsSync31(fullPath))
16752
16819
  return;
16820
+ const signal = ctx.signal;
16821
+ if (signal?.aborted)
16822
+ return;
16753
16823
  const ext = extname4(fullPath);
16754
- const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir);
16824
+ const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir, signal);
16825
+ if (signal?.aborted)
16826
+ return;
16755
16827
  if (syntaxError) {
16756
16828
  result.output += `
16757
16829
 
16758
16830
  [Syntax check failed]: ${syntaxError}`;
16759
16831
  return;
16760
16832
  }
16761
- await this.runProjectLint(ctx, result);
16762
- await this.runProjectTypeCheck(fullPath, ctx.baseDir, result);
16833
+ await this.runProjectLint(ctx, result, signal);
16834
+ if (signal?.aborted)
16835
+ return;
16836
+ await this.runProjectTypeCheck(fullPath, ctx.baseDir, result, signal);
16763
16837
  }
16764
- async checkSyntax(filePath, ext, baseDir) {
16838
+ async checkSyntax(filePath, ext, baseDir, signal) {
16765
16839
  if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
16766
16840
  let content = "";
16767
16841
  try {
16768
- content = readFileSync15(filePath, "utf-8");
16842
+ content = readFileSync16(filePath, "utf-8");
16769
16843
  } catch {
16770
16844
  return null;
16771
16845
  }
@@ -16775,7 +16849,9 @@ class LintOnWritePlugin {
16775
16849
  return cached.error;
16776
16850
  }
16777
16851
  try {
16778
- await runAsync(`bun build --no-bundle --target=bun "${filePath}"`, baseDir, 1e4);
16852
+ await runAsync(`bun build --no-bundle --target=bun "${filePath}"`, baseDir, 1e4, signal);
16853
+ if (signal?.aborted)
16854
+ return null;
16779
16855
  syntaxCache.set(filePath, { hash, error: null });
16780
16856
  return null;
16781
16857
  } catch (err) {
@@ -16791,7 +16867,7 @@ class LintOnWritePlugin {
16791
16867
  }
16792
16868
  if (ext === ".js" || ext === ".jsx" || ext === ".cjs" || ext === ".mjs") {
16793
16869
  try {
16794
- await runAsync(`node --check "${filePath}"`, baseDir, 5000);
16870
+ await runAsync(`node --check "${filePath}"`, baseDir, 5000, signal);
16795
16871
  return null;
16796
16872
  } catch (err) {
16797
16873
  const stderr = err.stderr?.toString() || "";
@@ -16802,19 +16878,19 @@ class LintOnWritePlugin {
16802
16878
  }
16803
16879
  return null;
16804
16880
  }
16805
- async runProjectLint(ctx, result) {
16881
+ async runProjectLint(ctx, result, signal) {
16806
16882
  try {
16807
16883
  const packageJsonPath = join25(ctx.baseDir, "package.json");
16808
16884
  if (!existsSync31(packageJsonPath)) {
16809
16885
  return;
16810
16886
  }
16811
- const packageJson = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
16887
+ const packageJson = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
16812
16888
  const lintScript = packageJson.scripts?.lint;
16813
16889
  if (!lintScript) {
16814
16890
  return;
16815
16891
  }
16816
16892
  ctx.logger.debug(`Running lint: ${lintScript}`);
16817
- await runAsync(lintScript, ctx.baseDir, 30000);
16893
+ await runAsync(lintScript, ctx.baseDir, 30000, signal);
16818
16894
  ctx.logger.debug("Lint passed");
16819
16895
  } catch (err) {
16820
16896
  const stderr = (err.stderr?.toString?.() || "").trim();
@@ -16828,7 +16904,7 @@ class LintOnWritePlugin {
16828
16904
  [Project lint failed]: ${detail}`;
16829
16905
  }
16830
16906
  }
16831
- async runProjectTypeCheck(filePath, baseDir, result) {
16907
+ async runProjectTypeCheck(filePath, baseDir, result, signal) {
16832
16908
  const projectRoot = findProjectRoot(filePath, baseDir, ["tsconfig.json", "package.json"]);
16833
16909
  const tsconfigPath = join25(projectRoot, "tsconfig.json");
16834
16910
  if (!existsSync31(tsconfigPath)) {
@@ -16845,7 +16921,7 @@ class LintOnWritePlugin {
16845
16921
  return;
16846
16922
  }
16847
16923
  this._checkTimestamp = now;
16848
- this._checkPromise = this.runTscCheck(projectRoot);
16924
+ this._checkPromise = this.runTscCheck(projectRoot, signal);
16849
16925
  const error = await this._checkPromise;
16850
16926
  if (error) {
16851
16927
  result.output += `
@@ -16853,9 +16929,9 @@ class LintOnWritePlugin {
16853
16929
  [Project typecheck failed]: ${error}`;
16854
16930
  }
16855
16931
  }
16856
- async runTscCheck(baseDir) {
16932
+ async runTscCheck(baseDir, signal) {
16857
16933
  try {
16858
- await runAsync(`npx tsc --noEmit --skipLibCheck`, baseDir, 30000);
16934
+ await runAsync(`npx tsc --noEmit --skipLibCheck`, baseDir, 30000, signal);
16859
16935
  return null;
16860
16936
  } catch (err) {
16861
16937
  if (err.status === 127 || err.message.includes("not found") || err.message.includes("ENOENT")) {
@@ -16871,7 +16947,7 @@ class LintOnWritePlugin {
16871
16947
  }
16872
16948
  }
16873
16949
  }
16874
- function runAsync(command, cwd, timeoutMs) {
16950
+ function runAsync(command, cwd, timeoutMs, signal) {
16875
16951
  return new Promise((resolve19, reject) => {
16876
16952
  const child = spawn5(command, {
16877
16953
  cwd,
@@ -16892,15 +16968,27 @@ function runAsync(command, cwd, timeoutMs) {
16892
16968
  child.kill();
16893
16969
  reject(new Error(`Command timed out after ${timeoutMs}ms`));
16894
16970
  }, timeoutMs);
16971
+ const onAbort = () => child.kill();
16972
+ if (signal?.aborted) {
16973
+ child.kill();
16974
+ } else {
16975
+ signal?.addEventListener("abort", onAbort, { once: true });
16976
+ }
16895
16977
  child.on("error", (err) => {
16896
16978
  clearTimeout(timer);
16897
- reject(err);
16979
+ signal?.removeEventListener("abort", onAbort);
16980
+ if (signal?.aborted) {
16981
+ resolve19({ stdout, stderr });
16982
+ } else {
16983
+ reject(err);
16984
+ }
16898
16985
  });
16899
16986
  child.on("close", (code) => {
16900
16987
  clearTimeout(timer);
16988
+ signal?.removeEventListener("abort", onAbort);
16901
16989
  stdout += decoder.decode();
16902
16990
  stderr += decoder.decode();
16903
- if (code === 0) {
16991
+ if (signal?.aborted || code === 0) {
16904
16992
  resolve19({ stdout, stderr });
16905
16993
  } else {
16906
16994
  const err = new Error(`Command failed with exit code ${code}`);
@@ -16944,25 +17032,6 @@ function generatePlanId() {
16944
17032
  }
16945
17033
 
16946
17034
  class PlanCreator {
16947
- static isMultiStep(task) {
16948
- const fileCount = (task.match(/\b[\w./-]+\.[a-z]+\b/gi) || []).length;
16949
- if (fileCount > 1)
16950
- return true;
16951
- const actionWords = [
16952
- "implement",
16953
- "create",
16954
- "add",
16955
- "build",
16956
- "setup",
16957
- "configure",
16958
- "write",
16959
- "make",
16960
- "develop"
16961
- ];
16962
- const words = task.split(/\s+/);
16963
- const hasActionWord = actionWords.some((w) => task.toLowerCase().includes(w));
16964
- return hasActionWord && words.length > 8;
16965
- }
16966
17035
  static createPlan(title, stepDescriptions, baseDir, kinds) {
16967
17036
  const stepCount = stepDescriptions.length;
16968
17037
  return {
@@ -16983,16 +17052,17 @@ class PlanCreator {
16983
17052
  const baseTitle = plan.title.replace(/^\[\d+[^]]*\]\s*/, "");
16984
17053
  const newTitle = title || baseTitle;
16985
17054
  const totalSteps = kept.length + newSteps.length;
16986
- const added = newSteps.map((desc, i) => ({
16987
- id: kept.length + i + 1,
17055
+ const added = newSteps.map((desc) => ({
17056
+ id: -1,
16988
17057
  description: desc,
16989
17058
  status: "pending",
16990
17059
  kind: "create"
16991
17060
  }));
17061
+ const steps = [...kept, ...added].map((s, i) => ({ ...s, id: i + 1 }));
16992
17062
  return {
16993
17063
  id: plan.id,
16994
17064
  title: `[${totalSteps}] ${newTitle}`,
16995
- steps: [...kept, ...added],
17065
+ steps,
16996
17066
  createdAt: plan.createdAt,
16997
17067
  baseDir: plan.baseDir,
16998
17068
  name: plan.name
@@ -17000,10 +17070,13 @@ class PlanCreator {
17000
17070
  }
17001
17071
  static toPromptBlock(plan, currentStepIndex) {
17002
17072
  const date = plan.createdAt.slice(0, 10);
17073
+ const doneCount = plan.steps.filter((s) => s.status === "done").length;
17074
+ const terminal = plan.steps.every((s) => s.status === "done" || s.status === "skipped");
17075
+ const progress = terminal ? `${doneCount}/${plan.steps.length} done, complete` : `${doneCount}/${plan.steps.length} done, current: step ${currentStepIndex + 1}`;
17003
17076
  const lines = [
17004
17077
  `[${plan.id}] ${plan.title}`,
17005
17078
  `Dir: ${plan.baseDir}`,
17006
- `Created: ${date} | Progress: ${plan.steps.filter((s) => s.status === "done").length}/${plan.steps.length} done, current: step ${currentStepIndex + 1}`,
17079
+ `Created: ${date} | Progress: ${progress}`,
17007
17080
  ``
17008
17081
  ];
17009
17082
  for (const step of plan.steps) {
@@ -17080,11 +17153,11 @@ class PlanTracker {
17080
17153
  var init_tracker = () => {};
17081
17154
 
17082
17155
  // src/modules/execution/plan-store.ts
17083
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync32, readdirSync as readdirSync10, rmSync } from "fs";
17156
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync32, readdirSync as readdirSync10, rmSync } from "fs";
17084
17157
  import { join as join26 } from "path";
17085
17158
  function readPlanFile(path, fallbackBaseDir) {
17086
17159
  try {
17087
- const raw = readFileSync16(path, "utf-8");
17160
+ const raw = readFileSync17(path, "utf-8");
17088
17161
  if (!raw.trim())
17089
17162
  return null;
17090
17163
  const parsed = JSON.parse(raw);
@@ -17227,6 +17300,41 @@ class PlanStore {
17227
17300
  return { plan: archived, status: "archived" };
17228
17301
  return null;
17229
17302
  }
17303
+ deletePlan(id) {
17304
+ const active = this.loadActive();
17305
+ if (active && active.id === id) {
17306
+ this.clearActive();
17307
+ return "active";
17308
+ }
17309
+ const draftPath = join26(this.draftsDir, `${id}.json`);
17310
+ if (existsSync32(draftPath)) {
17311
+ rmSync(draftPath, { force: true });
17312
+ return "draft";
17313
+ }
17314
+ const archivedPath = join26(this.archiveDir, `${id}.json`);
17315
+ if (existsSync32(archivedPath)) {
17316
+ rmSync(archivedPath, { force: true });
17317
+ return "archived";
17318
+ }
17319
+ return null;
17320
+ }
17321
+ purgeAll() {
17322
+ let n = 0;
17323
+ const active = this.loadActive();
17324
+ if (active) {
17325
+ this.clearActive();
17326
+ n++;
17327
+ }
17328
+ for (const p of this.listDrafts()) {
17329
+ this.removeDraft(p.id);
17330
+ n++;
17331
+ }
17332
+ for (const p of this.listArchived()) {
17333
+ this.removeArchived(p.id);
17334
+ n++;
17335
+ }
17336
+ return n;
17337
+ }
17230
17338
  }
17231
17339
  var LEGACY_FILE = "plan.json";
17232
17340
  var init_plan_store = () => {};
@@ -17300,16 +17408,18 @@ function createPlanToolDefinitions(deps) {
17300
17408
  {
17301
17409
  name: "plan",
17302
17410
  alwaysOn: true,
17303
- description: `Create, update, show, abort, list, switch, or re-plan multi-step plans.
17411
+ description: `Create, update, show, abort, list, switch, delete, purge, or re-plan multi-step plans.
17304
17412
 
17305
17413
  Actions:
17306
17414
  - create: Start a new plan. Previous active plan is auto-preserved: incomplete → draft, complete → archive.
17307
17415
  - update: Mark step status (done/failed/skipped), or rebuild plan with new steps.
17308
17416
  - show: Print current plan checklist.
17309
- - abort: Archive current plan and clear active slot.
17417
+ - abort: Archive the current plan (or the plan given by id) and clear the active slot.
17310
17418
  - list: Show all plans (active, drafts, archived) with progress.
17311
17419
  - switch: Make a different plan active (by plan id).
17312
17420
  - re-plan: Iterative replanning: keep completed steps, replace remaining with new steps.
17421
+ - delete: Permanently delete a plan by id (plan delete id=plan_xxx).
17422
+ - purge: Delete ALL plans (active, drafts, archived).
17313
17423
 
17314
17424
  Write CONCRETE steps with exact file paths and commands:
17315
17425
  - Specify WHICH files to create with exact paths (e.g. "create src/components/Header.tsx with navigation and logo")
@@ -17324,7 +17434,17 @@ Write CONCRETE steps with exact file paths and commands:
17324
17434
  properties: {
17325
17435
  action: {
17326
17436
  type: "string",
17327
- enum: ["create", "update", "show", "abort", "list", "switch", "re-plan"]
17437
+ enum: [
17438
+ "create",
17439
+ "update",
17440
+ "show",
17441
+ "abort",
17442
+ "list",
17443
+ "switch",
17444
+ "re-plan",
17445
+ "delete",
17446
+ "purge"
17447
+ ]
17328
17448
  },
17329
17449
  title: { type: "string" },
17330
17450
  steps: { type: "array", items: { type: "string" } },
@@ -17352,6 +17472,8 @@ Write CONCRETE steps with exact file paths and commands:
17352
17472
  const namePart = m.name ? ` (${m.name})` : "";
17353
17473
  return `${icon} ${m.id}${namePart} — ${m.title} ${m.doneCount}/${m.stepCount}`;
17354
17474
  });
17475
+ lines.push("");
17476
+ lines.push(t("plan.list_legend"));
17355
17477
  return {
17356
17478
  success: true,
17357
17479
  output: `${t("plan.list_header")}
@@ -17371,6 +17493,16 @@ ${lines.join(`
17371
17493
  output: t("plan.not_found", { id: planId })
17372
17494
  };
17373
17495
  }
17496
+ if (found.status === "active") {
17497
+ return {
17498
+ success: true,
17499
+ output: t("plan.already_active", {
17500
+ id: found.plan.id,
17501
+ title: found.plan.title
17502
+ }),
17503
+ display: deps.trackerRef.current?.toPromptBlock()
17504
+ };
17505
+ }
17374
17506
  deps.preserveActive();
17375
17507
  if (found.status === "draft") {
17376
17508
  deps.store.removeDraft(found.plan.id);
@@ -17378,7 +17510,7 @@ ${lines.join(`
17378
17510
  deps.store.removeArchived(found.plan.id);
17379
17511
  }
17380
17512
  deps.setPlan(found.plan);
17381
- const display = PlanCreator.toPromptBlock(found.plan, 0);
17513
+ const display = deps.trackerRef.current?.toPromptBlock();
17382
17514
  return {
17383
17515
  success: true,
17384
17516
  output: t("plan.switched", {
@@ -17401,7 +17533,7 @@ ${lines.join(`
17401
17533
  const replanned = PlanCreator.replan(oldPlan, newSteps, args.title ? String(args.title) : undefined);
17402
17534
  const keptCount = replanned.steps.length - newSteps.length;
17403
17535
  deps.setPlan(replanned);
17404
- const display = PlanCreator.toPromptBlock(replanned, keptCount);
17536
+ const display = deps.trackerRef.current?.toPromptBlock();
17405
17537
  return {
17406
17538
  success: true,
17407
17539
  output: t("plan.replanned", {
@@ -17514,6 +17646,7 @@ ${display}`,
17514
17646
  if (tracker.isComplete()) {
17515
17647
  const plan = tracker.getPlan();
17516
17648
  deps.store.archivePlan(plan);
17649
+ deps.recordCompleted(plan);
17517
17650
  deps.trackerRef.current = null;
17518
17651
  const done = plan.steps.filter((s) => s.status === "done").length;
17519
17652
  return {
@@ -17580,9 +17713,13 @@ ${progress2}`,
17580
17713
  tracker.addNote(Number(args.step), String(args.note));
17581
17714
  tracker.syncCurrentStep();
17582
17715
  deps.store.saveActive(tracker.getPlan());
17716
+ const vacuousGate = status === "done" && !deps.hasStepDeliverables(target);
17717
+ const vacuousNote = vacuousGate ? `
17718
+ ${t("plan.no_deliverables", { step: String(stepId) })}` : "";
17583
17719
  if (tracker.isComplete()) {
17584
17720
  const plan = tracker.getPlan();
17585
17721
  deps.store.archivePlan(plan);
17722
+ deps.recordCompleted(plan);
17586
17723
  deps.trackerRef.current = null;
17587
17724
  const done = plan.steps.filter((s) => s.status === "done").length;
17588
17725
  return {
@@ -17592,7 +17729,7 @@ ${t("plan.completed_archived", {
17592
17729
  id: plan.id,
17593
17730
  done: String(done),
17594
17731
  total: String(plan.steps.length)
17595
- })}`
17732
+ })}${vacuousNote}`
17596
17733
  };
17597
17734
  }
17598
17735
  const progress = tracker.getProgressString();
@@ -17601,7 +17738,7 @@ ${t("plan.completed_archived", {
17601
17738
  return {
17602
17739
  success: true,
17603
17740
  output: `${t("plan.step_status", { step: String(args.step), status: String(args.status || "done") })}
17604
- ${progress}`,
17741
+ ${progress}${vacuousNote}`,
17605
17742
  display
17606
17743
  };
17607
17744
  }
@@ -17615,7 +17752,7 @@ ${progress}`,
17615
17752
  }
17616
17753
  const plan = PlanCreator.createPlan(title, steps, deps.baseDir, parsed.kinds ?? []);
17617
17754
  deps.setPlan(plan);
17618
- const display = PlanCreator.toPromptBlock(plan, 0);
17755
+ const display = deps.trackerRef.current?.toPromptBlock();
17619
17756
  const output = t("plan.updated", {
17620
17757
  title,
17621
17758
  steps: String(steps.length)
@@ -17627,14 +17764,71 @@ ${progress}`,
17627
17764
  };
17628
17765
  }
17629
17766
  if (action === "abort") {
17767
+ const planId = args.id ? String(args.id) : "";
17768
+ if (planId) {
17769
+ const found = deps.store.find(planId);
17770
+ if (!found) {
17771
+ return {
17772
+ success: false,
17773
+ output: t("plan.not_found", { id: planId })
17774
+ };
17775
+ }
17776
+ if (found.status === "archived") {
17777
+ return {
17778
+ success: false,
17779
+ output: t("plan.already_archived", { id: planId })
17780
+ };
17781
+ }
17782
+ deps.store.archivePlan(found.plan);
17783
+ if (found.status === "active") {
17784
+ deps.trackerRef.current = null;
17785
+ deps.clearCompleted();
17786
+ }
17787
+ return {
17788
+ success: true,
17789
+ output: t("plan.aborted_id", { id: found.plan.id })
17790
+ };
17791
+ }
17630
17792
  const tracker = deps.trackerRef.current;
17631
- if (tracker) {
17632
- deps.store.archivePlan(tracker.getPlan());
17793
+ if (!tracker) {
17794
+ return { success: false, output: t("plan.no_active") };
17633
17795
  }
17796
+ deps.store.archivePlan(tracker.getPlan());
17634
17797
  deps.trackerRef.current = null;
17635
17798
  deps.store.clearActive();
17799
+ deps.clearCompleted();
17636
17800
  return { success: true, output: t("plan.aborted") };
17637
17801
  }
17802
+ if (action === "delete") {
17803
+ const planId = String(args.id || "");
17804
+ if (!planId) {
17805
+ return { success: false, output: t("plan.delete_no_id") };
17806
+ }
17807
+ const deleted = deps.store.deletePlan(planId);
17808
+ if (!deleted) {
17809
+ return {
17810
+ success: false,
17811
+ output: t("plan.not_found", { id: planId })
17812
+ };
17813
+ }
17814
+ if (deleted === "active") {
17815
+ deps.trackerRef.current = null;
17816
+ deps.clearCompleted();
17817
+ }
17818
+ return {
17819
+ success: true,
17820
+ output: t("plan.deleted", { id: planId })
17821
+ };
17822
+ }
17823
+ if (action === "purge") {
17824
+ const count = deps.store.purgeAll();
17825
+ deps.trackerRef.current = null;
17826
+ deps.clearCompleted();
17827
+ return {
17828
+ success: true,
17829
+ output: t("plan.purged", { count: String(count) })
17830
+ };
17831
+ }
17638
17832
  if (!deps.trackerRef.current) {
17639
17833
  return { success: false, output: t("plan.no_active") };
17640
17834
  }
@@ -17825,6 +18019,8 @@ function createExecutionPlugin(deps) {
17825
18019
  deps.state.consecutivePlanWarnings = 0;
17826
18020
  deps.state.lastStepId = -1;
17827
18021
  deps.state.stuckNotified = false;
18022
+ deps.state.mutationsWithoutPlan = 0;
18023
+ deps.state.planNudgeSent = false;
17828
18024
  } else {
17829
18025
  const step = deps.trackerRef.current?.getCurrentStep();
17830
18026
  if (deps.trackerRef.current && step) {
@@ -17835,22 +18031,21 @@ function createExecutionPlugin(deps) {
17835
18031
  }
17836
18032
  deps.stuckDetector.setCurrentStep(step.id, step.description);
17837
18033
  deps.stuckDetector.recordIteration(step.id);
18034
+ deps.state.mutationsWithoutPlan = 0;
18035
+ deps.state.planNudgeSent = false;
17838
18036
  } else {
17839
18037
  deps.stuckDetector.reset();
17840
18038
  deps.state.consecutivePlanWarnings = 0;
17841
18039
  deps.state.lastStepId = -1;
17842
18040
  deps.state.stuckNotified = false;
17843
- const iter = typeof ctx.iteration === "number" ? ctx.iteration : 0;
17844
- if (iter === 3 && !deps.trackerRef.current && ctx.contextManager) {
17845
- ctx.contextManager.addMessage({
17846
- role: "user",
17847
- content: `<system-summary>You have made 3 tool calls without creating a plan. For any task that involves creating files, installing packages, or multiple steps — you MUST use plan create BEFORE continuing. Use the plan tool now with concrete steps (exact filenames, commands, deliverables). Do NOT make any more write/edit/bash calls until you have a plan.</system-summary>`
17848
- });
17849
- }
17850
- if (iter >= 6 && !deps.trackerRef.current && ctx.contextManager) {
18041
+ const mutations = deps.state.mutationsWithoutPlan;
18042
+ if (mutations >= PLAN_NUDGE_THRESHOLD && !deps.state.planNudgeSent && ctx.contextManager) {
18043
+ deps.state.planNudgeSent = true;
17851
18044
  ctx.contextManager.addMessage({
17852
18045
  role: "user",
17853
- content: `<system-summary>STOP. ${iter} iterations without a plan. You MUST call plan create RIGHT NOW. No more tool calls until you create a plan.</system-summary>`
18046
+ content: `<system-summary>${t("exec.plan_nudge", {
18047
+ count: String(mutations)
18048
+ })}</system-summary>`
17854
18049
  });
17855
18050
  }
17856
18051
  }
@@ -17943,6 +18138,9 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
17943
18138
  const args = ctx?.args;
17944
18139
  if (toolName && args) {
17945
18140
  deps.stuckDetector.recordToolCall(toolName, args);
18141
+ if (!deps.trackerRef.current && (toolName === "write_file" || toolName === "edit_file" || toolName === "bash" || toolName === "download_file")) {
18142
+ deps.state.mutationsWithoutPlan++;
18143
+ }
17946
18144
  }
17947
18145
  },
17948
18146
  onAfterTool: (ctx, call, result) => {
@@ -18029,7 +18227,7 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
18029
18227
  }
18030
18228
  };
18031
18229
  }
18032
- var STUCK_RECOVERY_COOLDOWN = 5, MAX_PLAN_WARNINGS_BEFORE_BLOCK = 3, FORCE_SKIP_THRESHOLD = 10;
18230
+ var STUCK_RECOVERY_COOLDOWN = 5, MAX_PLAN_WARNINGS_BEFORE_BLOCK = 3, FORCE_SKIP_THRESHOLD = 10, PLAN_NUDGE_THRESHOLD = 2;
18033
18231
  var init_execution_plugin = __esm(() => {
18034
18232
  init_i18n();
18035
18233
  init_bash();
@@ -18037,7 +18235,7 @@ var init_execution_plugin = __esm(() => {
18037
18235
  });
18038
18236
 
18039
18237
  // src/modules/execution/module.ts
18040
- import { existsSync as existsSync33, readFileSync as readFileSync17 } from "fs";
18238
+ import { existsSync as existsSync33, readFileSync as readFileSync18 } from "fs";
18041
18239
  import { resolve as resolve19 } from "path";
18042
18240
 
18043
18241
  class ExecutionModule {
@@ -18049,6 +18247,7 @@ class ExecutionModule {
18049
18247
  store;
18050
18248
  baseDir;
18051
18249
  _auditSkipsRemaining = 0;
18250
+ completedPlan = null;
18052
18251
  pendingMessages = [];
18053
18252
  forbiddenBashFailures = new Map;
18054
18253
  searchRunner;
@@ -18062,7 +18261,9 @@ class ExecutionModule {
18062
18261
  consecutivePlanWarnings: 0,
18063
18262
  lastStepId: -1,
18064
18263
  stuckNotified: false,
18065
- depsGateHints: new Map
18264
+ depsGateHints: new Map,
18265
+ mutationsWithoutPlan: 0,
18266
+ planNudgeSent: false
18066
18267
  };
18067
18268
  trackerRef = (() => {
18068
18269
  const self = this;
@@ -18087,9 +18288,17 @@ class ExecutionModule {
18087
18288
  }
18088
18289
  setPlan(plan) {
18089
18290
  this.tracker = new PlanTracker(plan);
18291
+ this.tracker.syncCurrentStep();
18090
18292
  this.store.saveActive(plan);
18293
+ this.completedPlan = null;
18091
18294
  this._auditSkipsRemaining = 0;
18092
18295
  }
18296
+ recordCompleted(plan) {
18297
+ this.completedPlan = plan;
18298
+ }
18299
+ clearCompleted() {
18300
+ this.completedPlan = null;
18301
+ }
18093
18302
  restorePlan() {
18094
18303
  const plan = this.store.loadActive();
18095
18304
  if (!plan)
@@ -18167,8 +18376,22 @@ class ExecutionModule {
18167
18376
  }).catch((e) => ctx.logger?.warn(`error web search: ${e.message}`));
18168
18377
  }
18169
18378
  async runFinalAudit() {
18170
- if (!this.tracker)
18171
- return null;
18379
+ if (!this.tracker) {
18380
+ if (!this.completedPlan)
18381
+ return null;
18382
+ const plan2 = this.completedPlan;
18383
+ const audit2 = await this.auditor.audit(plan2);
18384
+ const pendingSteps2 = plan2.steps.flatMap((s) => s.status !== "done" && s.status !== "skipped" ? [`${s.id}. ${s.description}`] : []);
18385
+ const done2 = plan2.steps.filter((s) => s.status === "done").length;
18386
+ return {
18387
+ passed: audit2.passed && pendingSteps2.length === 0,
18388
+ done: done2,
18389
+ total: plan2.steps.length,
18390
+ pendingSteps: pendingSteps2,
18391
+ missingFiles: audit2.missingFiles,
18392
+ summary: audit2.summary
18393
+ };
18394
+ }
18172
18395
  if (this._auditSkipsRemaining > 0) {
18173
18396
  this._auditSkipsRemaining--;
18174
18397
  return null;
@@ -18216,6 +18439,9 @@ class ExecutionModule {
18216
18439
  trackerRef: this.trackerRef,
18217
18440
  preserveActive: () => this.preserveActive(),
18218
18441
  setPlan: (p) => this.setPlan(p),
18442
+ recordCompleted: (p) => this.recordCompleted(p),
18443
+ clearCompleted: () => this.clearCompleted(),
18444
+ hasStepDeliverables: (s) => this.hasStepDeliverables(s),
18219
18445
  missingStepDeliverables: (s) => this.missingStepDeliverables(s),
18220
18446
  stillExistingDeliverables: (s) => this.stillExistingDeliverables(s),
18221
18447
  parseKinds: (a, st) => this.parseKinds(a, st),
@@ -18267,7 +18493,7 @@ class ExecutionModule {
18267
18493
  const stepPaths = extractFileLikeTokens(stripUrls(step.description)).map((p) => p.toLowerCase());
18268
18494
  if (stepPaths.length === 0)
18269
18495
  return null;
18270
- const argStr = JSON.stringify(call.arguments);
18496
+ const argStr = this.pathArgStrings(call.arguments).join(" ");
18271
18497
  const callPaths = extractFileLikeTokens(stripUrls(argStr)).map((p) => p.toLowerCase());
18272
18498
  if (callPaths.length === 0)
18273
18499
  return null;
@@ -18292,13 +18518,31 @@ class ExecutionModule {
18292
18518
  tool: call.name
18293
18519
  });
18294
18520
  }
18521
+ pathArgStrings(args) {
18522
+ if (!args)
18523
+ return [];
18524
+ const out = [];
18525
+ for (const [key, value] of Object.entries(args)) {
18526
+ if (!/path|file|dir|src|dst|source|target|input|output|destination|glob|workdir|cwd|command|pattern|query/i.test(key)) {
18527
+ continue;
18528
+ }
18529
+ if (typeof value === "string")
18530
+ out.push(value);
18531
+ else if (Array.isArray(value)) {
18532
+ for (const v of value)
18533
+ if (typeof v === "string")
18534
+ out.push(v);
18535
+ }
18536
+ }
18537
+ return out;
18538
+ }
18295
18539
  advancePlanIfStepComplete(contextManager, sessionLog) {
18296
18540
  const step = this.tracker?.getCurrentStep();
18297
18541
  if (!step)
18298
18542
  return;
18299
18543
  const stepText = step.description.toLowerCase();
18300
18544
  const stepPaths = extractFileLikeTokens(stripUrls(step.description)) || [];
18301
- const isDepsStep = stepText.includes("install") || stepText.includes("зависим") || stepText.includes("init") || stepText.includes("инициализац");
18545
+ const isDepsStep = /(?:npm|bun|yarn|pnpm|pip|pip3|pipenv|poetry|composer|deno|go|gem|cargo)\s+(?:install|add|init|i|get)\b|bun\s+(?:add|install)|npm\s+(?:i|install|add)|(?:install|установ\w*)\s+(?:dependencies|зависимост\w*|пакет\w*|packages?)/i.test(stepText);
18302
18546
  if (isDepsStep) {
18303
18547
  const lockFiles = [
18304
18548
  "package-lock.json",
@@ -18332,18 +18576,21 @@ class ExecutionModule {
18332
18576
  }
18333
18577
  if (stepPaths.length === 0)
18334
18578
  return;
18335
- const allExist = stepPaths.every((p) => existsSync33(resolve19(this.baseDir, p)));
18336
- const allGone = stepPaths.every((p) => !existsSync33(resolve19(this.baseDir, p)));
18579
+ const resolved = stepPaths.map((p) => findExistingFile(this.baseDir, p));
18580
+ const allExist = resolved.every((r) => r !== null);
18581
+ const allGone = resolved.every((r) => r === null);
18337
18582
  const satisfied = step.kind === "delete" ? allGone && !allExist : allExist;
18338
18583
  if (!satisfied)
18339
18584
  return;
18340
18585
  if (step.kind !== "delete") {
18341
18586
  const emptyFiles = [];
18342
- for (const p of stepPaths) {
18587
+ for (const r of resolved) {
18588
+ if (!r)
18589
+ continue;
18343
18590
  try {
18344
- const content = readFileSync17(resolve19(this.baseDir, p), "utf-8");
18591
+ const content = readFileSync18(r, "utf-8");
18345
18592
  if (content.trim().length < 10) {
18346
- emptyFiles.push(p);
18593
+ emptyFiles.push(r);
18347
18594
  }
18348
18595
  } catch {}
18349
18596
  }
@@ -18376,6 +18623,7 @@ class ExecutionModule {
18376
18623
  if (this.tracker?.isComplete()) {
18377
18624
  const completed = this.tracker.getPlan();
18378
18625
  this.store.archivePlan(completed);
18626
+ this.recordCompleted(completed);
18379
18627
  this.tracker = null;
18380
18628
  sessionLog?.plan("auto-archive", `Plan ${completed.id} complete — archived`);
18381
18629
  }
@@ -18392,6 +18640,9 @@ class ExecutionModule {
18392
18640
  return [];
18393
18641
  return tokens.filter((p) => findExistingFile(this.baseDir, p));
18394
18642
  }
18643
+ hasStepDeliverables(step) {
18644
+ return extractFileLikeTokens(stripUrls(step.description)).length > 0;
18645
+ }
18395
18646
  parseKinds(args, steps) {
18396
18647
  if (args.kinds === undefined)
18397
18648
  return { kinds: null, error: null };
@@ -18445,7 +18696,7 @@ var init_module = __esm(() => {
18445
18696
  });
18446
18697
 
18447
18698
  // src/modules/security/session-encryption.ts
18448
- import { readFileSync as readFileSync18, writeFileSync as writeFileSync11, existsSync as existsSync34, readdirSync as readdirSync11, unlinkSync as unlinkSync4 } from "fs";
18699
+ import { readFileSync as readFileSync19, writeFileSync as writeFileSync11, existsSync as existsSync34, readdirSync as readdirSync11, unlinkSync as unlinkSync4 } from "fs";
18449
18700
  import { join as join27 } from "path";
18450
18701
  import { homedir as homedir8 } from "os";
18451
18702
 
@@ -18500,7 +18751,7 @@ class SessionFileEncryptor {
18500
18751
  return lines.map((line) => this.decryptFileContent(line));
18501
18752
  }
18502
18753
  readSessionFile(filePath) {
18503
- const content = readFileSync18(filePath, "utf8");
18754
+ const content = readFileSync19(filePath, "utf8");
18504
18755
  return this.decryptFileContent(content);
18505
18756
  }
18506
18757
  writeSessionFile(filePath, content) {
@@ -18508,7 +18759,7 @@ class SessionFileEncryptor {
18508
18759
  writeFileSync11(filePath, encrypted, "utf8");
18509
18760
  }
18510
18761
  readSessionJSON(filePath) {
18511
- const content = readFileSync18(filePath, "utf8");
18762
+ const content = readFileSync19(filePath, "utf8");
18512
18763
  return this.decryptJSON(content);
18513
18764
  }
18514
18765
  writeSessionJSON(filePath, obj) {
@@ -18516,7 +18767,7 @@ class SessionFileEncryptor {
18516
18767
  writeFileSync11(filePath, content, "utf8");
18517
18768
  }
18518
18769
  readSessionJSONL(filePath) {
18519
- const content = readFileSync18(filePath, "utf8");
18770
+ const content = readFileSync19(filePath, "utf8");
18520
18771
  const lines = content.split(`
18521
18772
  `).filter((line) => line.trim());
18522
18773
  const decryptedLines = this.decryptJSONL(lines);
@@ -18544,7 +18795,7 @@ class SessionFileEncryptor {
18544
18795
  const filePath = join27(sessionDir, file);
18545
18796
  if (existsSync34(filePath) && !file.endsWith(".enc")) {
18546
18797
  try {
18547
- const content = readFileSync18(filePath, "utf8");
18798
+ const content = readFileSync19(filePath, "utf8");
18548
18799
  const encrypted = this.encryptFileContent(content);
18549
18800
  writeFileSync11(filePath + ".enc", encrypted, "utf8");
18550
18801
  unlinkSync4(filePath);
@@ -18561,7 +18812,7 @@ class SessionFileEncryptor {
18561
18812
  const encFilePath = join27(sessionDir, file);
18562
18813
  const decFilePath = encFilePath.slice(0, -4);
18563
18814
  try {
18564
- const content = readFileSync18(encFilePath, "utf8");
18815
+ const content = readFileSync19(encFilePath, "utf8");
18565
18816
  const decrypted = this.decryptFileContent(content);
18566
18817
  writeFileSync11(decFilePath, decrypted, "utf8");
18567
18818
  unlinkSync4(encFilePath);
@@ -18586,7 +18837,7 @@ import {
18586
18837
  existsSync as existsSync35,
18587
18838
  mkdirSync as mkdirSync15,
18588
18839
  readdirSync as readdirSync12,
18589
- readFileSync as readFileSync19,
18840
+ readFileSync as readFileSync20,
18590
18841
  rmSync as rmSync2,
18591
18842
  writeFileSync as writeFileSync12,
18592
18843
  appendFileSync as appendFileSync6
@@ -18654,7 +18905,7 @@ class SessionStore {
18654
18905
  if (!existsSync35(path))
18655
18906
  return null;
18656
18907
  try {
18657
- const raw = readFileSync19(path, "utf-8");
18908
+ const raw = readFileSync20(path, "utf-8");
18658
18909
  const content = this.encryptor ? this.encryptor.decryptFileContent(raw) : raw;
18659
18910
  const meta = JSON.parse(content);
18660
18911
  this._metaCache.set(id, meta);
@@ -18686,7 +18937,7 @@ class SessionStore {
18686
18937
  if (!existsSync35(path))
18687
18938
  return [];
18688
18939
  try {
18689
- const raw = readFileSync19(path, "utf-8");
18940
+ const raw = readFileSync20(path, "utf-8");
18690
18941
  const lines = raw.split(`
18691
18942
  `).filter(Boolean);
18692
18943
  const parseLine = (line) => {
@@ -18727,7 +18978,7 @@ class SessionStore {
18727
18978
  if (!existsSync35(path))
18728
18979
  return [];
18729
18980
  try {
18730
- const raw = readFileSync19(path, "utf-8");
18981
+ const raw = readFileSync20(path, "utf-8");
18731
18982
  const lines = raw.split(`
18732
18983
  `).filter(Boolean);
18733
18984
  const parseLine = (line) => {
@@ -18782,7 +19033,7 @@ class SessionStore {
18782
19033
  if (updatedAt < thirtyDaysAgo) {
18783
19034
  const historyPath = this.historyPath(session2.id);
18784
19035
  if (existsSync35(historyPath)) {
18785
- const content = readFileSync19(historyPath, "utf-8");
19036
+ const content = readFileSync20(historyPath, "utf-8");
18786
19037
  const compressed = gzipSync(content);
18787
19038
  const gzPath = join28(this.baseDir, `${session2.id}.jsonl.gz`);
18788
19039
  writeFileSync12(gzPath, compressed);
@@ -18994,7 +19245,7 @@ class ProfileCompressor {
18994
19245
  }
18995
19246
 
18996
19247
  // src/modules/user-profile/profile.ts
18997
- import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync36, mkdirSync as mkdirSync16 } from "fs";
19248
+ import { readFileSync as readFileSync21, writeFileSync as writeFileSync13, existsSync as existsSync36, mkdirSync as mkdirSync16 } from "fs";
18998
19249
  import { join as join29 } from "path";
18999
19250
  import { homedir as homedir9, hostname, platform as platform7, type } from "os";
19000
19251
  import { env } from "process";
@@ -19029,7 +19280,7 @@ class UserProfile {
19029
19280
  if (!existsSync36(path))
19030
19281
  return null;
19031
19282
  try {
19032
- const data = JSON.parse(readFileSync20(path, "utf-8"));
19283
+ const data = JSON.parse(readFileSync21(path, "utf-8"));
19033
19284
  this.info = {
19034
19285
  platform: data.platform,
19035
19286
  os: data.os,
@@ -19064,7 +19315,7 @@ class UserProfile {
19064
19315
  var init_profile = () => {};
19065
19316
 
19066
19317
  // src/modules/skills/loader.ts
19067
- import { readdirSync as readdirSync13, readFileSync as readFileSync21, existsSync as existsSync37, statSync as statSync6 } from "fs";
19318
+ import { readdirSync as readdirSync13, readFileSync as readFileSync22, existsSync as existsSync37, statSync as statSync6 } from "fs";
19068
19319
  import { join as join30 } from "path";
19069
19320
 
19070
19321
  class SkillsLoader {
@@ -19086,7 +19337,7 @@ class SkillsLoader {
19086
19337
  }
19087
19338
  if (!entry.endsWith(".md") && !entry.endsWith(".skill.md"))
19088
19339
  continue;
19089
- const content = readFileSync21(fullPath, "utf-8");
19340
+ const content = readFileSync22(fullPath, "utf-8");
19090
19341
  const parsed = this.parseSkillFile(content, fullPath);
19091
19342
  if (parsed)
19092
19343
  skills.push(parsed);
@@ -19988,7 +20239,7 @@ var init_startup_check = __esm(() => {
19988
20239
  });
19989
20240
 
19990
20241
  // src/modules/indexer/walker.ts
19991
- import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync40, watch } from "fs";
20242
+ import { readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync7, existsSync as existsSync40, watch } from "fs";
19992
20243
  import { join as join32, relative as relative4, extname as extname5 } from "path";
19993
20244
 
19994
20245
  class Indexer {
@@ -20038,7 +20289,7 @@ class Indexer {
20038
20289
  const ext = extname5(entry).toLowerCase();
20039
20290
  const language = LANGUAGES[ext];
20040
20291
  if (language) {
20041
- const content = readFileSync22(fullPath, "utf-8");
20292
+ const content = readFileSync23(fullPath, "utf-8");
20042
20293
  const exports = this.extractExports(content, language);
20043
20294
  files.push({ path: relPath, language, exports, size: stat2.size });
20044
20295
  totalSize += stat2.size;
@@ -20090,7 +20341,7 @@ var init_walker = __esm(() => {
20090
20341
  });
20091
20342
 
20092
20343
  // src/modules/indexer/cache.ts
20093
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as existsSync41, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
20344
+ import { readFileSync as readFileSync24, writeFileSync as writeFileSync14, existsSync as existsSync41, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
20094
20345
  import { join as join33 } from "path";
20095
20346
 
20096
20347
  class IndexCache {
@@ -20105,7 +20356,7 @@ class IndexCache {
20105
20356
  if (!existsSync41(this.cachePath))
20106
20357
  return null;
20107
20358
  try {
20108
- this.cache = JSON.parse(readFileSync23(this.cachePath, "utf-8"));
20359
+ this.cache = JSON.parse(readFileSync24(this.cachePath, "utf-8"));
20109
20360
  return this.cache;
20110
20361
  } catch {
20111
20362
  return null;
@@ -20130,7 +20381,7 @@ class IndexCache {
20130
20381
  var init_cache = () => {};
20131
20382
 
20132
20383
  // src/modules/indexer/project-profile.ts
20133
- import { readFileSync as readFileSync24, existsSync as existsSync42 } from "fs";
20384
+ import { readFileSync as readFileSync25, existsSync as existsSync42 } from "fs";
20134
20385
  import { join as join34 } from "path";
20135
20386
  function detectManifest(baseDir) {
20136
20387
  for (const manifest of MANIFEST_ORDER) {
@@ -20151,7 +20402,7 @@ function cleanDependency(entry) {
20151
20402
  }
20152
20403
  function readPackageJson(baseDir) {
20153
20404
  try {
20154
- const raw = JSON.parse(readFileSync24(join34(baseDir, "package.json"), "utf-8"));
20405
+ const raw = JSON.parse(readFileSync25(join34(baseDir, "package.json"), "utf-8"));
20155
20406
  if (!raw || typeof raw !== "object")
20156
20407
  return null;
20157
20408
  const profile = {
@@ -20175,7 +20426,7 @@ function readPackageJson(baseDir) {
20175
20426
  }
20176
20427
  function readPyproject(baseDir) {
20177
20428
  try {
20178
- const content = readFileSync24(join34(baseDir, "pyproject.toml"), "utf-8");
20429
+ const content = readFileSync25(join34(baseDir, "pyproject.toml"), "utf-8");
20179
20430
  const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
20180
20431
  const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
20181
20432
  if (nameMatch)
@@ -20191,7 +20442,7 @@ function readPyproject(baseDir) {
20191
20442
  }
20192
20443
  function readCargo(baseDir) {
20193
20444
  try {
20194
- const content = readFileSync24(join34(baseDir, "Cargo.toml"), "utf-8");
20445
+ const content = readFileSync25(join34(baseDir, "Cargo.toml"), "utf-8");
20195
20446
  const profile = { runtime: "rust", deps: [], devDeps: [], scripts: {} };
20196
20447
  const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
20197
20448
  if (nameMatch)
@@ -20215,7 +20466,7 @@ function readCargo(baseDir) {
20215
20466
  }
20216
20467
  function readGoMod(baseDir) {
20217
20468
  try {
20218
- const content = readFileSync24(join34(baseDir, "go.mod"), "utf-8");
20469
+ const content = readFileSync25(join34(baseDir, "go.mod"), "utf-8");
20219
20470
  const profile = { runtime: "go", deps: [], devDeps: [], scripts: {} };
20220
20471
  const moduleMatch = content.match(/^module\s+(\S+)/m);
20221
20472
  if (moduleMatch)
@@ -20233,7 +20484,7 @@ function readGoMod(baseDir) {
20233
20484
  }
20234
20485
  function readRequirements(baseDir) {
20235
20486
  try {
20236
- const content = readFileSync24(join34(baseDir, "requirements.txt"), "utf-8");
20487
+ const content = readFileSync25(join34(baseDir, "requirements.txt"), "utf-8");
20237
20488
  const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
20238
20489
  for (const line of content.split(`
20239
20490
  `)) {
@@ -20786,7 +21037,7 @@ var init_module8 = __esm(() => {
20786
21037
  });
20787
21038
 
20788
21039
  // src/core/version.ts
20789
- import { existsSync as existsSync43, readFileSync as readFileSync25 } from "fs";
21040
+ import { existsSync as existsSync43, readFileSync as readFileSync26 } from "fs";
20790
21041
  import { join as join36, dirname as dirname13 } from "path";
20791
21042
  import { fileURLToPath as fileURLToPath2 } from "url";
20792
21043
  function readMmaVersion() {
@@ -20795,7 +21046,7 @@ function readMmaVersion() {
20795
21046
  for (const p of candidates) {
20796
21047
  if (existsSync43(p)) {
20797
21048
  try {
20798
- const raw = JSON.parse(readFileSync25(p, "utf8"));
21049
+ const raw = JSON.parse(readFileSync26(p, "utf8"));
20799
21050
  if (raw.version)
20800
21051
  return raw.version;
20801
21052
  } catch {}
@@ -20813,7 +21064,7 @@ __export(exports_bootstrap, {
20813
21064
  });
20814
21065
  import { homedir as homedir11 } from "os";
20815
21066
  import { join as join37, resolve as resolve23 } from "path";
20816
- import { existsSync as existsSync44, readFileSync as readFileSync26, writeFileSync as writeFileSync15 } from "fs";
21067
+ import { existsSync as existsSync44, readFileSync as readFileSync27, writeFileSync as writeFileSync15 } from "fs";
20817
21068
  function buildSystemInfo(config, baseDir, profileCompressed) {
20818
21069
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
20819
21070
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -21073,7 +21324,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21073
21324
  ];
21074
21325
  for (const p of agentsMdCandidates) {
21075
21326
  if (existsSync44(p)) {
21076
- const content = readFileSync26(p, "utf-8").trim();
21327
+ const content = readFileSync27(p, "utf-8").trim();
21077
21328
  if (content) {
21078
21329
  agentsMdBlocks.push({
21079
21330
  content,
@@ -21937,13 +22188,13 @@ __export(exports_manifest, {
21937
22188
  getCertMark: () => getCertMark,
21938
22189
  MANIFEST_PATH: () => MANIFEST_PATH
21939
22190
  });
21940
- import { existsSync as existsSync45, readFileSync as readFileSync27, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
22191
+ import { existsSync as existsSync45, readFileSync as readFileSync28, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
21941
22192
  import { homedir as homedir13 } from "os";
21942
22193
  import { join as join39 } from "path";
21943
22194
  function readManifest(path = MANIFEST_PATH) {
21944
22195
  try {
21945
22196
  if (existsSync45(path)) {
21946
- const raw = JSON.parse(readFileSync27(path, "utf-8"));
22197
+ const raw = JSON.parse(readFileSync28(path, "utf-8"));
21947
22198
  return { version: 1, certifications: raw.certifications ?? [] };
21948
22199
  }
21949
22200
  } catch {}
@@ -29108,7 +29359,7 @@ var init_scenarios = __esm(() => {
29108
29359
  });
29109
29360
 
29110
29361
  // src/modules/certification/loader.ts
29111
- import { existsSync as existsSync46, readdirSync as readdirSync15, readFileSync as readFileSync28 } from "fs";
29362
+ import { existsSync as existsSync46, readdirSync as readdirSync15, readFileSync as readFileSync29 } from "fs";
29112
29363
  import { join as join40 } from "path";
29113
29364
  function validateScenario(s) {
29114
29365
  const errors2 = [];
@@ -29163,7 +29414,7 @@ function loadScenarios(userDir) {
29163
29414
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
29164
29415
  continue;
29165
29416
  try {
29166
- const raw = readFileSync28(join40(userDir, file), "utf-8");
29417
+ const raw = readFileSync29(join40(userDir, file), "utf-8");
29167
29418
  const data = $parse(raw);
29168
29419
  const parsed = normalizeScenario(data, file);
29169
29420
  const errs = validateScenario(parsed);
@@ -29216,7 +29467,7 @@ var init_loader3 = __esm(() => {
29216
29467
  });
29217
29468
 
29218
29469
  // src/modules/certification/fact-checker.ts
29219
- import { existsSync as existsSync47, readFileSync as readFileSync29, statSync as statSync8 } from "fs";
29470
+ import { existsSync as existsSync47, readFileSync as readFileSync30, statSync as statSync8 } from "fs";
29220
29471
  import { join as join41 } from "path";
29221
29472
  function checkSandbox(sandboxDir, checks, exitCode, output) {
29222
29473
  const failures = [];
@@ -29243,7 +29494,7 @@ function runCheck2(sandboxDir, check, exitCode, output) {
29243
29494
  const abs = join41(sandboxDir, check.path);
29244
29495
  if (!isFile(abs))
29245
29496
  return false;
29246
- const content = readFileSync29(abs, "utf-8");
29497
+ const content = readFileSync30(abs, "utf-8");
29247
29498
  if (check.contains !== undefined)
29248
29499
  return content.includes(check.contains);
29249
29500
  if (check.equals !== undefined)
@@ -29254,7 +29505,7 @@ function runCheck2(sandboxDir, check, exitCode, output) {
29254
29505
  const abs = join41(sandboxDir, check.path);
29255
29506
  if (!isFile(abs))
29256
29507
  return false;
29257
- return new RegExp(check.pattern).test(readFileSync29(abs, "utf-8"));
29508
+ return new RegExp(check.pattern).test(readFileSync30(abs, "utf-8"));
29258
29509
  }
29259
29510
  default:
29260
29511
  return false;
@@ -29470,13 +29721,13 @@ import { rmSync as rmSync5 } from "fs";
29470
29721
  import { homedir as homedir14 } from "os";
29471
29722
  import { join as join43, dirname as dirname15 } from "path";
29472
29723
  import { fileURLToPath as fileURLToPath3 } from "url";
29473
- import { existsSync as existsSync49, readFileSync as readFileSync30 } from "fs";
29724
+ import { existsSync as existsSync49, readFileSync as readFileSync31 } from "fs";
29474
29725
  function readVersion() {
29475
29726
  const candidates = [join43(MMA_ROOT, "package.json")];
29476
29727
  for (const p of candidates) {
29477
29728
  if (existsSync49(p)) {
29478
29729
  try {
29479
- const raw = JSON.parse(readFileSync30(p, "utf-8"));
29730
+ const raw = JSON.parse(readFileSync31(p, "utf-8"));
29480
29731
  if (raw.version)
29481
29732
  return raw.version;
29482
29733
  } catch {}
@@ -29637,7 +29888,7 @@ __export(exports_repl_commands, {
29637
29888
  });
29638
29889
  import { join as join45, dirname as dirname17 } from "path";
29639
29890
  import { homedir as homedir16 } from "os";
29640
- import { existsSync as existsSync51, readFileSync as readFileSync32 } from "fs";
29891
+ import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
29641
29892
  import { fileURLToPath as fileURLToPath5 } from "url";
29642
29893
  function readVersion3() {
29643
29894
  const here = dirname17(fileURLToPath5(import.meta.url));
@@ -29645,7 +29896,7 @@ function readVersion3() {
29645
29896
  for (const p of candidates) {
29646
29897
  if (existsSync51(p)) {
29647
29898
  try {
29648
- const raw = JSON.parse(readFileSync32(p, "utf8"));
29899
+ const raw = JSON.parse(readFileSync33(p, "utf8"));
29649
29900
  if (raw.version)
29650
29901
  return raw.version;
29651
29902
  } catch {}
@@ -30303,7 +30554,7 @@ init_setup();
30303
30554
  init_i18n();
30304
30555
  import { join as join44, dirname as dirname16 } from "path";
30305
30556
  import { homedir as homedir15 } from "os";
30306
- import { existsSync as existsSync50, readFileSync as readFileSync31 } from "fs";
30557
+ import { existsSync as existsSync50, readFileSync as readFileSync32 } from "fs";
30307
30558
 
30308
30559
  // src/cli/security-commands.ts
30309
30560
  init_bootstrap();
@@ -30945,7 +31196,7 @@ function readVersion2() {
30945
31196
  for (const p of candidates) {
30946
31197
  if (existsSync50(p)) {
30947
31198
  try {
30948
- const raw = JSON.parse(readFileSync31(p, "utf8"));
31199
+ const raw = JSON.parse(readFileSync32(p, "utf8"));
30949
31200
  if (raw.version)
30950
31201
  return raw.version;
30951
31202
  } catch {}
@@ -31928,7 +32179,7 @@ class LineEditor {
31928
32179
  }
31929
32180
 
31930
32181
  // src/cli/repl.ts
31931
- import { existsSync as existsSync53, readFileSync as readFileSync34, writeFileSync as writeFileSync17 } from "fs";
32182
+ import { existsSync as existsSync53, readFileSync as readFileSync35, writeFileSync as writeFileSync17 } from "fs";
31932
32183
  import { join as join47, dirname as dirname18 } from "path";
31933
32184
  import { homedir as homedir17 } from "os";
31934
32185
  import { fileURLToPath as fileURLToPath6 } from "url";
@@ -32517,14 +32768,14 @@ init_config();
32517
32768
  init_colors();
32518
32769
  init_js_identifiers();
32519
32770
  init_i18n();
32520
- import { existsSync as existsSync52, readFileSync as readFileSync33 } from "fs";
32771
+ import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
32521
32772
  import { join as join46 } from "path";
32522
32773
  function readActivePlan(baseDir) {
32523
32774
  const p = join46(baseDir, ".mma", "plans", "active.json");
32524
32775
  if (!existsSync52(p))
32525
32776
  return null;
32526
32777
  try {
32527
- const raw = readFileSync33(p, "utf-8");
32778
+ const raw = readFileSync34(p, "utf-8");
32528
32779
  if (!raw.trim())
32529
32780
  return null;
32530
32781
  const parsed = JSON.parse(raw);
@@ -32623,7 +32874,7 @@ function readVersion4() {
32623
32874
  for (const p of candidates) {
32624
32875
  if (existsSync53(p)) {
32625
32876
  try {
32626
- const raw = JSON.parse(readFileSync34(p, "utf8"));
32877
+ const raw = JSON.parse(readFileSync35(p, "utf8"));
32627
32878
  if (raw.version)
32628
32879
  return raw.version;
32629
32880
  } catch {}
@@ -32719,7 +32970,7 @@ class Repl {
32719
32970
  loadHistory() {
32720
32971
  if (existsSync53(this.historyPath)) {
32721
32972
  try {
32722
- const raw = readFileSync34(this.historyPath, "utf-8");
32973
+ const raw = readFileSync35(this.historyPath, "utf-8");
32723
32974
  this.history = raw.split(`
32724
32975
  `).filter(Boolean).slice(-this.maxHistory);
32725
32976
  } catch {
@@ -33192,7 +33443,7 @@ init_setup();
33192
33443
  init_config2();
33193
33444
  init_i18n();
33194
33445
  init_colors();
33195
- import { existsSync as existsSync54, readFileSync as readFileSync35 } from "fs";
33446
+ import { existsSync as existsSync54, readFileSync as readFileSync36 } from "fs";
33196
33447
  import { join as join48, dirname as dirname19 } from "path";
33197
33448
  import { homedir as homedir18 } from "os";
33198
33449
  import { fileURLToPath as fileURLToPath7 } from "url";
@@ -33301,7 +33552,7 @@ function readVersion5() {
33301
33552
  for (const p of candidates) {
33302
33553
  if (existsSync54(p)) {
33303
33554
  try {
33304
- const raw = JSON.parse(readFileSync35(p, "utf8"));
33555
+ const raw = JSON.parse(readFileSync36(p, "utf8"));
33305
33556
  if (raw.version)
33306
33557
  return raw.version;
33307
33558
  } catch {}