micro-models-agent 0.29.1 → 0.30.0

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 +272 -22
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2263,7 +2263,13 @@ var init_defaults = __esm(() => {
2263
2263
  stableSystemPrompt: true,
2264
2264
  maxParallelChunkQueries: 4
2265
2265
  },
2266
- lsp: DEFAULT_LSP_CONFIG
2266
+ lsp: DEFAULT_LSP_CONFIG,
2267
+ updater: {
2268
+ enabled: true,
2269
+ checkOnStart: true,
2270
+ autoInstall: true,
2271
+ intervalMs: 0
2272
+ }
2267
2273
  };
2268
2274
  });
2269
2275
 
@@ -2304,6 +2310,7 @@ var init_en = __esm(() => {
2304
2310
  "error.response_blocked": "Response blocked: {reason}",
2305
2311
  "error.max_iters": "Max iterations ({max}) reached",
2306
2312
  "error.empty_response": "Model returned an empty response after retries",
2313
+ "error.audit_failed": "Task could not be verified as complete: {summary}",
2307
2314
  "error.grep_failed": "Grep failed: {message}",
2308
2315
  "error.search_failed": "Search failed: {message}",
2309
2316
  "error.fetch_failed": "Fetch failed: {message}",
@@ -2448,6 +2455,8 @@ Command: {command}`,
2448
2455
  "plan.step_status": "Step {step}: {status}",
2449
2456
  "plan.no_active": "No active plan",
2450
2457
  "plan.step_not_found": "Step not found",
2458
+ "plan.step_already_done": "Step {step} is already marked done. Stop re-marking it — either continue with the next step or investigate why progress appears stuck.",
2459
+ "plan.order_blocked": 'Cannot mark step {step} done: step {first} ("{desc}") is not finished yet. Complete earlier steps first, or mark step {first} status=skipped if it is not needed.',
2451
2460
  "plan.show_header": "Plan status:",
2452
2461
  "plan.show_empty": "(plan has no steps)",
2453
2462
  "plan.list_header": "Plans:",
@@ -2829,8 +2838,13 @@ Use this knowledge to answer the user's question.`,
2829
2838
  "ctx.compactions": "compactions: {count}",
2830
2839
  "ctx.quality": "quality: {percent}%",
2831
2840
  "ctx.delta_pos": "ctx +{tokens}",
2832
- "ctx.delta_neg": "ctx -{tokens}",
2833
- "ctx.delta_zero": "ctx ±0"
2841
+ "ctx.delta_neg": "ctx -{tokens} ",
2842
+ "ctx.delta_zero": "ctx +0",
2843
+ "updater.check_error": "[updater] update check failed: {error}",
2844
+ "updater.available": "[updater] Update available: {current} → {latest}. Run `npm install -g micro-models-agent` to upgrade.",
2845
+ "updater.installing": "[updater] Installing {latest} globally (current: {current})…",
2846
+ "updater.installed": "[updater] Installed {latest}. Restart MMA to use it (was {current}).",
2847
+ "updater.install_failed": "[updater] Failed to install {latest}: {error}. Update manually with `npm install -g micro-models-agent`."
2834
2848
  };
2835
2849
  });
2836
2850
 
