micro-models-agent 0.29.2 → 0.31.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 +367 -37
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2224,6 +2224,8 @@ var init_defaults = __esm(() => {
2224
2224
  enabled: true,
2225
2225
  headless: true,
2226
2226
  maxElements: 30,
2227
+ maxContentChars: 2500,
2228
+ maxConsoleEntries: 20,
2227
2229
  viewportWidth: 1280,
2228
2230
  viewportHeight: 720,
2229
2231
  navigationTimeout: 15000
@@ -2263,7 +2265,13 @@ var init_defaults = __esm(() => {
2263
2265
  stableSystemPrompt: true,
2264
2266
  maxParallelChunkQueries: 4
2265
2267
  },
2266
- lsp: DEFAULT_LSP_CONFIG
2268
+ lsp: DEFAULT_LSP_CONFIG,
2269
+ updater: {
2270
+ enabled: true,
2271
+ checkOnStart: true,
2272
+ autoInstall: true,
2273
+ intervalMs: 0
2274
+ }
2267
2275
  };
2268
2276
  });
2269
2277
 
@@ -2778,6 +2786,10 @@ Use this knowledge to answer the user's question.`,
2778
2786
  "browser.no_page_short": "No page",
2779
2787
  "browser.no_elements": "(no interactive elements on page)",
2780
2788
  "browser.more_elements": "... and more elements not shown. Use scroll or search to find others.",
2789
+ "browser.content_header": "Content:",
2790
+ "browser.console_header": "Console:",
2791
+ "browser.network_errors_header": "Network errors:",
2792
+ "browser.truncated": "... (truncated)",
2781
2793
  "pipeline.invalid": "Invalid pipeline: name and steps required",
2782
2794
  "pipeline.step_missing_fields": "Step missing required fields (id, agent, prompt): {step}",
2783
2795
  "pipeline.circular": "Circular dependency: {stepId}",
@@ -2832,8 +2844,13 @@ Use this knowledge to answer the user's question.`,
2832
2844
  "ctx.compactions": "compactions: {count}",
2833
2845
  "ctx.quality": "quality: {percent}%",
2834
2846
  "ctx.delta_pos": "ctx +{tokens}",
2835
- "ctx.delta_neg": "ctx -{tokens}",
2836
- "ctx.delta_zero": "ctx ±0"
2847
+ "ctx.delta_neg": "ctx -{tokens} ",
2848
+ "ctx.delta_zero": "ctx +0",
2849
+ "updater.check_error": "[updater] update check failed: {error}",
2850
+ "updater.available": "[updater] Update available: {current} → {latest}. Run `npm install -g micro-models-agent` to upgrade.",
2851
+ "updater.installing": "[updater] Installing {latest} globally (current: {current})…",
2852
+ "updater.installed": "[updater] Installed {latest}. Restart MMA to use it (was {current}).",
2853
+ "updater.install_failed": "[updater] Failed to install {latest}: {error}. Update manually with `npm install -g micro-models-agent`."
2837
2854
  };
2838
2855
  });
2839
2856
 
