micro-models-agent 0.43.2 → 0.43.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.js +56 -43
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2580,6 +2580,7 @@ Fix the error and re-edit the file (a clean write clears the failure), or mark t
2580
2580
  "verify.script_passed": "Script '{script}' passed",
2581
2581
  "verify.script_failed": "Script '{script}' failed: {message}",
2582
2582
  "verify.syntax_error": "Syntax error in: {path}",
2583
+ "verify.file_still_exists": "File should be deleted but still exists: {path}",
2583
2584
  "verify.no_files": "Step {step} has no named files to verify — run a real check instead (bash: bun run build / bun test / lsp_check) and confirm the result.",
2584
2585
  "lsp.unavailable": "static checks are unavailable (server not found). Verify via the project's own build/test instead.",
2585
2586
  "lsp.check_disabled": "LSP checks are disabled in the config.",
@@ -3237,6 +3238,7 @@ var init_ru = __esm(() => {
3237
3238
  "verify.script_passed": "Скрипт '{script}' пройден",
3238
3239
  "verify.script_failed": "Скрипт '{script}' не пройден: {message}",
3239
3240
  "verify.syntax_error": "Синтаксическая ошибка в: {path}",
3241
+ "verify.file_still_exists": "Файл должен быть удалён, но всё ещё существует: {path}",
3240
3242
  "verify.no_files": "Шаг {step} не содержит именованных файлов для проверки — выполни реальную проверку (bun run build / bun test / lsp_check) и подтверди результат.",
3241
3243
  "lsp.unavailable": "статические проверки недоступны (сервер не найден). Проверяйте через собственный build/test проекта.",
3242
3244
  "lsp.check_disabled": "LSP-проверки отключены в конфигурации.",
@@ -9670,6 +9672,9 @@ class StuckDetector {
9670
9672
  this.consecutiveFailures = 0;
9671
9673
  this.lastFailedTool = "";
9672
9674
  this.escalationCount = 0;
9675
+ if (this.iterationsOnCurrentStep > 0) {
9676
+ this.iterationsOnCurrentStep = Math.max(0, this.iterationsOnCurrentStep - 1);
9677
+ }
9673
9678
  }
9674
9679
  setCurrentStep(stepId, description) {
9675
9680
  if (stepId !== this.currentStepId) {
@@ -11061,7 +11066,7 @@ class StepVerifier {
11061
11066
  details
11062
11067
  };
11063
11068
  }
11064
- async verifyStep(stepDescription) {
11069
+ async verifyStep(stepDescription, kind) {
11065
11070
  const fileMatches = extractFileLikeTokens(stripUrls(stepDescription));
11066
11071
  if (fileMatches.length === 0) {
11067
11072
  return { passed: false, syntaxValid: true, failed: [], noFiles: true };
@@ -11070,7 +11075,15 @@ class StepVerifier {
11070
11075
  let syntaxValid = true;
11071
11076
  for (const filePath of fileMatches) {
11072
11077
  const resolved = findExistingFile(this.baseDir, filePath);
11073
- if (!resolved) {
11078
+ const exists = !!resolved;
11079
+ if (kind === "delete") {
11080
+ results.push({
11081
+ passed: !exists,
11082
+ message: exists ? t("verify.file_still_exists", { path: filePath }) : t("verify.file_not_found", { path: filePath })
11083
+ });
11084
+ continue;
11085
+ }
11086
+ if (!exists) {
11074
11087
  results.push({ passed: false, message: t("verify.file_not_found", { path: filePath }) });
11075
11088
  continue;
11076
11089
  }
@@ -17545,30 +17558,29 @@ function createExecutionPlugin(deps) {
17545
17558
  if (currentIter - deps.state.lastRecoveryIteration >= STUCK_RECOVERY_COOLDOWN) {
17546
17559
  const recovery = deps.stuckDetector.getRecoveryMessage();
17547
17560
  if (recovery && ctx.contextManager) {
17548
- const lastError = deps.stuckDetector.getLastErrorOutput();
17549
- const skillHint = lastError ? `
17550
- If you have relevant skills available, consider loading one with load_skill for expert guidance.` : "";
17551
- const actionableHints = deps.stuckDetector.getActionableHints();
17552
- const actionableHintStr = actionableHints.length > 0 ? `
17553
- ${t("exec.hints", { hints: actionableHints.map((h) => `- ${h}`).join(`
17554
- `) })}` : "";
17555
- const alternative = deps.stuckDetector.getToolAlternative();
17556
- const altHint = alternative ? `
17557
- Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}" instead.` : "";
17558
- ctx.contextManager.addMessage({
17559
- role: "user",
17560
- content: `<system-summary>${recovery}${skillHint}${actionableHintStr}${altHint}</system-summary>`
17561
- });
17562
- }
17563
- const hints = deps.stuckDetector.getHints();
17564
- if (hints.length > 0 && ctx.contextManager) {
17565
- const hintMsg = t("exec.hints", {
17566
- hints: hints.map((h) => `- ${h}`).join(`
17567
- `)
17568
- });
17561
+ let tscContext = "";
17562
+ if (deps.state.typecheckFailures.size > 0) {
17563
+ const currentStep = deps.trackerRef.current?.getCurrentStep();
17564
+ if (currentStep) {
17565
+ const stepFiles = extractFileLikeTokens(stripUrls(currentStep.description));
17566
+ for (const [file, error] of deps.state.typecheckFailures) {
17567
+ if (!file || stepFiles.some((f) => file.endsWith(f) || f.endsWith(file))) {
17568
+ tscContext = `
17569
+ Last compile error: ${error}`;
17570
+ break;
17571
+ }
17572
+ }
17573
+ if (!tscContext) {
17574
+ const first = deps.state.typecheckFailures.entries().next().value;
17575
+ if (first)
17576
+ tscContext = `
17577
+ Last compile error: ${first[1]}`;
17578
+ }
17579
+ }
17580
+ }
17569
17581
  ctx.contextManager.addMessage({
17570
17582
  role: "user",
17571
- content: `<system-summary>${hintMsg}</system-summary>`
17583
+ content: `<system-summary>${recovery}${tscContext}</system-summary>`
17572
17584
  });
17573
17585
  }
17574
17586
  deps.stuckDetector.recordEscalation();
@@ -17627,6 +17639,24 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
17627
17639
  if (call.name === "bash") {
17628
17640
  deps.stuckDetector.recordBashOutput(String(call.arguments?.command ?? ""), String(result.output ?? ""));
17629
17641
  }
17642
+ if (call.name === "delete_file" && result.success && deps.trackerRef.current) {
17643
+ const deletedPath = String(call.arguments?.path ?? "");
17644
+ if (deletedPath) {
17645
+ const plan = deps.trackerRef.current.getPlan();
17646
+ const tokens = extractFileLikeTokens(stripUrls(deletedPath));
17647
+ for (const step of plan.steps) {
17648
+ if (step.status !== "pending" && step.status !== "in_progress")
17649
+ continue;
17650
+ const stepTokens = extractFileLikeTokens(stripUrls(step.description));
17651
+ const overlap = tokens.some((t2) => stepTokens.some((st) => t2.endsWith(st) || st.endsWith(t2)));
17652
+ if (overlap && step.kind !== "delete") {
17653
+ step.kind = "delete";
17654
+ deps.store.saveActive(plan);
17655
+ break;
17656
+ }
17657
+ }
17658
+ }
17659
+ }
17630
17660
  const toolText = String(result.output ?? "");
17631
17661
  const hasTypeError = /error TS\d+|\[Project typecheck failed\]|\[Syntax check failed\]/.test(toolText);
17632
17662
  if (hasTypeError) {
@@ -17659,19 +17689,6 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
17659
17689
  if (!hasTypeError) {
17660
17690
  deps.stuckDetector.recordToolError(call.name, result.output);
17661
17691
  }
17662
- const actionableHints = deps.stuckDetector.getActionableHints();
17663
- const alternative = deps.stuckDetector.getToolAlternative();
17664
- if (actionableHints.length > 0 || alternative) {
17665
- const parts = [...actionableHints];
17666
- if (alternative) {
17667
- parts.push(`Tool "${call.name}" crashed. Try "${alternative}" instead.`);
17668
- }
17669
- deps.pendingMessages.push({
17670
- role: "user",
17671
- content: `<system-summary>${t("exec.hints", { hints: parts.map((h) => `- ${h}`).join(`
17672
- `) })}</system-summary>`
17673
- });
17674
- }
17675
17692
  } else {
17676
17693
  deps.stuckDetector.recordToolSuccess();
17677
17694
  if (call.name === "bash" && result.success) {
@@ -17687,11 +17704,6 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
17687
17704
  role: "user",
17688
17705
  content: `<system-summary>${testRun.framework}: all ${testRun.passed} test(s) passed for "${cmd}". You may mark the current step as done via plan update step=N status=done.</system-summary>`
17689
17706
  });
17690
- } else if (/node|tsx|ts-node|python|npm\s+(start|test|run)/.test(cmd)) {
17691
- deps.pendingMessages.push({
17692
- role: "user",
17693
- content: `<system-summary>The command "${cmd}" completed successfully. If this was testing your code, mark the current step as done via plan update step=N status=done.</system-summary>`
17694
- });
17695
17707
  }
17696
17708
  }
17697
17709
  }
@@ -18285,7 +18297,7 @@ ${lines.join(`
18285
18297
  const step = args.step ? tracker.getStep(Number(args.step)) : tracker.getCurrentStep();
18286
18298
  if (!step)
18287
18299
  return { success: false, output: t("plan.step_not_found") };
18288
- const result = await deps.verifier.verifyStep(step.description);
18300
+ const result = await deps.verifier.verifyStep(step.description, step.kind);
18289
18301
  if (result.noFiles) {
18290
18302
  return {
18291
18303
  success: true,
@@ -18532,6 +18544,7 @@ class ExecutionModule {
18532
18544
  pendingMessages: this.pendingMessages,
18533
18545
  forbiddenBashFailures: this.forbiddenBashFailures,
18534
18546
  state: this.state,
18547
+ store: this.store,
18535
18548
  checkPlanAlignment: (call) => this.checkPlanAlignment(call),
18536
18549
  advancePlanIfStepComplete: (cm, sl) => this.advancePlanIfStepComplete(cm, sl),
18537
18550
  maybeSearchError: (ctx, call) => this.maybeSearchError(ctx, call)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micro-models-agent",
3
- "version": "0.43.2",
3
+ "version": "0.43.3",
4
4
  "description": "Micro Models Agent (MMA) — LLM agent harness for small models (Qwen3.5-9B, 32K-64K context)",
5
5
  "type": "module",
6
6
  "bin": {