@@ -2870,6 +2884,7 @@ var init_ru = __esm(() => {
2870
2884
  "error.response_blocked": "Ответ заблокирован: {reason}",
2871
2885
  "error.max_iters": "Достигнут максимум итераций ({max})",
2872
2886
  "error.empty_response": "Модель вернула пустой ответ после повторных попыток",
2887
+ "error.audit_failed": "Задача не может быть подтверждена как выполненная: {summary}",
2873
2888
  "error.grep_failed": "Ошибка grep: {message}",
2874
2889
  "error.search_failed": "Ошибка поиска: {message}",
2875
2890
  "error.fetch_failed": "Ошибка загрузки: {message}",
@@ -3013,6 +3028,8 @@ var init_ru = __esm(() => {
3013
3028
  "plan.step_status": "Шаг {step}: {status}",
3014
3029
  "plan.no_active": "Нет активного плана",
3015
3030
  "plan.step_not_found": "Шаг не найден",
3031
+ "plan.step_already_done": "Шаг {step} уже отмечен выполненным. Прекратите повторную отметку — переходите к следующему шагу или выясните, почему прогресс заблокирован.",
3032
+ "plan.order_blocked": "Нельзя отметить шаг {step} выполненным: шаг {first} («{desc}») ещё не завершён. Сначала завершите предыдущие шаги или отметьте шаг {first} status=skipped, если он не нужен.",
3016
3033
  "plan.show_header": "Статус плана:",
3017
3034
  "plan.show_empty": "(в плане нет шагов)",
3018
3035
  "plan.list_header": "Планы:",
@@ -3397,7 +3414,12 @@ var init_ru = __esm(() => {
3397
3414
  "ctx.delta_neg": "контекст -{tokens} ↓",
3398
3415
  "ctx.delta_zero": "контекст ±0",
3399
3416
  "file.notfound_resolved": "Файл не найден: {path} (резолвится в {resolved})",
3400
- "bash.echo_write_blocked": "Запись файлов через echo/printf ненадёжна в Windows cmd.exe (кавычки и многострочность ломаются). Используй инструмент write_file вместо этого (цель: {path})."
3417
+ "bash.echo_write_blocked": "Запись файлов через echo/printf ненадёжна в Windows cmd.exe (кавычки и многострочность ломаются). Используй инструмент write_file вместо этого (цель: {path}).",
3418
+ "updater.check_error": "[updater] Ошибка проверки обновления: {error}",
3419
+ "updater.available": "[updater] Доступно обновление: {current} → {latest}. Выполните `npm install -g micro-models-agent` для обновления.",
3420
+ "updater.installing": "[updater] Установка {latest} глобально (текущая: {current})…",
3421
+ "updater.installed": "[updater] Установлена {latest}. Перезапустите MMA для применения (была {current}).",
3422
+ "updater.install_failed": "[updater] Не удалось установить {latest}: {error}. Обновите вручную: `npm install -g micro-models-agent`."
3401
3423
  };
3402
3424
  });
3403
3425
 
@@ -7469,7 +7491,7 @@ function emptyCliRunHint(command, output, code) {
7469
7491
  return null;
7470
7492
  return "the command exited 0 but printed NOTHING to stdout. If this should run a CLI program, the file probably has no entry point: read it with read_file and check the code actually calls its main function with command-line arguments (e.g. main(process.argv[2])) and prints results with console.log.";
7471
7493
  }
7472
- var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, bashGraceMs, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, bashTool;
7494
+ var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, bashGraceMs, FAILING_FIRST_WORDS, HARD_BLOCK_THRESHOLD = 3, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, bashTool;
7473
7495
  var init_bash = __esm(() => {
7474
7496
  init_command_validator();
7475
7497
  init_audit_log();
@@ -7478,6 +7500,7 @@ var init_bash = __esm(() => {
7478
7500
  init_processes();
7479
7501
  init_i18n();
7480
7502
  bashGraceMs = BASH_GRACE_MS;
7503
+ FAILING_FIRST_WORDS = new Map;
7481
7504
  UNIX_TO_WIN_HINTS = {
7482
7505
  ls: "Use the list_dir tool instead.",
7483
7506
  pwd: "Use the file_info tool instead.",
@@ -7629,13 +7652,22 @@ ${output2}`;
7629
7652
  if (!output2 && code !== 0) {
7630
7653
  output2 = `(exit code ${code})`;
7631
7654
  }
7632
- if (platform2() === "win32" && code !== 0) {
7655
+ if (platform2() === "win32") {
7633
7656
  const firstWord = command.trim().split(/\s+/)[0]?.split(/[\\/]/).pop();
7634
- const hint = firstWord ? UNIX_TO_WIN_HINTS[firstWord] : undefined;
7635
- if (hint) {
7636
- output2 = `${output2}
7657
+ if (firstWord && firstWord in UNIX_TO_WIN_HINTS) {
7658
+ if (code === 0) {
7659
+ FAILING_FIRST_WORDS.delete(firstWord);
7660
+ } else {
7661
+ const failures = (FAILING_FIRST_WORDS.get(firstWord) || 0) + 1;
7662
+ FAILING_FIRST_WORDS.set(firstWord, failures);
7663
+ if (failures >= HARD_BLOCK_THRESHOLD) {
7664
+ 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]}`;
7665
+ } else {
7666
+ output2 = `${output2}
7637
7667
 
7638
- Hint: "${firstWord}" may not work on Windows. ${hint}`;
7668
+ Hint: "${firstWord}" may not work on Windows. ${UNIX_TO_WIN_HINTS[firstWord]}`;
7669
+ }
7670
+ }
7639
7671
  }
7640
7672
  }
7641
7673
  if (securityConfig?.logCommands) {
@@ -10392,6 +10424,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
10392
10424
  this.abortController = new AbortController;
10393
10425
  let iteration = 0;
10394
10426
  let lastText = "";
10427
+ let lastForcedCompactionIteration = -FORCED_COMPACTION_COOLDOWN;
10395
10428
  let hallucinationRetries = 0;
10396
10429
  let lastToolSignature = "";
10397
10430
  let apiPromptTokens = 0;
@@ -10405,6 +10438,8 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
10405
10438
  let emptyResponseRetries = 0;
10406
10439
  const MAX_EMPTY_RESPONSE_RETRIES = 2;
10407
10440
  let emptyResponseExhausted = false;
10441
+ let auditFailed = false;
10442
+ let lastAuditSummary = "";
10408
10443
  let repeatedToolCount = 0;
10409
10444
  const MAX_REPEATED_TOOL_CALLS = 2;
10410
10445
  const allToolsForBudget = toolExecutor.getToolDefinitions(this.deps.toolTags);
@@ -10431,7 +10466,8 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
10431
10466
  const currentTokens = contextManager.getEstimatedTokens();
10432
10467
  const budget2 = contextManager.getBudget();
10433
10468
  const quality = contextManager.getQuality();
10434
- if (quality < QUALITY_TRIGGER_THRESHOLD && contextManager.getCompactionCount() > 0) {
10469
+ if (quality < QUALITY_TRIGGER_THRESHOLD && contextManager.getCompactionCount() > 0 && iteration - lastForcedCompactionIteration >= FORCED_COMPACTION_COOLDOWN) {
10470
+ lastForcedCompactionIteration = iteration;
10435
10471
  contextManager.compact();
10436
10472
  logger.warn(`Low context quality (${quality}%) — forced compaction`);
10437
10473
  slog.logCompaction(`quality-triggered compaction (${quality}% < ${QUALITY_TRIGGER_THRESHOLD}%), iteration ${iteration}`, iteration, currentTokens, budget2.history);
@@ -10794,8 +10830,10 @@ ${warnLine}
10794
10830
  });
10795
10831
  slog.logAudit(audit.summary, iteration);
10796
10832
  auditRetries++;
10833
+ lastAuditSummary = audit.summary;
10797
10834
  if (auditRetries >= MAX_AUDIT_RETRIES || iteration >= config.maxToolIterations - 1) {
10798
- logger.warn(`Final audit still incomplete after ${auditRetries} retries — finishing anyway`);
10835
+ logger.warn(`Final audit still incomplete after ${auditRetries} retries — reporting failure`);
10836
+ auditFailed = true;
10799
10837
  break;
10800
10838
  }
10801
10839
  continue;
@@ -10823,9 +10861,9 @@ ${warnLine}
10823
10861
  };
10824
10862
  }
10825
10863
  return {
10826
- success: emptyResponseExhausted ? false : true,
10864
+ success: emptyResponseExhausted || auditFailed ? false : true,
10827
10865
  text: lastText,
10828
- error: emptyResponseExhausted ? t("error.empty_response") : undefined,
10866
+ error: emptyResponseExhausted ? t("error.empty_response") : auditFailed ? t("error.audit_failed", { summary: lastAuditSummary }) : undefined,
10829
10867
  iterationCount: iteration,
10830
10868
  contextUsed: tokensUsed,
10831
10869
  contextLimit: budget.history,
@@ -10890,7 +10928,7 @@ ${warnLine}
10890
10928
  });
10891
10929
  }
10892
10930
  }
10893
- var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000, QUALITY_TRIGGER_THRESHOLD = 40;
10931
+ var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000, QUALITY_TRIGGER_THRESHOLD = 40, FORCED_COMPACTION_COOLDOWN = 3;
10894
10932
  var init_agent = __esm(() => {
10895
10933
  init_i18n();
10896
10934
  init_colors();
@@ -10993,7 +11031,8 @@ class ContextManager {
10993
11031
  getQuality() {
10994
11032
  const usedTokens = this.getEstimatedTokens();
10995
11033
  const tokenLoad = Math.max(0, 1 - usedTokens / this.budget.history);
10996
- const compactionLoss = Math.max(0, 1 - this.compactionCount * 0.15);
11034
+ const COMPACTION_PENALTY_FLOOR = 0.5;
11035
+ const compactionLoss = Math.max(COMPACTION_PENALTY_FLOOR, 1 - this.compactionCount * 0.15);
10997
11036
  const msgCount = this.messages.length || 1;
10998
11037
  const errorDensity = Math.max(0, 1 - Math.min(1, this.errorFacts.length / msgCount));
10999
11038
  const freshness = Math.max(0, 1 - this.iterationsSinceCompaction / COMPACTION_INTERVAL);
@@ -11139,6 +11178,9 @@ ${lines.join(`
11139
11178
  const newErrors = [];
11140
11179
  for (const msg of turns) {
11141
11180
  const content = getMessageText(msg.content);
11181
+ if (msg.role === "user" && (content.startsWith("<system-summary>") || content.includes("[Compressed:"))) {
11182
+ continue;
11183
+ }
11142
11184
  if (msg.role === "tool") {
11143
11185
  for (const pattern of filePatterns) {
11144
11186
  for (const match of content.matchAll(pattern)) {
@@ -15592,7 +15634,34 @@ ${display}`,
15592
15634
  };
15593
15635
  }
15594
15636
  if (action === "update" && args.step && this.tracker) {
15595
- this.tracker.updateStepStatus(Number(args.step), args.status || "done");
15637
+ const stepId = Number(args.step);
15638
+ const target = this.tracker.getStep(stepId);
15639
+ if (!target) {
15640
+ return { success: false, output: t("plan.step_not_found") };
15641
+ }
15642
+ const status = String(args.status || "done");
15643
+ if (status === "done" && target.status === "done") {
15644
+ return {
15645
+ success: false,
15646
+ output: t("plan.step_already_done", {
15647
+ step: String(stepId)
15648
+ })
15649
+ };
15650
+ }
15651
+ if (status === "done") {
15652
+ const blockers = this.tracker.getPlan().steps.filter((s) => s.id < stepId && s.status !== "done" && s.status !== "skipped");
15653
+ if (blockers.length > 0) {
15654
+ return {
15655
+ success: false,
15656
+ output: t("plan.order_blocked", {
15657
+ step: String(stepId),
15658
+ first: String(blockers[0].id),
15659
+ desc: blockers[0].description
15660
+ })
15661
+ };
15662
+ }
15663
+ }
15664
+ this.tracker.updateStepStatus(stepId, status);
15596
15665
  if (args.note)
15597
15666
  this.tracker.addNote(Number(args.step), String(args.note));
15598
15667
  this.tracker.syncCurrentStep();
@@ -17016,8 +17085,8 @@ class LspClient {
17016
17085
  }
17017
17086
  });
17018
17087
  return await diagPromise;
17019
- } catch {
17020
- return [];
17088
+ } catch (e) {
17089
+ throw e instanceof Error ? e : new Error(String(e));
17021
17090
  } finally {
17022
17091
  await this.shutdown();
17023
17092
  }
@@ -17249,7 +17318,15 @@ ${items}`;
17249
17318
  [LSP warnings]:
17250
17319
  ${items}`;
17251
17320
  }
17252
- } catch {}
17321
+ } catch (e) {
17322
+ const msg = e instanceof Error ? e.message : String(e);
17323
+ try {
17324
+ _ctx.logger?.warn(`LSP check failed for ${filePath}: ${msg}`);
17325
+ } catch {}
17326
+ result.output += `
17327
+
17328
+ [LSP check failed]: ${msg}`;
17329
+ }
17253
17330
  }