@@ -3346,6 +3363,10 @@ var init_ru = __esm(() => {
3346
3363
  "browser.no_page_short": "Нет страницы",
3347
3364
  "browser.no_elements": "(нет интерактивных элементов на странице)",
3348
3365
  "browser.more_elements": "... и другие элементы не показаны. Используйте прокрутку или поиск.",
3366
+ "browser.content_header": "Содержимое:",
3367
+ "browser.console_header": "Консоль:",
3368
+ "browser.network_errors_header": "Сетевые ошибки:",
3369
+ "browser.truncated": "... (обрезано)",
3349
3370
  "pipeline.invalid": "Невалидный пайплайн: требуются name и steps",
3350
3371
  "pipeline.step_missing_fields": "Шаг не содержит обязательных полей (id, agent, prompt): {step}",
3351
3372
  "pipeline.circular": "Циклическая зависимость: {stepId}",
@@ -3403,7 +3424,12 @@ var init_ru = __esm(() => {
3403
3424
  "ctx.delta_neg": "контекст -{tokens} ↓",
3404
3425
  "ctx.delta_zero": "контекст ±0",
3405
3426
  "file.notfound_resolved": "Файл не найден: {path} (резолвится в {resolved})",
3406
- "bash.echo_write_blocked": "Запись файлов через echo/printf ненадёжна в Windows cmd.exe (кавычки и многострочность ломаются). Используй инструмент write_file вместо этого (цель: {path})."
3427
+ "bash.echo_write_blocked": "Запись файлов через echo/printf ненадёжна в Windows cmd.exe (кавычки и многострочность ломаются). Используй инструмент write_file вместо этого (цель: {path}).",
3428
+ "updater.check_error": "[updater] Ошибка проверки обновления: {error}",
3429
+ "updater.available": "[updater] Доступно обновление: {current} → {latest}. Выполните `npm install -g micro-models-agent` для обновления.",
3430
+ "updater.installing": "[updater] Установка {latest} глобально (текущая: {current})…",
3431
+ "updater.installed": "[updater] Установлена {latest}. Перезапустите MMA для применения (была {current}).",
3432
+ "updater.install_failed": "[updater] Не удалось установить {latest}: {error}. Обновите вручную: `npm install -g micro-models-agent`."
3407
3433
  };
3408
3434
  });
3409
3435
 
@@ -13644,6 +13670,22 @@ var init_recall = __esm(() => {
13644
13670
  };
13645
13671
  });
13646
13672
 
13673
+ // src/modules/browser/types.ts
13674
+ var DEFAULT_BROWSER_CONFIG;
13675
+ var init_types = __esm(() => {
13676
+ DEFAULT_BROWSER_CONFIG = {
13677
+ headless: true,
13678
+ maxElements: 30,
13679
+ maxContentChars: 2500,
13680
+ maxConsoleEntries: 20,
13681
+ screenshotMaxWidth: 1280,
13682
+ cookieDir: "",
13683
+ viewportWidth: 1280,
13684
+ viewportHeight: 720,
13685
+ navigationTimeout: 15000
13686
+ };
13687
+ });
13688
+
13647
13689
  // src/modules/browser/snapshot.ts
13648
13690
  function inferRole(tag, type) {
13649
13691
  const t2 = tag.toLowerCase();
@@ -13731,35 +13773,69 @@ function extractInteractiveElements(html, maxElements = 30) {
13731
13773
  }
13732
13774
  return elements;
13733
13775
  }
13734
- function formatSnapshot(snapshot) {
13776
+ function truncateText(text, maxChars) {
13777
+ if (maxChars <= 0)
13778
+ return "";
13779
+ if (text.length <= maxChars)
13780
+ return text;
13781
+ const cut = text.slice(0, maxChars);
13782
+ const lastNewline = cut.lastIndexOf(`
13783
+ `);
13784
+ const safe = lastNewline > maxChars * 0.6 ? cut.slice(0, lastNewline) : cut;
13785
+ return `${safe}
13786
+ ${t("browser.truncated")}`;
13787
+ }
13788
+ function formatSnapshot(snapshot, maxContentChars = DEFAULT_BROWSER_CONFIG.maxContentChars) {
13735
13789
  const lines = [];
13736
13790
  lines.push(`Page: "${snapshot.title}"`);
13737
13791
  lines.push(`URL: ${snapshot.url}`);
13738
13792
  lines.push("");
13739
13793
  if (snapshot.elements.length === 0 && !snapshot.truncated) {
13740
13794
  lines.push(t("browser.no_elements"));
13741
- return lines.join(`
13742
- `);
13795
+ } else {
13796
+ for (const el of snapshot.elements) {
13797
+ let line = `[${el.index}] ${el.role}`;
13798
+ if (el.name)
13799
+ line += ` "${el.name}"`;
13800
+ if (el.href)
13801
+ line += ` → ${el.href}`;
13802
+ if (el.value)
13803
+ line += ` = "${el.value}"`;
13804
+ lines.push(line);
13805
+ }
13806
+ if (snapshot.truncated) {
13807
+ lines.push("");
13808
+ lines.push(t("browser.more_elements"));
13809
+ }
13743
13810
  }
13744
- for (const el of snapshot.elements) {
13745
- let line = `[${el.index}] ${el.role}`;
13746
- if (el.name)
13747
- line += ` "${el.name}"`;
13748
- if (el.href)
13749
- line += ` → ${el.href}`;
13750
- if (el.value)
13751
- line += ` = "${el.value}"`;
13752
- lines.push(line);
13753
- }
13754
- if (snapshot.truncated) {
13811
+ if (snapshot.content) {
13755
13812
  lines.push("");
13756
- lines.push(t("browser.more_elements"));
13813
+ lines.push(t("browser.content_header"));
13814
+ for (const line of truncateText(snapshot.content, maxContentChars).split(`
13815
+ `)) {
13816
+ lines.push(`- ${line}`);
13817
+ }
13818
+ }
13819
+ if (snapshot.console.length > 0) {
13820
+ lines.push("");
13821
+ lines.push(t("browser.console_header"));
13822
+ for (const entry of snapshot.console) {
13823
+ lines.push(`[${entry.type}] ${entry.text}`);
13824
+ }
13825
+ }
13826
+ if (snapshot.networkErrors.length > 0) {
13827
+ lines.push("");
13828
+ lines.push(t("browser.network_errors_header"));
13829
+ for (const err of snapshot.networkErrors) {
13830
+ lines.push(`${err.method} ${err.url} → ${err.error}`);
13831
+ }
13757
13832
  }
13758
13833
  return lines.join(`
13759
13834
  `);
13760
13835
  }
13761
13836
  var init_snapshot = __esm(() => {
13762
13837
  init_i18n();
13838
+ init_types();
13763
13839
  });
13764
13840
 
13765
13841
  // src/modules/browser/actions.ts
@@ -13806,6 +13882,36 @@ function buildIndexInjectionScript() {
13806
13882
  });
13807
13883
  `;
13808
13884
  }
13885
+ function buildTextExtractionScript() {
13886
+ return `
13887
+ const contentTags = new Set(['h1','h2','h3','h4','h5','h6','p','li','article','main','section','blockquote','pre','td','th','dt','dd','figcaption']);
13888
+ const out = [];
13889
+ const seen = new Set();
13890
+ const isHidden = (el) => {
13891
+ const st = window.getComputedStyle(el);
13892
+ return st.display === 'none' || st.visibility === 'hidden';
13893
+ };
13894
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
13895
+ acceptNode: (node) => {
13896
+ const tag = node.tagName ? node.tagName.toLowerCase() : '';
13897
+ if (!contentTags.has(tag)) return NodeFilter.FILTER_SKIP;
13898
+ if (isHidden(node)) return NodeFilter.FILTER_REJECT;
13899
+ return NodeFilter.FILTER_ACCEPT;
13900
+ }
13901
+ });
13902
+ let node;
13903
+ while ((node = walker.nextNode())) {
13904
+ const tag = node.tagName.toLowerCase();
13905
+ const text = (node.textContent || '').replace(/\\s+/g, ' ').trim();
13906
+ if (!text) continue;
13907
+ if (seen.has(text)) continue;
13908
+ seen.add(text);
13909
+ const line = text.length > 200 ? text.slice(0, 200) + '…' : text;
13910
+ out.push('[' + tag + '] ' + line);
13911
+ }
13912
+ return out.join('\\n');
13913
+ `;
13914
+ }
13809
13915
 
13810
13916
  // src/modules/browser/cookie-store.ts
13811
13917
  import { readFile, writeFile, mkdir } from "fs/promises";
@@ -13839,6 +13945,33 @@ import {
13839
13945
  chromium
13840
13946
  } from "playwright";
13841
13947
 
13948
+ class ConsoleBuffer {
13949
+ entries = [];
13950
+ maxEntries;
13951
+ constructor(maxEntries = 20) {
13952
+ this.maxEntries = maxEntries;
13953
+ }
13954
+ add(type, text) {
13955
+ const clean = String(text).replace(/\s+/g, " ").trim();
13956
+ if (!clean)
13957
+ return;
13958
+ const line = clean.length > CONSOLE_MAX_LINE ? clean.slice(0, CONSOLE_MAX_LINE) + "…" : clean;
13959
+ this.entries.push({ type, text: line });
13960
+ if (this.entries.length > this.maxEntries) {
13961
+ this.entries.splice(0, this.entries.length - this.maxEntries);
13962
+ }
13963
+ }
13964
+ clear() {
13965
+ this.entries = [];
13966
+ }
13967
+ getAll() {
13968
+ return [...this.entries];
13969
+ }
13970
+ get size() {
13971
+ return this.entries.length;
13972
+ }
13973
+ }
13974
+
13842
13975
  class BrowserActionTracker {
13843
13976
  history = [];
13844
13977
  threshold;
@@ -13877,9 +14010,12 @@ class BrowserSession {
13877
14010
  elementCount: 0
13878
14011
  };
13879
14012
  actionTracker = new BrowserActionTracker(3);
14013
+ consoleBuffer;
14014
+ networkErrors = [];
13880
14015
  constructor(config) {
13881
14016
  this.config = config;
13882
14017
  this.cookieStore = new CookieStore(config.cookieDir);
14018
+ this.consoleBuffer = new ConsoleBuffer(config.maxConsoleEntries);
13883
14019
  }
13884
14020
  getState() {
13885
14021
  return { ...this.state };
@@ -13965,6 +14101,20 @@ class BrowserSession {
13965
14101
  }
13966
14102
  this.page = await this.context.newPage();
13967
14103
  this.page.setDefaultTimeout(this.config.navigationTimeout);
14104
+ this.page.on("console", (msg) => {
14105
+ this.consoleBuffer.add(msg.type(), msg.text());
14106
+ });
14107
+ this.page.on("pageerror", (err) => {
14108
+ this.consoleBuffer.add("pageerror", `Page error: ${err.message}`);
14109
+ });
14110
+ this.page.on("requestfailed", (req) => {
14111
+ const failure = req.failure();
14112
+ this.networkErrors.push({
14113
+ method: req.method(),
14114
+ url: req.url(),
14115
+ error: failure?.errorText || "unknown"
14116
+ });
14117
+ });
13968
14118
  }
13969
14119
  async saveCookies() {
13970
14120
  if (!this.context)
@@ -13979,6 +14129,12 @@ class BrowserSession {
13979
14129
  const html = await this.page.content();
13980
14130
  const url = this.page.url();
13981
14131
  const title = await this.page.title();
14132
+ let content = "";
14133
+ try {
14134
+ content = await this.page.evaluate(buildTextExtractionScript());
14135
+ } catch {
14136
+ content = "";
14137
+ }
13982
14138
  const allElements = extractInteractiveElements(html, this.config.maxElements + 5);
13983
14139
  const truncated = allElements.length > this.config.maxElements;
13984
14140
  const elements = allElements.slice(0, this.config.maxElements);
@@ -13988,7 +14144,15 @@ class BrowserSession {
13988
14144
  title,
13989
14145
  elementCount: elements.length
13990
14146
  };
13991
- return formatSnapshot({ url, title, elements, truncated });
14147
+ return formatSnapshot({
14148
+ url,
14149
+ title,
14150
+ elements,
14151
+ content,
14152
+ console: this.consoleBuffer.getAll(),
14153
+ networkErrors: this.networkErrors.slice(-5),
14154
+ truncated
14155
+ });
13992
14156
  }
13993
14157
  async open(url) {
13994
14158
  if (!url)
@@ -14001,6 +14165,8 @@ class BrowserSession {
14001
14165
  if (!this.page)
14002
14166
  return { success: false, output: t("browser.create_page_failed") };
14003
14167
  this.actionTracker.reset();
14168
+ this.consoleBuffer.clear();
14169
+ this.networkErrors = [];
14004
14170
  try {
14005
14171
  await this.page.goto(url, {
14006
14172
  waitUntil: "domcontentloaded",
@@ -14157,26 +14323,13 @@ class BrowserSession {
14157
14323
  return { success: true, output: t("browser.closed") };
14158
14324
  }
14159
14325
  }
14326
+ var CONSOLE_MAX_LINE = 200;
14160
14327
  var init_session = __esm(() => {
14161
14328
  init_snapshot();
14162
14329
  init_cookie_store();
14163
14330
  init_i18n();
14164
14331
  });
14165
14332
 
14166
- // src/modules/browser/types.ts
14167
- var DEFAULT_BROWSER_CONFIG;
14168
- var init_types = __esm(() => {
14169
- DEFAULT_BROWSER_CONFIG = {
14170
- headless: true,
14171
- maxElements: 30,
14172
- screenshotMaxWidth: 1280,
14173
- cookieDir: "",
14174
- viewportWidth: 1280,
14175
- viewportHeight: 720,
14176
- navigationTimeout: 15000
14177
- };
14178
- });
14179
-
14180
14333
  // src/tools/browser.ts
14181
14334
  import { join as join18 } from "path";
14182
14335
  function getSession(ctx) {
@@ -14186,6 +14339,8 @@ function getSession(ctx) {
14186
14339
  ...DEFAULT_BROWSER_CONFIG,
14187
14340
  headless: ctx.config.browser?.headless ?? true,
14188
14341
  maxElements: ctx.config.browser?.maxElements ?? 30,
14342
+ maxContentChars: ctx.config.browser?.maxContentChars ?? 2500,
14343
+ maxConsoleEntries: ctx.config.browser?.maxConsoleEntries ?? 20,
14189
14344
  navigationTimeout: ctx.config.browser?.navigationTimeout ?? 15000,
14190
14345
  viewportWidth: ctx.config.browser?.viewportWidth ?? 1280,
14191
14346
  viewportHeight: ctx.config.browser?.viewportHeight ?? 720,
@@ -14214,7 +14369,8 @@ function createBrowserTool() {
14214
14369
  tags: ["browser", "vision"],
14215
14370
  description: [
14216
14371
  "Control a headless browser. Navigate pages, click elements, type text, scroll, take screenshots.",
14217
- "Returns a numbered list of interactive elements use element numbers as targets for click/type.",
14372
+ "Each snapshot returns: a numbered list of interactive elements, the visible page text (Content section), browser console messages, and network errors.",
14373
+ "Use the Content section to understand what the page says; use element numbers as targets for click/type.",
14218
14374
  "Actions: open (url), click (target), type (target, text), scroll (direction), back, forward, screenshot, snapshot, close, wait (ms)."
14219
14375
  ].join(" "),
14220
14376
  parameters: {
@@ -16986,6 +17142,7 @@ class BrowserModule {
16986
17142
  content: [
16987
17143
  "You have a headless browser tool. Use it to navigate websites, click links, fill forms, and read page content.",
16988
17144
  "Workflow: open(url) → read snapshot → click/type on element numbers → read updated snapshot.",
17145
+ 'Each snapshot includes a "Content" section with the visible page text, a "Console" section with browser messages, and network errors. Use these to understand the page, detect JS errors, and verify the result of your actions.',
16989
17146
  'Always start with "open" action. Use element numbers from snapshot for click/type targets.',
16990
17147
  'Use "screenshot" action only if the model supports vision. Otherwise rely on the text snapshot.'
16991
17148
  ].join(`