17254
17331
  };
17255
17332
  }
@@ -29087,9 +29164,180 @@ init_setup();
29087
29164
  init_config2();
29088
29165
  init_i18n();
29089
29166
  init_colors();
29090
- import { existsSync as existsSync46 } from "fs";
29091
- import { join as join40 } from "path";
29167
+ import { existsSync as existsSync46, readFileSync as readFileSync32 } from "fs";
29168
+ import { join as join40, dirname as dirname13 } from "path";
29092
29169
  import { homedir as homedir18 } from "os";
29170
+ import { fileURLToPath as fileURLToPath5 } from "url";
29171
+
29172
+ // src/modules/updater/checker.ts
29173
+ var defaultRunner2 = async (command, args, options) => {
29174
+ const { execFile } = await import("child_process");
29175
+ return new Promise((resolve23) => {
29176
+ execFile(command, args, options, (err) => resolve23({ error: err?.message }));
29177
+ });
29178
+ };
29179
+
29180
+ class Updater {
29181
+ currentVersion;
29182
+ packageName;
29183
+ runner;
29184
+ constructor(currentVersion, packageName, runner) {
29185
+ this.currentVersion = currentVersion;
29186
+ this.packageName = packageName;
29187
+ this.runner = runner ?? defaultRunner2;
29188
+ }
29189
+ getCurrentVersion() {
29190
+ return this.currentVersion;
29191
+ }
29192
+ getPackageName() {
29193
+ return this.packageName;
29194
+ }
29195
+ async check() {
29196
+ try {
29197
+ const response = await fetch(`https://registry.npmjs.org/${this.packageName}`, {
29198
+ headers: { Accept: "application/vnd.npm.install-v1+json" },
29199
+ signal: AbortSignal.timeout(5000)
29200
+ });
29201
+ if (!response.ok) {
29202
+ return { updateAvailable: false, current: this.currentVersion, error: `HTTP ${response.status}` };
29203
+ }
29204
+ const data = await response.json();
29205
+ const latest = data["dist-tags"]?.latest;
29206
+ if (!latest) {
29207
+ return { updateAvailable: false, current: this.currentVersion, error: "No latest tag" };
29208
+ }
29209
+ const updateAvailable = latest !== this.currentVersion;
29210
+ return { updateAvailable, current: this.currentVersion, latest };
29211
+ } catch (e) {
29212
+ return { updateAvailable: false, current: this.currentVersion, error: e.message };
29213
+ }
29214
+ }
29215
+ async install(latest) {
29216
+ try {
29217
+ const res = await this.runner("npm", ["install", "-g", `${this.packageName}@${latest}`], {
29218
+ timeout: 120000,
29219
+ windowsHide: true
29220
+ });
29221
+ if (res.error)
29222
+ return { success: false, error: res.error };
29223
+ return { success: true, installed: latest };
29224
+ } catch (e) {
29225
+ const msg = e?.message ?? String(e);
29226
+ return { success: false, error: msg.split(`
29227
+ `)[0] };
29228
+ }
29229
+ }
29230
+ }
29231
+ // src/modules/updater/module.ts
29232
+ init_i18n();
29233
+ init_colors();
29234
+
29235
+ class UpdaterModule {
29236
+ name = "updater";
29237
+ updater;
29238
+ config;
29239
+ logger;
29240
+ started = false;
29241
+ timer = null;
29242
+ installEnabled = true;
29243
+ constructor(config, currentVersion, packageName, logger, installRunner) {
29244
+ this.config = config;
29245
+ this.updater = new Updater(currentVersion, packageName, installRunner);
29246
+ this.logger = logger ?? {
29247
+ info: () => {},
29248
+ warn: (m) => console.warn(pc2.yellow(m)),
29249
+ error: (m) => console.error(pc2.red(m))
29250
+ };
29251
+ }
29252
+ setInstallEnabled(enabled2) {
29253
+ this.installEnabled = enabled2;
29254
+ }
29255
+ getUpdater() {
29256
+ return this.updater;
29257
+ }
29258
+ isStarted() {
29259
+ return this.started;
29260
+ }
29261
+ start() {
29262
+ if (this.started || !this.config.enabled)
29263
+ return;
29264
+ this.started = true;
29265
+ this.runLoop();
29266
+ }
29267
+ stop() {
29268
+ this.started = false;
29269
+ if (this.timer) {
29270
+ clearTimeout(this.timer);
29271
+ this.timer = null;
29272
+ }
29273
+ }
29274
+ async runLoop() {
29275
+ while (this.started) {
29276
+ await this.checkOnce();
29277
+ if (!this.started)
29278
+ return;
29279
+ if (this.config.intervalMs > 0) {
29280
+ await new Promise((r) => this.timer = setTimeout(r, this.config.intervalMs));
29281
+ } else {
29282
+ this.started = false;
29283
+ }
29284
+ }
29285
+ }
29286
+ async runOnce() {
29287
+ const result = await this.updater.check();
29288
+ if (result.error) {
29289
+ this.logger.info(t("updater.check_error", { error: result.error }));
29290
+ return;
29291
+ }
29292
+ if (!result.updateAvailable || !result.latest)
29293
+ return;
29294
+ if (this.config.autoInstall && this.installEnabled) {
29295
+ this.logger.info(t("updater.installing", {
29296
+ current: result.current,
29297
+ latest: result.latest
29298
+ }));
29299
+ const install = await this.updater.install(result.latest);
29300
+ if (install.success) {
29301
+ this.logger.info(t("updater.installed", { current: result.current, latest: result.latest }));
29302
+ } else {
29303
+ this.logger.warn(t("updater.install_failed", {
29304
+ current: result.current,
29305
+ latest: result.latest,
29306
+ error: install.error ?? ""
29307
+ }));
29308
+ }
29309
+ } else {
29310
+ this.logger.info(t("updater.available", { current: result.current, latest: result.latest }));
29311
+ }
29312
+ }
29313
+ async checkOnce() {
29314
+ await this.runOnce();
29315
+ }
29316
+ }
29317
+ // src/cli/main.ts
29318
+ function readVersion5() {
29319
+ const here = dirname13(fileURLToPath5(import.meta.url));
29320
+ const candidates = [
29321
+ join40(here, "..", "..", "package.json"),
29322
+ join40(here, "..", "package.json")
29323
+ ];
29324
+ for (const p of candidates) {
29325
+ if (existsSync46(p)) {
29326
+ try {
29327
+ const raw = JSON.parse(readFileSync32(p, "utf8"));
29328
+ if (raw.version)
29329
+ return raw.version;
29330
+ } catch {}
29331
+ }
29332
+ }
29333
+ return "0.0.0";
29334
+ }
29335
+ function startAutoUpdate(config) {
29336
+ try {
29337
+ const module = new UpdaterModule(config.updater, readVersion5(), "micro-models-agent");
29338
+ module.start();
29339
+ } catch {}
29340
+ }
29093
29341
  async function main() {
29094
29342
  const program2 = createProgram();
29095
29343
  program2.parse(process.argv);
@@ -29106,6 +29354,7 @@ async function main() {
29106
29354
  if (program2.args.length > 0) {
29107
29355
  const prompt = program2.args.join(" ");
29108
29356
  const { agent, config } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
29357
+ startAutoUpdate(config);
29109
29358
  if (jsonMode) {
29110
29359
  const result2 = await agent.run(prompt);
29111
29360
  agent.shutdown();
@@ -29215,6 +29464,7 @@ async function main() {
29215
29464
  baseDir,
29216
29465
  logger
29217
29466
  } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
29467
+ startAutoUpdate(config);
29218
29468
  const repl = new Repl(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger);
29219
29469
  repl.start();
29220
29470
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micro-models-agent",
3
- "version": "0.29.1",
3
+ "version": "0.30.0",
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": {