@@ -29148,9 +29305,180 @@ init_setup();
29148
29305
  init_config2();
29149
29306
  init_i18n();
29150
29307
  init_colors();
29151
- import { existsSync as existsSync46 } from "fs";
29152
- import { join as join40 } from "path";
29308
+ import { existsSync as existsSync46, readFileSync as readFileSync32 } from "fs";
29309
+ import { join as join40, dirname as dirname13 } from "path";
29153
29310
  import { homedir as homedir18 } from "os";
29311
+ import { fileURLToPath as fileURLToPath5 } from "url";
29312
+
29313
+ // src/modules/updater/checker.ts
29314
+ var defaultRunner2 = async (command, args, options) => {
29315
+ const { execFile } = await import("child_process");
29316
+ return new Promise((resolve23) => {
29317
+ execFile(command, args, options, (err) => resolve23({ error: err?.message }));
29318
+ });
29319
+ };
29320
+
29321
+ class Updater {
29322
+ currentVersion;
29323
+ packageName;
29324
+ runner;
29325
+ constructor(currentVersion, packageName, runner) {
29326
+ this.currentVersion = currentVersion;
29327
+ this.packageName = packageName;
29328
+ this.runner = runner ?? defaultRunner2;
29329
+ }
29330
+ getCurrentVersion() {
29331
+ return this.currentVersion;
29332
+ }
29333
+ getPackageName() {
29334
+ return this.packageName;
29335
+ }
29336
+ async check() {
29337
+ try {
29338
+ const response = await fetch(`https://registry.npmjs.org/${this.packageName}`, {
29339
+ headers: { Accept: "application/vnd.npm.install-v1+json" },
29340
+ signal: AbortSignal.timeout(5000)
29341
+ });
29342
+ if (!response.ok) {
29343
+ return { updateAvailable: false, current: this.currentVersion, error: `HTTP ${response.status}` };
29344
+ }
29345
+ const data = await response.json();
29346
+ const latest = data["dist-tags"]?.latest;
29347
+ if (!latest) {
29348
+ return { updateAvailable: false, current: this.currentVersion, error: "No latest tag" };
29349
+ }
29350
+ const updateAvailable = latest !== this.currentVersion;
29351
+ return { updateAvailable, current: this.currentVersion, latest };
29352
+ } catch (e) {
29353
+ return { updateAvailable: false, current: this.currentVersion, error: e.message };
29354
+ }
29355
+ }
29356
+ async install(latest) {
29357
+ try {
29358
+ const res = await this.runner("npm", ["install", "-g", `${this.packageName}@${latest}`], {
29359
+ timeout: 120000,
29360
+ windowsHide: true
29361
+ });
29362
+ if (res.error)
29363
+ return { success: false, error: res.error };
29364
+ return { success: true, installed: latest };
29365
+ } catch (e) {
29366
+ const msg = e?.message ?? String(e);
29367
+ return { success: false, error: msg.split(`
29368
+ `)[0] };
29369
+ }
29370
+ }
29371
+ }
29372
+ // src/modules/updater/module.ts
29373
+ init_i18n();
29374
+ init_colors();
29375
+
29376
+ class UpdaterModule {
29377
+ name = "updater";
29378
+ updater;
29379
+ config;
29380
+ logger;
29381
+ started = false;
29382
+ timer = null;
29383
+ installEnabled = true;
29384
+ constructor(config, currentVersion, packageName, logger, installRunner) {
29385
+ this.config = config;
29386
+ this.updater = new Updater(currentVersion, packageName, installRunner);
29387
+ this.logger = logger ?? {
29388
+ info: () => {},
29389
+ warn: (m) => console.warn(pc2.yellow(m)),
29390
+ error: (m) => console.error(pc2.red(m))
29391
+ };
29392
+ }
29393
+ setInstallEnabled(enabled2) {
29394
+ this.installEnabled = enabled2;
29395
+ }
29396
+ getUpdater() {
29397
+ return this.updater;
29398
+ }
29399
+ isStarted() {
29400
+ return this.started;
29401
+ }
29402
+ start() {
29403
+ if (this.started || !this.config.enabled)
29404
+ return;
29405
+ this.started = true;
29406
+ this.runLoop();
29407
+ }
29408
+ stop() {
29409
+ this.started = false;
29410
+ if (this.timer) {
29411
+ clearTimeout(this.timer);
29412
+ this.timer = null;
29413
+ }
29414
+ }
29415
+ async runLoop() {
29416
+ while (this.started) {
29417
+ await this.checkOnce();
29418
+ if (!this.started)
29419
+ return;
29420
+ if (this.config.intervalMs > 0) {
29421
+ await new Promise((r) => this.timer = setTimeout(r, this.config.intervalMs));
29422
+ } else {
29423
+ this.started = false;
29424
+ }
29425
+ }
29426
+ }
29427
+ async runOnce() {
29428
+ const result = await this.updater.check();
29429
+ if (result.error) {
29430
+ this.logger.info(t("updater.check_error", { error: result.error }));
29431
+ return;
29432
+ }
29433
+ if (!result.updateAvailable || !result.latest)
29434
+ return;
29435
+ if (this.config.autoInstall && this.installEnabled) {
29436
+ this.logger.info(t("updater.installing", {
29437
+ current: result.current,
29438
+ latest: result.latest
29439
+ }));
29440
+ const install = await this.updater.install(result.latest);
29441
+ if (install.success) {
29442
+ this.logger.info(t("updater.installed", { current: result.current, latest: result.latest }));
29443
+ } else {
29444
+ this.logger.warn(t("updater.install_failed", {
29445
+ current: result.current,
29446
+ latest: result.latest,
29447
+ error: install.error ?? ""
29448
+ }));
29449
+ }
29450
+ } else {
29451
+ this.logger.info(t("updater.available", { current: result.current, latest: result.latest }));
29452
+ }
29453
+ }
29454
+ async checkOnce() {
29455
+ await this.runOnce();
29456
+ }
29457
+ }
29458
+ // src/cli/main.ts
29459
+ function readVersion5() {
29460
+ const here = dirname13(fileURLToPath5(import.meta.url));
29461
+ const candidates = [
29462
+ join40(here, "..", "..", "package.json"),
29463
+ join40(here, "..", "package.json")
29464
+ ];
29465
+ for (const p of candidates) {
29466
+ if (existsSync46(p)) {
29467
+ try {
29468
+ const raw = JSON.parse(readFileSync32(p, "utf8"));
29469
+ if (raw.version)
29470
+ return raw.version;
29471
+ } catch {}
29472
+ }
29473
+ }
29474
+ return "0.0.0";
29475
+ }
29476
+ function startAutoUpdate(config) {
29477
+ try {
29478
+ const module = new UpdaterModule(config.updater, readVersion5(), "micro-models-agent");
29479
+ module.start();
29480
+ } catch {}
29481
+ }
29154
29482
  async function main() {
29155
29483
  const program2 = createProgram();
29156
29484
  program2.parse(process.argv);
@@ -29167,6 +29495,7 @@ async function main() {
29167
29495
  if (program2.args.length > 0) {
29168
29496
  const prompt = program2.args.join(" ");
29169
29497
  const { agent, config } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
29498
+ startAutoUpdate(config);
29170
29499
  if (jsonMode) {
29171
29500
  const result2 = await agent.run(prompt);
29172
29501
  agent.shutdown();
@@ -29276,6 +29605,7 @@ async function main() {
29276
29605
  baseDir,
29277
29606
  logger
29278
29607
  } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
29608
+ startAutoUpdate(config);
29279
29609
  const repl = new Repl(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger);
29280
29610
  repl.start();
29281
29611
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micro-models-agent",
3
- "version": "0.29.2",
3
+ "version": "0.31.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": {