micro-models-agent 0.30.0 → 0.32.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.
package/dist/main.js CHANGED
@@ -2224,6 +2224,9 @@ var init_defaults = __esm(() => {
2224
2224
  enabled: true,
2225
2225
  headless: true,
2226
2226
  maxElements: 30,
2227
+ maxContentChars: 2500,
2228
+ maxConsoleEntries: 40,
2229
+ maxConsoleLineChars: 400,
2227
2230
  viewportWidth: 1280,
2228
2231
  viewportHeight: 720,
2229
2232
  navigationTimeout: 15000
@@ -2784,6 +2787,10 @@ Use this knowledge to answer the user's question.`,
2784
2787
  "browser.no_page_short": "No page",
2785
2788
  "browser.no_elements": "(no interactive elements on page)",
2786
2789
  "browser.more_elements": "... and more elements not shown. Use scroll or search to find others.",
2790
+ "browser.content_header": "Content:",
2791
+ "browser.console_header": "Console:",
2792
+ "browser.network_errors_header": "Network errors:",
2793
+ "browser.truncated": "... (truncated)",
2787
2794
  "pipeline.invalid": "Invalid pipeline: name and steps required",
2788
2795
  "pipeline.step_missing_fields": "Step missing required fields (id, agent, prompt): {step}",
2789
2796
  "pipeline.circular": "Circular dependency: {stepId}",
@@ -3357,6 +3364,10 @@ var init_ru = __esm(() => {
3357
3364
  "browser.no_page_short": "Нет страницы",
3358
3365
  "browser.no_elements": "(нет интерактивных элементов на странице)",
3359
3366
  "browser.more_elements": "... и другие элементы не показаны. Используйте прокрутку или поиск.",
3367
+ "browser.content_header": "Содержимое:",
3368
+ "browser.console_header": "Консоль:",
3369
+ "browser.network_errors_header": "Сетевые ошибки:",
3370
+ "browser.truncated": "... (обрезано)",
3360
3371
  "pipeline.invalid": "Невалидный пайплайн: требуются name и steps",
3361
3372
  "pipeline.step_missing_fields": "Шаг не содержит обязательных полей (id, agent, prompt): {step}",
3362
3373
  "pipeline.circular": "Циклическая зависимость: {stepId}",
@@ -13660,6 +13671,323 @@ var init_recall = __esm(() => {
13660
13671
  };
13661
13672
  });
13662
13673
 
13674
+ // src/modules/browser/bridge-client.ts
13675
+ var exports_bridge_client = {};
13676
+ __export(exports_bridge_client, {
13677
+ BridgeDriver: () => BridgeDriver
13678
+ });
13679
+ import { spawn as spawn4 } from "child_process";
13680
+ import { createInterface } from "readline";
13681
+ import { dirname as dirname6, join as join17 } from "path";
13682
+ import { fileURLToPath } from "url";
13683
+ function bridgeScriptPath() {
13684
+ return join17(dirname6(fileURLToPath(import.meta.url)), "bridge-server.mjs");
13685
+ }
13686
+
13687
+ class BridgeDriver {
13688
+ proc = null;
13689
+ rl = null;
13690
+ pending = new Map;
13691
+ nextId = 1;
13692
+ lastUrl = "";
13693
+ console = new ConsoleBuffer(500);
13694
+ network = [];
13695
+ maxConsoleLineChars;
13696
+ constructor(opts = {}) {
13697
+ this.maxConsoleLineChars = opts.maxConsoleLineChars ?? 400;
13698
+ }
13699
+ async send(cmd, params = {}) {
13700
+ if (!this.proc || !this.rl)
13701
+ throw new Error("Bridge is not running");
13702
+ const id = this.nextId++;
13703
+ const response = await new Promise((resolve15, reject) => {
13704
+ const timer = setTimeout(() => {
13705
+ this.pending.delete(id);
13706
+ reject(new Error(`Bridge timeout waiting for "${cmd}"`));
13707
+ }, BRIDGE_REQUEST_TIMEOUT_MS);
13708
+ this.pending.set(id, (resp) => {
13709
+ clearTimeout(timer);
13710
+ resolve15(resp);
13711
+ });
13712
+ this.proc.stdin.write(JSON.stringify({ id, cmd, params }) + `
13713
+ `);
13714
+ });
13715
+ this.drainEvents(response);
13716
+ if (!response.ok)
13717
+ throw new Error(response.error || `Bridge command failed: ${cmd}`);
13718
+ return response;
13719
+ }
13720
+ drainEvents(resp) {
13721
+ if (Array.isArray(resp.console)) {
13722
+ for (const entry of resp.console) {
13723
+ this.console.add(entry.type, entry.text);
13724
+ }
13725
+ }
13726
+ if (Array.isArray(resp.network)) {
13727
+ for (const err of resp.network)
13728
+ this.network.push(err);
13729
+ }
13730
+ if (resp.data && typeof resp.data.url === "string") {
13731
+ this.lastUrl = resp.data.url;
13732
+ }
13733
+ }
13734
+ async launch(cfg) {
13735
+ this.spawnBridge();
13736
+ await this.send("launch", {
13737
+ headless: cfg.headless,
13738
+ viewport: cfg.viewport,
13739
+ timeoutMs: cfg.timeoutMs,
13740
+ maxConsoleLineChars: this.maxConsoleLineChars
13741
+ });
13742
+ }
13743
+ spawnBridge() {
13744
+ const script = bridgeScriptPath();
13745
+ const proc = spawn4("node", [script], { stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
13746
+ this.proc = proc;
13747
+ proc.stderr.on("data", () => {});
13748
+ const rl = createInterface({ input: proc.stdout });
13749
+ this.rl = rl;
13750
+ rl.on("line", (line) => {
13751
+ let resp;
13752
+ try {
13753
+ resp = JSON.parse(line);
13754
+ } catch {
13755
+ return;
13756
+ }
13757
+ const resolver = this.pending.get(resp.id);
13758
+ if (resolver) {
13759
+ this.pending.delete(resp.id);
13760
+ resolver(resp);
13761
+ }
13762
+ });
13763
+ proc.on("exit", () => {
13764
+ for (const [, resolver] of this.pending) {
13765
+ resolver({ id: -1, ok: false, error: "Bridge process exited" });
13766
+ }
13767
+ this.pending.clear();
13768
+ this.proc = null;
13769
+ this.rl = null;
13770
+ });
13771
+ }
13772
+ async goto(url, timeoutMs) {
13773
+ await this.send("goto", { url, timeoutMs });
13774
+ }
13775
+ async evaluate(js) {
13776
+ const resp = await this.send("evaluate", { js });
13777
+ return resp.data?.result;
13778
+ }
13779
+ async content() {
13780
+ const resp = await this.send("content");
13781
+ return String(resp.data?.html ?? "");
13782
+ }
13783
+ async title() {
13784
+ const resp = await this.send("title");
13785
+ return String(resp.data?.title ?? "");
13786
+ }
13787
+ url() {
13788
+ return this.lastUrl;
13789
+ }
13790
+ async waitForLoad(timeoutMs) {
13791
+ await this.send("waitLoad", { timeoutMs });
13792
+ }
13793
+ async screenshot() {
13794
+ const resp = await this.send("screenshot");
13795
+ return Buffer.from(String(resp.data?.base64 ?? ""), "base64");
13796
+ }
13797
+ async cookies() {
13798
+ const resp = await this.send("cookies");
13799
+ return resp.data?.cookies ?? [];
13800
+ }
13801
+ async addCookies(cookies) {
13802
+ await this.send("setCookies", { cookies });
13803
+ }
13804
+ async goBack(timeoutMs) {
13805
+ await this.send("back", { timeoutMs });
13806
+ }
13807
+ async goForward(timeoutMs) {
13808
+ await this.send("forward", { timeoutMs });
13809
+ }
13810
+ resetEventLog() {
13811
+ this.console.clear();
13812
+ this.network = [];
13813
+ }
13814
+ getConsole() {
13815
+ return this.console.getAll();
13816
+ }
13817
+ getNetworkErrors() {
13818
+ return this.network.slice(-15);
13819
+ }
13820
+ async close() {
13821
+ try {
13822
+ if (this.proc)
13823
+ await this.send("close");
13824
+ } catch {}
13825
+ this.dispose();
13826
+ }
13827
+ dispose() {
13828
+ if (this.proc) {
13829
+ this.proc.kill();
13830
+ this.proc = null;
13831
+ }
13832
+ if (this.rl) {
13833
+ this.rl.close();
13834
+ this.rl = null;
13835
+ }
13836
+ }
13837
+ }
13838
+ var BRIDGE_REQUEST_TIMEOUT_MS = 30000;
13839
+ var init_bridge_client = __esm(() => {
13840
+ init_session();
13841
+ });
13842
+
13843
+ // src/modules/browser/driver.ts
13844
+ import { chromium } from "playwright";
13845
+
13846
+ class PlaywrightDriver {
13847
+ browser = null;
13848
+ context = null;
13849
+ page = null;
13850
+ console = new ConsoleBuffer;
13851
+ network = [];
13852
+ async launch(cfg) {
13853
+ if (this.browser)
13854
+ return;
13855
+ this.browser = await chromium.launch({
13856
+ headless: cfg.headless,
13857
+ timeout: cfg.timeoutMs
13858
+ });
13859
+ this.context = await this.browser.newContext({ viewport: cfg.viewport });
13860
+ this.page = await this.context.newPage();
13861
+ this.page.setDefaultTimeout(cfg.timeoutMs);
13862
+ this.page.on("console", (msg) => this.console.add(msg.type(), msg.text()));
13863
+ this.page.on("pageerror", (err) => this.console.add("pageerror", `Page error: ${err.message}`));
13864
+ this.page.on("requestfailed", (req) => {
13865
+ const failure = req.failure();
13866
+ this.network.push({
13867
+ method: req.method(),
13868
+ url: req.url(),
13869
+ error: failure?.errorText || "unknown"
13870
+ });
13871
+ });
13872
+ }
13873
+ async goto(url, timeoutMs) {
13874
+ this.requirePage();
13875
+ this.console.clear();
13876
+ this.network = [];
13877
+ await this.page.goto(url, { waitUntil: "domcontentloaded", timeout: timeoutMs });
13878
+ }
13879
+ async evaluate(js) {
13880
+ return this.requirePage().evaluate(js);
13881
+ }
13882
+ async content() {
13883
+ return this.requirePage().content();
13884
+ }
13885
+ async title() {
13886
+ return this.requirePage().title();
13887
+ }
13888
+ url() {
13889
+ return this.page?.url() || "";
13890
+ }
13891
+ async waitForLoad(timeoutMs) {
13892
+ await this.requirePage().waitForLoadState("domcontentloaded", { timeout: timeoutMs }).catch(() => {});
13893
+ }
13894
+ async screenshot() {
13895
+ return this.requirePage().screenshot({ type: "png", fullPage: false });
13896
+ }
13897
+ async cookies() {
13898
+ if (!this.context)
13899
+ return [];
13900
+ return this.context.cookies();
13901
+ }
13902
+ async addCookies(cookies) {
13903
+ if (!this.context || cookies.length === 0)
13904
+ return;
13905
+ await this.context.addCookies(cookies);
13906
+ }
13907
+ async goBack(timeoutMs) {
13908
+ await this.requirePage().goBack({ waitUntil: "domcontentloaded", timeout: timeoutMs }).catch(() => {});
13909
+ }
13910
+ async goForward(timeoutMs) {
13911
+ await this.requirePage().goForward({ waitUntil: "domcontentloaded", timeout: timeoutMs }).catch(() => {});
13912
+ }
13913
+ resetEventLog() {
13914
+ this.console.clear();
13915
+ this.network = [];
13916
+ }
13917
+ getConsole() {
13918
+ return this.console.getAll();
13919
+ }
13920
+ getNetworkErrors() {
13921
+ return this.network.slice(-15);
13922
+ }
13923
+ async close() {
13924
+ if (this.page)
13925
+ await this.page.close().catch(() => {});
13926
+ if (this.context)
13927
+ await this.context.close().catch(() => {});
13928
+ if (this.browser)
13929
+ await this.browser.close().catch(() => {});
13930
+ this.page = null;
13931
+ this.context = null;
13932
+ this.browser = null;
13933
+ }
13934
+ dispose() {
13935
+ this.close().catch(() => {});
13936
+ }
13937
+ requirePage() {
13938
+ if (!this.page)
13939
+ throw new Error("No page open");
13940
+ return this.page;
13941
+ }
13942
+ }
13943
+ function createBrowserDriver(config) {
13944
+ const common = {
13945
+ headless: config.headless,
13946
+ viewport: { width: config.viewportWidth, height: config.viewportHeight },
13947
+ timeoutMs: config.navigationTimeout
13948
+ };
13949
+ return (async () => {
13950
+ if (process.versions.bun) {
13951
+ return launchBridge(config, common);
13952
+ }
13953
+ const direct = new PlaywrightDriver;
13954
+ try {
13955
+ await direct.launch({ ...common, timeoutMs: DIRECT_LAUNCH_TIMEOUT_MS });
13956
+ return direct;
13957
+ } catch {
13958
+ direct.dispose();
13959
+ }
13960
+ return launchBridge(config, common);
13961
+ })();
13962
+ }
13963
+ async function launchBridge(config, common) {
13964
+ const { BridgeDriver: BridgeDriver2 } = await Promise.resolve().then(() => (init_bridge_client(), exports_bridge_client));
13965
+ const bridge = new BridgeDriver2({ maxConsoleLineChars: config.maxConsoleLineChars });
13966
+ await bridge.launch(common);
13967
+ return bridge;
13968
+ }
13969
+ var DIRECT_LAUNCH_TIMEOUT_MS = 8000;
13970
+ var init_driver = __esm(() => {
13971
+ init_session();
13972
+ });
13973
+
13974
+ // src/modules/browser/types.ts
13975
+ var DEFAULT_BROWSER_CONFIG;
13976
+ var init_types = __esm(() => {
13977
+ DEFAULT_BROWSER_CONFIG = {
13978
+ headless: true,
13979
+ maxElements: 30,
13980
+ maxContentChars: 2500,
13981
+ maxConsoleEntries: 40,
13982
+ maxConsoleLineChars: 400,
13983
+ screenshotMaxWidth: 1280,
13984
+ cookieDir: "",
13985
+ viewportWidth: 1280,
13986
+ viewportHeight: 720,
13987
+ navigationTimeout: 15000
13988
+ };
13989
+ });
13990
+
13663
13991
  // src/modules/browser/snapshot.ts
13664
13992
  function inferRole(tag, type) {
13665
13993
  const t2 = tag.toLowerCase();
@@ -13747,35 +14075,69 @@ function extractInteractiveElements(html, maxElements = 30) {
13747
14075
  }
13748
14076
  return elements;
13749
14077
  }
13750
- function formatSnapshot(snapshot) {
14078
+ function truncateText(text, maxChars) {
14079
+ if (maxChars <= 0)
14080
+ return "";
14081
+ if (text.length <= maxChars)
14082
+ return text;
14083
+ const cut = text.slice(0, maxChars);
14084
+ const lastNewline = cut.lastIndexOf(`
14085
+ `);
14086
+ const safe = lastNewline > maxChars * 0.6 ? cut.slice(0, lastNewline) : cut;
14087
+ return `${safe}
14088
+ ${t("browser.truncated")}`;
14089
+ }
14090
+ function formatSnapshot(snapshot, maxContentChars = DEFAULT_BROWSER_CONFIG.maxContentChars) {
13751
14091
  const lines = [];
13752
14092
  lines.push(`Page: "${snapshot.title}"`);
13753
14093
  lines.push(`URL: ${snapshot.url}`);
13754
14094
  lines.push("");
13755
14095
  if (snapshot.elements.length === 0 && !snapshot.truncated) {
13756
14096
  lines.push(t("browser.no_elements"));
13757
- return lines.join(`
13758
- `);
14097
+ } else {
14098
+ for (const el of snapshot.elements) {
14099
+ let line = `[${el.index}] ${el.role}`;
14100
+ if (el.name)
14101
+ line += ` "${el.name}"`;
14102
+ if (el.href)
14103
+ line += ` → ${el.href}`;
14104
+ if (el.value)
14105
+ line += ` = "${el.value}"`;
14106
+ lines.push(line);
14107
+ }
14108
+ if (snapshot.truncated) {
14109
+ lines.push("");
14110
+ lines.push(t("browser.more_elements"));
14111
+ }
14112
+ }
14113
+ if (snapshot.content) {
14114
+ lines.push("");
14115
+ lines.push(t("browser.content_header"));
14116
+ for (const line of truncateText(snapshot.content, maxContentChars).split(`
14117
+ `)) {
14118
+ lines.push(`- ${line}`);
14119
+ }
14120
+ }
14121
+ if (snapshot.console.length > 0) {
14122
+ lines.push("");
14123
+ lines.push(t("browser.console_header"));
14124
+ for (const entry of snapshot.console) {
14125
+ lines.push(`[${entry.type}] ${entry.text}`);
14126
+ }
13759
14127
  }
13760
- for (const el of snapshot.elements) {
13761
- let line = `[${el.index}] ${el.role}`;
13762
- if (el.name)
13763
- line += ` "${el.name}"`;
13764
- if (el.href)
13765
- line += ` → ${el.href}`;
13766
- if (el.value)
13767
- line += ` = "${el.value}"`;
13768
- lines.push(line);
13769
- }
13770
- if (snapshot.truncated) {
14128
+ if (snapshot.networkErrors.length > 0) {
13771
14129
  lines.push("");
13772
- lines.push(t("browser.more_elements"));
14130
+ lines.push(t("browser.network_errors_header"));
14131
+ for (const err of snapshot.networkErrors) {
14132
+ lines.push(`${err.method} ${err.url} → ${err.error}`);
14133
+ }
13773
14134
  }
13774
14135
  return lines.join(`
13775
14136
  `);
13776
14137
  }
13777
14138
  var init_snapshot = __esm(() => {
13778
14139
  init_i18n();
14140
+ init_types();
13779
14141
  });
13780
14142
 
13781
14143
  // src/modules/browser/actions.ts
@@ -13822,18 +14184,48 @@ function buildIndexInjectionScript() {
13822
14184
  });
13823
14185
  `;
13824
14186
  }
14187
+ function buildTextExtractionScript() {
14188
+ return `
14189
+ const contentTags = new Set(['h1','h2','h3','h4','h5','h6','p','li','article','main','section','blockquote','pre','td','th','dt','dd','figcaption']);
14190
+ const out = [];
14191
+ const seen = new Set();
14192
+ const isHidden = (el) => {
14193
+ const st = window.getComputedStyle(el);
14194
+ return st.display === 'none' || st.visibility === 'hidden';
14195
+ };
14196
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
14197
+ acceptNode: (node) => {
14198
+ const tag = node.tagName ? node.tagName.toLowerCase() : '';
14199
+ if (!contentTags.has(tag)) return NodeFilter.FILTER_SKIP;
14200
+ if (isHidden(node)) return NodeFilter.FILTER_REJECT;
14201
+ return NodeFilter.FILTER_ACCEPT;
14202
+ }
14203
+ });
14204
+ let node;
14205
+ while ((node = walker.nextNode())) {
14206
+ const tag = node.tagName.toLowerCase();
14207
+ const text = (node.textContent || '').replace(/\\s+/g, ' ').trim();
14208
+ if (!text) continue;
14209
+ if (seen.has(text)) continue;
14210
+ seen.add(text);
14211
+ const line = text.length > 200 ? text.slice(0, 200) + '…' : text;
14212
+ out.push('[' + tag + '] ' + line);
14213
+ }
14214
+ return out.join('\\n');
14215
+ `;
14216
+ }
13825
14217
 
13826
14218
  // src/modules/browser/cookie-store.ts
13827
14219
  import { readFile, writeFile, mkdir } from "fs/promises";
13828
- import { join as join17 } from "path";
14220
+ import { join as join18 } from "path";
13829
14221
 
13830
14222
  class CookieStore {
13831
14223
  filePath;
13832
14224
  constructor(cookieDir) {
13833
- this.filePath = join17(cookieDir, "cookies.json");
14225
+ this.filePath = join18(cookieDir, "cookies.json");
13834
14226
  }
13835
14227
  async save(cookies) {
13836
- await mkdir(join17(this.filePath, ".."), { recursive: true });
14228
+ await mkdir(join18(this.filePath, ".."), { recursive: true });
13837
14229
  await writeFile(this.filePath, JSON.stringify(cookies, null, 2), "utf-8");
13838
14230
  }
13839
14231
  async load() {
@@ -13851,9 +14243,32 @@ class CookieStore {
13851
14243
  var init_cookie_store = () => {};
13852
14244
 
13853
14245
  // src/modules/browser/session.ts
13854
- import {
13855
- chromium
13856
- } from "playwright";
14246
+ class ConsoleBuffer {
14247
+ entries = [];
14248
+ maxEntries;
14249
+ constructor(maxEntries = 20) {
14250
+ this.maxEntries = maxEntries;
14251
+ }
14252
+ add(type, text) {
14253
+ const clean = String(text).replace(/\s+/g, " ").trim();
14254
+ if (!clean)
14255
+ return;
14256
+ const line = clean.length > CONSOLE_MAX_LINE ? clean.slice(0, CONSOLE_MAX_LINE) + "…" : clean;
14257
+ this.entries.push({ type, text: line });
14258
+ if (this.entries.length > this.maxEntries) {
14259
+ this.entries.splice(0, this.entries.length - this.maxEntries);
14260
+ }
14261
+ }
14262
+ clear() {
14263
+ this.entries = [];
14264
+ }
14265
+ getAll() {
14266
+ return [...this.entries];
14267
+ }
14268
+ get size() {
14269
+ return this.entries.length;
14270
+ }
14271
+ }
13857
14272
 
13858
14273
  class BrowserActionTracker {
13859
14274
  history = [];
@@ -13881,9 +14296,7 @@ class BrowserActionTracker {
13881
14296
  }
13882
14297
 
13883
14298
  class BrowserSession {
13884
- browser = null;
13885
- context = null;
13886
- page = null;
14299
+ driver = null;
13887
14300
  config;
13888
14301
  cookieStore;
13889
14302
  state = {
@@ -13941,7 +14354,7 @@ class BrowserSession {
13941
14354
  };
13942
14355
  }
13943
14356
  if (action !== "open") {
13944
- const warning = this.actionTracker.record(action, args, this.page?.url() || "");
14357
+ const warning = this.actionTracker.record(action, args, this.driver?.url() || "");
13945
14358
  if (warning && result.success) {
13946
14359
  result.output = result.output + `
13947
14360
 
@@ -13956,45 +14369,40 @@ class BrowserSession {
13956
14369
  };
13957
14370
  }
13958
14371
  }
13959
- async ensurePage() {
13960
- if (!this.page) {
14372
+ async ensureDriver() {
14373
+ if (!this.driver) {
13961
14374
  return { success: false, output: t("browser.no_page") };
13962
14375
  }
13963
14376
  return null;
13964
14377
  }
13965
14378
  async launch() {
13966
- if (this.browser)
14379
+ if (this.driver)
13967
14380
  return;
13968
- this.browser = await chromium.launch({ headless: this.config.headless });
13969
- this.context = await this.browser.newContext({
13970
- viewport: {
13971
- width: this.config.viewportWidth,
13972
- height: this.config.viewportHeight
13973
- }
13974
- });
14381
+ this.driver = await createBrowserDriver(this.config);
13975
14382
  const savedCookies = await this.cookieStore.load();
13976
14383
  if (savedCookies.length > 0) {
13977
- await this.context.addCookies(savedCookies.map((c) => ({
13978
- ...c,
13979
- sameSite: c.sameSite
13980
- })));
14384
+ await this.driver.addCookies(savedCookies);
13981
14385
  }
13982
- this.page = await this.context.newPage();
13983
- this.page.setDefaultTimeout(this.config.navigationTimeout);
13984
14386
  }
13985
14387
  async saveCookies() {
13986
- if (!this.context)
14388
+ if (!this.driver)
13987
14389
  return;
13988
- const cookies = await this.context.cookies();
14390
+ const cookies = await this.driver.cookies();
13989
14391
  await this.cookieStore.save(cookies);
13990
14392
  }
13991
14393
  async takeSnapshot() {
13992
- if (!this.page)
14394
+ if (!this.driver)
13993
14395
  return "No page open.";
13994
- await this.page.evaluate(buildIndexInjectionScript());
13995
- const html = await this.page.content();
13996
- const url = this.page.url();
13997
- const title = await this.page.title();
14396
+ await this.driver.evaluate(buildIndexInjectionScript());
14397
+ const html = await this.driver.content();
14398
+ const url = this.driver.url();
14399
+ const title = await this.driver.title();
14400
+ let content = "";
14401
+ try {
14402
+ content = String(await this.driver.evaluate(buildTextExtractionScript()));
14403
+ } catch {
14404
+ content = "";
14405
+ }
13998
14406
  const allElements = extractInteractiveElements(html, this.config.maxElements + 5);
13999
14407
  const truncated = allElements.length > this.config.maxElements;
14000
14408
  const elements = allElements.slice(0, this.config.maxElements);
@@ -14004,7 +14412,15 @@ class BrowserSession {
14004
14412
  title,
14005
14413
  elementCount: elements.length
14006
14414
  };
14007
- return formatSnapshot({ url, title, elements, truncated });
14415
+ return formatSnapshot({
14416
+ url,
14417
+ title,
14418
+ elements,
14419
+ content,
14420
+ console: this.driver.getConsole(),
14421
+ networkErrors: this.driver.getNetworkErrors(),
14422
+ truncated
14423
+ });
14008
14424
  }
14009
14425
  async open(url) {
14010
14426
  if (!url)
@@ -14014,14 +14430,12 @@ class BrowserSession {
14014
14430
  url = isLocalhost ? "http://" + url : "https://" + url;
14015
14431
  }
14016
14432
  await this.launch();
14017
- if (!this.page)
14433
+ if (!this.driver)
14018
14434
  return { success: false, output: t("browser.create_page_failed") };
14019
14435
  this.actionTracker.reset();
14436
+ this.driver.resetEventLog();
14020
14437
  try {
14021
- await this.page.goto(url, {
14022
- waitUntil: "domcontentloaded",
14023
- timeout: this.config.navigationTimeout
14024
- });
14438
+ await this.driver.goto(url, this.config.navigationTimeout);
14025
14439
  } catch (err) {
14026
14440
  return {
14027
14441
  success: false,
@@ -14033,18 +14447,17 @@ class BrowserSession {
14033
14447
  return { success: true, output: snapshot };
14034
14448
  }
14035
14449
  async click(target) {
14036
- const err = await this.ensurePage();
14450
+ const err = await this.ensureDriver();
14037
14451
  if (err)
14038
14452
  return err;
14039
- if (!this.page)
14453
+ if (!this.driver)
14040
14454
  return { success: false, output: "No page" };
14041
14455
  if (!target || target < 1) {
14042
14456
  return { success: false, output: t("browser.invalid_target") };
14043
14457
  }
14044
14458
  try {
14045
- const script = buildClickScript(target);
14046
- await this.page.evaluate(script);
14047
- await this.page.waitForLoadState("domcontentloaded", { timeout: 5000 }).catch(() => {});
14459
+ await this.driver.evaluate(buildClickScript(target));
14460
+ await this.driver.waitForLoad(5000);
14048
14461
  await new Promise((r) => setTimeout(r, 500));
14049
14462
  const snapshot = await this.takeSnapshot();
14050
14463
  await this.saveCookies();
@@ -14057,10 +14470,10 @@ class BrowserSession {
14057
14470
  }
14058
14471
  }
14059
14472
  async type(target, text) {
14060
- const err = await this.ensurePage();
14473
+ const err = await this.ensureDriver();
14061
14474
  if (err)
14062
14475
  return err;
14063
- if (!this.page)
14476
+ if (!this.driver)
14064
14477
  return { success: false, output: "No page" };
14065
14478
  if (!target || target < 1) {
14066
14479
  return { success: false, output: t("browser.invalid_target_short") };
@@ -14069,8 +14482,7 @@ class BrowserSession {
14069
14482
  return { success: false, output: t("browser.text_required") };
14070
14483
  }
14071
14484
  try {
14072
- const script = buildTypeScript(target, text);
14073
- await this.page.evaluate(script);
14485
+ await this.driver.evaluate(buildTypeScript(target, text));
14074
14486
  const snapshot = await this.takeSnapshot();
14075
14487
  return { success: true, output: snapshot };
14076
14488
  } catch (err2) {
@@ -14081,17 +14493,17 @@ class BrowserSession {
14081
14493
  }
14082
14494
  }
14083
14495
  async scroll(direction) {
14084
- const err = await this.ensurePage();
14496
+ const err = await this.ensureDriver();
14085
14497
  if (err)
14086
14498
  return err;
14087
- if (!this.page)
14499
+ if (!this.driver)
14088
14500
  return { success: false, output: "No page" };
14089
14501
  const dir = direction;
14090
14502
  if (!["up", "down", "top", "bottom"].includes(dir)) {
14091
14503
  return { success: false, output: t("browser.direction_invalid") };
14092
14504
  }
14093
14505
  try {
14094
- await this.page.evaluate(buildScrollScript(dir));
14506
+ await this.driver.evaluate(buildScrollScript(dir));
14095
14507
  await new Promise((r) => setTimeout(r, 300));
14096
14508
  const snapshot = await this.takeSnapshot();
14097
14509
  return { success: true, output: snapshot };
@@ -14103,52 +14515,46 @@ class BrowserSession {
14103
14515
  }
14104
14516
  }
14105
14517
  async back() {
14106
- const err = await this.ensurePage();
14518
+ const err = await this.ensureDriver();
14107
14519
  if (err)
14108
14520
  return err;
14109
- if (!this.page)
14521
+ if (!this.driver)
14110
14522
  return { success: false, output: "No page" };
14111
- await this.page.goBack({
14112
- waitUntil: "domcontentloaded",
14113
- timeout: this.config.navigationTimeout
14114
- }).catch(() => {});
14523
+ await this.driver.goBack(this.config.navigationTimeout);
14115
14524
  await new Promise((r) => setTimeout(r, 300));
14116
14525
  const snapshot = await this.takeSnapshot();
14117
14526
  return { success: true, output: snapshot };
14118
14527
  }
14119
14528
  async forward() {
14120
- const err = await this.ensurePage();
14529
+ const err = await this.ensureDriver();
14121
14530
  if (err)
14122
14531
  return err;
14123
- if (!this.page)
14532
+ if (!this.driver)
14124
14533
  return { success: false, output: "No page" };
14125
- await this.page.goForward({
14126
- waitUntil: "domcontentloaded",
14127
- timeout: this.config.navigationTimeout
14128
- }).catch(() => {});
14534
+ await this.driver.goForward(this.config.navigationTimeout);
14129
14535
  await new Promise((r) => setTimeout(r, 300));
14130
14536
  const snapshot = await this.takeSnapshot();
14131
14537
  return { success: true, output: snapshot };
14132
14538
  }
14133
14539
  async screenshot() {
14134
- const err = await this.ensurePage();
14540
+ const err = await this.ensureDriver();
14135
14541
  if (err)
14136
14542
  return err;
14137
- if (!this.page)
14543
+ if (!this.driver)
14138
14544
  return { success: false, output: "No page" };
14139
- const buffer = await this.page.screenshot({ type: "png", fullPage: false });
14545
+ const buffer = await this.driver.screenshot();
14140
14546
  const snapshot = await this.takeSnapshot();
14141
14547
  return { success: true, output: snapshot, screenshot: buffer };
14142
14548
  }
14143
14549
  async snapshot() {
14144
- const err = await this.ensurePage();
14550
+ const err = await this.ensureDriver();
14145
14551
  if (err)
14146
14552
  return err;
14147
14553
  const snap = await this.takeSnapshot();
14148
14554
  return { success: true, output: snap };
14149
14555
  }
14150
14556
  async wait(ms) {
14151
- const err = await this.ensurePage();
14557
+ const err = await this.ensureDriver();
14152
14558
  if (err)
14153
14559
  return err;
14154
14560
  await new Promise((r) => setTimeout(r, Math.min(ms, 1e4)));
@@ -14157,51 +14563,34 @@ class BrowserSession {
14157
14563
  }
14158
14564
  async close() {
14159
14565
  await this.saveCookies();
14160
- if (this.page) {
14161
- await this.page.close().catch(() => {});
14162
- this.page = null;
14163
- }
14164
- if (this.context) {
14165
- await this.context.close().catch(() => {});
14166
- this.context = null;
14167
- }
14168
- if (this.browser) {
14169
- await this.browser.close().catch(() => {});
14170
- this.browser = null;
14566
+ if (this.driver) {
14567
+ await this.driver.close();
14568
+ this.driver = null;
14171
14569
  }
14172
14570
  this.state = { isOpen: false, url: null, title: null, elementCount: 0 };
14173
14571
  return { success: true, output: t("browser.closed") };
14174
14572
  }
14175
14573
  }
14574
+ var CONSOLE_MAX_LINE = 400;
14176
14575
  var init_session = __esm(() => {
14576
+ init_driver();
14177
14577
  init_snapshot();
14178
14578
  init_cookie_store();
14179
14579
  init_i18n();
14180
14580
  });
14181
14581
 
14182
- // src/modules/browser/types.ts
14183
- var DEFAULT_BROWSER_CONFIG;
14184
- var init_types = __esm(() => {
14185
- DEFAULT_BROWSER_CONFIG = {
14186
- headless: true,
14187
- maxElements: 30,
14188
- screenshotMaxWidth: 1280,
14189
- cookieDir: "",
14190
- viewportWidth: 1280,
14191
- viewportHeight: 720,
14192
- navigationTimeout: 15000
14193
- };
14194
- });
14195
-
14196
14582
  // src/tools/browser.ts
14197
- import { join as join18 } from "path";
14583
+ import { join as join19 } from "path";
14198
14584
  function getSession(ctx) {
14199
14585
  if (!session) {
14200
- const cookieDir = join18(ctx.baseDir, ".mma", "browser");
14586
+ const cookieDir = join19(ctx.baseDir, ".mma", "browser");
14201
14587
  session = new BrowserSession({
14202
14588
  ...DEFAULT_BROWSER_CONFIG,
14203
14589
  headless: ctx.config.browser?.headless ?? true,
14204
14590
  maxElements: ctx.config.browser?.maxElements ?? 30,
14591
+ maxContentChars: ctx.config.browser?.maxContentChars ?? 2500,
14592
+ maxConsoleEntries: ctx.config.browser?.maxConsoleEntries ?? 40,
14593
+ maxConsoleLineChars: ctx.config.browser?.maxConsoleLineChars ?? 400,
14205
14594
  navigationTimeout: ctx.config.browser?.navigationTimeout ?? 15000,
14206
14595
  viewportWidth: ctx.config.browser?.viewportWidth ?? 1280,
14207
14596
  viewportHeight: ctx.config.browser?.viewportHeight ?? 720,
@@ -14230,7 +14619,8 @@ function createBrowserTool() {
14230
14619
  tags: ["browser", "vision"],
14231
14620
  description: [
14232
14621
  "Control a headless browser. Navigate pages, click elements, type text, scroll, take screenshots.",
14233
- "Returns a numbered list of interactive elements use element numbers as targets for click/type.",
14622
+ "Each snapshot returns: a numbered list of interactive elements, the visible page text (Content section), browser console messages, and network errors.",
14623
+ "Use the Content section to understand what the page says; use element numbers as targets for click/type.",
14234
14624
  "Actions: open (url), click (target), type (target, text), scroll (direction), back, forward, screenshot, snapshot, close, wait (ms)."
14235
14625
  ].join(" "),
14236
14626
  parameters: {
@@ -14327,8 +14717,8 @@ async function readClipboardFallback() {
14327
14717
  const { platform: platform3 } = await import("os");
14328
14718
  const { execSync } = await import("child_process");
14329
14719
  const { readFileSync: readFileSync15, unlinkSync: unlinkSync4 } = await import("fs");
14330
- const { join: join19 } = await import("path");
14331
- const tmpPath = join19(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
14720
+ const { join: join20 } = await import("path");
14721
+ const tmpPath = join20(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
14332
14722
  try {
14333
14723
  if (platform3() === "linux") {
14334
14724
  execSync(`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`, { timeout: 5000 });
@@ -14608,7 +14998,7 @@ class ModuleRegistry {
14608
14998
 
14609
14999
  // src/modules/plugins/loader.ts
14610
15000
  import { readdirSync as readdirSync7, existsSync as existsSync25, statSync as statSync5 } from "fs";
14611
- import { join as join19 } from "path";
15001
+ import { join as join20 } from "path";
14612
15002
 
14613
15003
  class PluginLoader {
14614
15004
  loadFromDir(dirPath, pluginManager, logger) {
@@ -14616,7 +15006,7 @@ class PluginLoader {
14616
15006
  return;
14617
15007
  const entries = readdirSync7(dirPath);
14618
15008
  for (const entry of entries) {
14619
- const fullPath = join19(dirPath, entry);
15009
+ const fullPath = join20(dirPath, entry);
14620
15010
  if (!statSync5(fullPath).isFile())
14621
15011
  continue;
14622
15012
  if (!entry.endsWith(".ts") && !entry.endsWith(".js"))
@@ -14639,9 +15029,9 @@ var init_loader = __esm(() => {
14639
15029
  });
14640
15030
 
14641
15031
  // src/modules/plugins/builtin/lint-on-write.ts
14642
- import { spawn as spawn4, execSync } from "child_process";
15032
+ import { spawn as spawn5, execSync } from "child_process";
14643
15033
  import { existsSync as existsSync26, readFileSync as readFileSync15 } from "fs";
14644
- import { resolve as resolve16, extname as extname4, join as join20 } from "path";
15034
+ import { resolve as resolve16, extname as extname4, join as join21 } from "path";
14645
15035
  import { platform as platform3 } from "os";
14646
15036
  function contentHash(content) {
14647
15037
  let h = 5381;
@@ -14743,7 +15133,7 @@ class LintOnWritePlugin {
14743
15133
  }
14744
15134
  async runProjectLint(ctx, result) {
14745
15135
  try {
14746
- const packageJsonPath = join20(ctx.baseDir, "package.json");
15136
+ const packageJsonPath = join21(ctx.baseDir, "package.json");
14747
15137
  if (!existsSync26(packageJsonPath)) {
14748
15138
  return;
14749
15139
  }
@@ -14763,7 +15153,7 @@ class LintOnWritePlugin {
14763
15153
  }
14764
15154
  }
14765
15155
  async runProjectTypeCheck(ctx, result) {
14766
- const tsconfigPath = join20(ctx.baseDir, "tsconfig.json");
15156
+ const tsconfigPath = join21(ctx.baseDir, "tsconfig.json");
14767
15157
  if (!existsSync26(tsconfigPath)) {
14768
15158
  return;
14769
15159
  }
@@ -14806,7 +15196,7 @@ class LintOnWritePlugin {
14806
15196
  }
14807
15197
  function runAsync(command, cwd, timeoutMs) {
14808
15198
  return new Promise((resolve17, reject) => {
14809
- const child = spawn4(command, {
15199
+ const child = spawn5(command, {
14810
15200
  cwd,
14811
15201
  shell: true,
14812
15202
  windowsHide: true,
@@ -15007,7 +15397,7 @@ var init_tracker = () => {};
15007
15397
 
15008
15398
  // src/modules/execution/auditor.ts
15009
15399
  import { existsSync as existsSync27, readdirSync as readdirSync8 } from "fs";
15010
- import { resolve as resolve17, join as join21 } from "path";
15400
+ import { resolve as resolve17, join as join22 } from "path";
15011
15401
  function findTestFile(dir, depth = 0) {
15012
15402
  if (depth > 5)
15013
15403
  return null;
@@ -15018,7 +15408,7 @@ function findTestFile(dir, depth = 0) {
15018
15408
  return null;
15019
15409
  }
15020
15410
  for (const e of entries) {
15021
- const full = join21(dir, e.name);
15411
+ const full = join22(dir, e.name);
15022
15412
  if (e.isDirectory()) {
15023
15413
  if (SKIP_DIRS.has(e.name))
15024
15414
  continue;
@@ -15178,7 +15568,7 @@ var init_auditor = __esm(() => {
15178
15568
 
15179
15569
  // src/modules/execution/plan-store.ts
15180
15570
  import { readFileSync as readFileSync16, writeFileSync as writeFileSync9, mkdirSync as mkdirSync13, existsSync as existsSync28, readdirSync as readdirSync9, rmSync } from "fs";
15181
- import { join as join22 } from "path";
15571
+ import { join as join23 } from "path";
15182
15572
  function readPlanFile(path, fallbackBaseDir) {
15183
15573
  try {
15184
15574
  const raw = readFileSync16(path, "utf-8");
@@ -15206,7 +15596,7 @@ function listDir(dir, baseDir) {
15206
15596
  if (!existsSync28(dir))
15207
15597
  return [];
15208
15598
  const files = readdirSync9(dir).filter((f) => f.endsWith(".json"));
15209
- return files.map((f) => readPlanFile(join22(dir, f), baseDir)).filter((p) => p !== null);
15599
+ return files.map((f) => readPlanFile(join23(dir, f), baseDir)).filter((p) => p !== null);
15210
15600
  }
15211
15601
  function toMeta(plan, status) {
15212
15602
  return {
@@ -15227,21 +15617,21 @@ class PlanStore {
15227
15617
  archiveDir;
15228
15618
  legacyPath;
15229
15619
  constructor(baseDir) {
15230
- const mmaDir = join22(baseDir, ".mma");
15620
+ const mmaDir = join23(baseDir, ".mma");
15231
15621
  if (!existsSync28(mmaDir))
15232
15622
  mkdirSync13(mmaDir, { recursive: true });
15233
15623
  this.baseDir = baseDir;
15234
- this.plansDir = join22(mmaDir, "plans");
15235
- this.draftsDir = join22(this.plansDir, "drafts");
15236
- this.archiveDir = join22(this.plansDir, "archive");
15237
- this.legacyPath = join22(mmaDir, LEGACY_FILE);
15624
+ this.plansDir = join23(mmaDir, "plans");
15625
+ this.draftsDir = join23(this.plansDir, "drafts");
15626
+ this.archiveDir = join23(this.plansDir, "archive");
15627
+ this.legacyPath = join23(mmaDir, LEGACY_FILE);
15238
15628
  for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
15239
15629
  if (!existsSync28(dir))
15240
15630
  mkdirSync13(dir, { recursive: true });
15241
15631
  }
15242
15632
  }
15243
15633
  activePath() {
15244
- return join22(this.plansDir, "active.json");
15634
+ return join23(this.plansDir, "active.json");
15245
15635
  }
15246
15636
  saveActive(plan) {
15247
15637
  writePlanFile(this.activePath(), plan);
@@ -15271,14 +15661,14 @@ class PlanStore {
15271
15661
  rmSync(p, { force: true });
15272
15662
  }
15273
15663
  saveDraft(plan) {
15274
- writePlanFile(join22(this.draftsDir, `${plan.id}.json`), plan);
15664
+ writePlanFile(join23(this.draftsDir, `${plan.id}.json`), plan);
15275
15665
  }
15276
15666
  loadDraft(id) {
15277
- const p = join22(this.draftsDir, `${id}.json`);
15667
+ const p = join23(this.draftsDir, `${id}.json`);
15278
15668
  return existsSync28(p) ? readPlanFile(p, this.baseDir) : null;
15279
15669
  }
15280
15670
  removeDraft(id) {
15281
- const p = join22(this.draftsDir, `${id}.json`);
15671
+ const p = join23(this.draftsDir, `${id}.json`);
15282
15672
  if (existsSync28(p))
15283
15673
  rmSync(p, { force: true });
15284
15674
  }
@@ -15286,7 +15676,7 @@ class PlanStore {
15286
15676
  return listDir(this.draftsDir, this.baseDir);
15287
15677
  }
15288
15678
  archivePlan(plan) {
15289
- writePlanFile(join22(this.archiveDir, `${plan.id}.json`), plan);
15679
+ writePlanFile(join23(this.archiveDir, `${plan.id}.json`), plan);
15290
15680
  this.removeDraft(plan.id);
15291
15681
  const active = this.loadActive();
15292
15682
  if (active && active.id === plan.id) {
@@ -15297,7 +15687,7 @@ class PlanStore {
15297
15687
  return listDir(this.archiveDir, this.baseDir);
15298
15688
  }
15299
15689
  removeArchived(id) {
15300
- const p = join22(this.archiveDir, `${id}.json`);
15690
+ const p = join23(this.archiveDir, `${id}.json`);
15301
15691
  if (existsSync28(p))
15302
15692
  rmSync(p, { force: true });
15303
15693
  }
@@ -16164,7 +16554,7 @@ import {
16164
16554
  readdirSync as readdirSync10,
16165
16555
  unlinkSync as unlinkSync4
16166
16556
  } from "fs";
16167
- import { join as join23 } from "path";
16557
+ import { join as join24 } from "path";
16168
16558
  import { homedir as homedir8 } from "os";
16169
16559
 
16170
16560
  class SessionFileEncryptor {
@@ -16173,7 +16563,7 @@ class SessionFileEncryptor {
16173
16563
  constructor(config) {
16174
16564
  this.config = { ...DEFAULT_SESSION_ENCRYPTION, ...config };
16175
16565
  this.encryptor = new ConfigEncryptor({
16176
- keyPath: config?.keyPath || join23(homedir8(), ".mma", ".session-encryption-key")
16566
+ keyPath: config?.keyPath || join24(homedir8(), ".mma", ".session-encryption-key")
16177
16567
  });
16178
16568
  }
16179
16569
  isEnabled() {
@@ -16259,7 +16649,7 @@ class SessionFileEncryptor {
16259
16649
  return;
16260
16650
  const files = readdirSync10(sessionDir);
16261
16651
  for (const file of files) {
16262
- const filePath = join23(sessionDir, file);
16652
+ const filePath = join24(sessionDir, file);
16263
16653
  if (existsSync30(filePath) && !file.endsWith(".enc")) {
16264
16654
  try {
16265
16655
  const content = readFileSync18(filePath, "utf8");
@@ -16276,7 +16666,7 @@ class SessionFileEncryptor {
16276
16666
  const files = readdirSync10(sessionDir);
16277
16667
  for (const file of files) {
16278
16668
  if (file.endsWith(".enc")) {
16279
- const encFilePath = join23(sessionDir, file);
16669
+ const encFilePath = join24(sessionDir, file);
16280
16670
  const decFilePath = encFilePath.slice(0, -4);
16281
16671
  try {
16282
16672
  const content = readFileSync18(encFilePath, "utf8");
@@ -16309,7 +16699,7 @@ import {
16309
16699
  writeFileSync as writeFileSync11,
16310
16700
  appendFileSync as appendFileSync6
16311
16701
  } from "fs";
16312
- import { join as join24 } from "path";
16702
+ import { join as join25 } from "path";
16313
16703
  import { gzipSync } from "zlib";
16314
16704
 
16315
16705
  class SessionStore {
@@ -16323,7 +16713,7 @@ class SessionStore {
16323
16713
  }
16324
16714
  }
16325
16715
  getSessionDir(id) {
16326
- return join24(this.baseDir, id);
16716
+ return join25(this.baseDir, id);
16327
16717
  }
16328
16718
  updateEncryption(config) {
16329
16719
  if (config?.enabled) {
@@ -16339,16 +16729,16 @@ class SessionStore {
16339
16729
  mkdirSync14(this.baseDir, { recursive: true });
16340
16730
  }
16341
16731
  sessionDir(id) {
16342
- return join24(this.baseDir, id);
16732
+ return join25(this.baseDir, id);
16343
16733
  }
16344
16734
  metaPath(id) {
16345
- return join24(this.sessionDir(id), "meta.json");
16735
+ return join25(this.sessionDir(id), "meta.json");
16346
16736
  }
16347
16737
  historyPath(id) {
16348
- return join24(this.sessionDir(id), "history.jsonl");
16738
+ return join25(this.sessionDir(id), "history.jsonl");
16349
16739
  }
16350
16740
  sessionLogPath(id) {
16351
- return join24(this.sessionDir(id), "session.jsonl");
16741
+ return join25(this.sessionDir(id), "session.jsonl");
16352
16742
  }
16353
16743
  sessionExists(id) {
16354
16744
  return existsSync31(this.metaPath(id));
@@ -16502,7 +16892,7 @@ class SessionStore {
16502
16892
  if (existsSync31(historyPath)) {
16503
16893
  const content = readFileSync19(historyPath, "utf-8");
16504
16894
  const compressed = gzipSync(content);
16505
- const gzPath = join24(this.baseDir, `${session2.id}.jsonl.gz`);
16895
+ const gzPath = join25(this.baseDir, `${session2.id}.jsonl.gz`);
16506
16896
  writeFileSync11(gzPath, compressed);
16507
16897
  rmSync2(historyPath);
16508
16898
  }
@@ -16713,7 +17103,7 @@ class ProfileCompressor {
16713
17103
 
16714
17104
  // src/modules/user-profile/profile.ts
16715
17105
  import { readFileSync as readFileSync20, writeFileSync as writeFileSync12, existsSync as existsSync32, mkdirSync as mkdirSync15 } from "fs";
16716
- import { join as join25 } from "path";
17106
+ import { join as join26 } from "path";
16717
17107
  import { homedir as homedir9, hostname, platform as platform4, type } from "os";
16718
17108
  import { env } from "process";
16719
17109
 
@@ -16740,10 +17130,10 @@ class UserProfile {
16740
17130
  if (!existsSync32(this.profileDir)) {
16741
17131
  mkdirSync15(this.profileDir, { recursive: true });
16742
17132
  }
16743
- writeFileSync12(join25(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
17133
+ writeFileSync12(join26(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
16744
17134
  }
16745
17135
  load() {
16746
- const path = join25(this.profileDir, "profile.json");
17136
+ const path = join26(this.profileDir, "profile.json");
16747
17137
  if (!existsSync32(path))
16748
17138
  return null;
16749
17139
  try {
@@ -16783,7 +17173,7 @@ var init_profile = () => {};
16783
17173
 
16784
17174
  // src/modules/skills/loader.ts
16785
17175
  import { readdirSync as readdirSync12, readFileSync as readFileSync21, existsSync as existsSync33, statSync as statSync6 } from "fs";
16786
- import { join as join26 } from "path";
17176
+ import { join as join27 } from "path";
16787
17177
 
16788
17178
  class SkillsLoader {
16789
17179
  loadFromDir(dirPath) {
@@ -16796,7 +17186,7 @@ class SkillsLoader {
16796
17186
  scanDir(dirPath, skills) {
16797
17187
  const entries = readdirSync12(dirPath);
16798
17188
  for (const entry of entries) {
16799
- const fullPath = join26(dirPath, entry);
17189
+ const fullPath = join27(dirPath, entry);
16800
17190
  const stat = statSync6(fullPath);
16801
17191
  if (stat.isDirectory()) {
16802
17192
  this.scanDir(fullPath, skills);
@@ -17002,6 +17392,7 @@ class BrowserModule {
17002
17392
  content: [
17003
17393
  "You have a headless browser tool. Use it to navigate websites, click links, fill forms, and read page content.",
17004
17394
  "Workflow: open(url) → read snapshot → click/type on element numbers → read updated snapshot.",
17395
+ '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.',
17005
17396
  'Always start with "open" action. Use element numbers from snapshot for click/type targets.',
17006
17397
  'Use "screenshot" action only if the model supports vision. Otherwise rely on the text snapshot.'
17007
17398
  ].join(`
@@ -17032,12 +17423,14 @@ var init_browser2 = __esm(() => {
17032
17423
  init_module4();
17033
17424
  init_session();
17034
17425
  init_cookie_store();
17426
+ init_driver();
17427
+ init_bridge_client();
17035
17428
  init_snapshot();
17036
17429
  init_types();
17037
17430
  });
17038
17431
 
17039
17432
  // src/modules/lsp/client.ts
17040
- import { spawn as spawn5, execSync as execSync2 } from "child_process";
17433
+ import { spawn as spawn6, execSync as execSync2 } from "child_process";
17041
17434
  import { resolve as resolve19 } from "path";
17042
17435
 
17043
17436
  class LspClient {
@@ -17101,7 +17494,7 @@ class LspClient {
17101
17494
  }
17102
17495
  return new Promise((resolve20, reject) => {
17103
17496
  const args = config.args ?? [];
17104
- const proc = spawn5(config.command, args, {
17497
+ const proc = spawn6(config.command, args, {
17105
17498
  stdio: ["pipe", "pipe", "pipe"],
17106
17499
  env: { ...process.env, ...config.env },
17107
17500
  cwd: baseDir
@@ -17362,7 +17755,7 @@ var init_lsp = __esm(() => {
17362
17755
 
17363
17756
  // src/modules/indexer/walker.ts
17364
17757
  import { readdirSync as readdirSync13, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync35, watch } from "fs";
17365
- import { join as join27, relative as relative2, extname as extname5 } from "path";
17758
+ import { join as join28, relative as relative2, extname as extname5 } from "path";
17366
17759
 
17367
17760
  class Indexer {
17368
17761
  baseDir;
@@ -17400,7 +17793,7 @@ class Indexer {
17400
17793
  for (const entry of entries) {
17401
17794
  if (count >= this.MAX_FILES)
17402
17795
  return;
17403
- const fullPath = join27(dir, entry);
17796
+ const fullPath = join28(dir, entry);
17404
17797
  const relPath = relative2(this.baseDir, fullPath);
17405
17798
  const stat = statSync7(fullPath);
17406
17799
  if (stat.isDirectory()) {
@@ -17464,13 +17857,13 @@ var init_walker = __esm(() => {
17464
17857
 
17465
17858
  // src/modules/indexer/cache.ts
17466
17859
  import { readFileSync as readFileSync23, writeFileSync as writeFileSync13, existsSync as existsSync36, mkdirSync as mkdirSync16, rmSync as rmSync3 } from "fs";
17467
- import { join as join28 } from "path";
17860
+ import { join as join29 } from "path";
17468
17861
 
17469
17862
  class IndexCache {
17470
17863
  cachePath;
17471
17864
  cache = null;
17472
17865
  constructor(cacheDir) {
17473
- this.cachePath = join28(cacheDir, "index-cache.json");
17866
+ this.cachePath = join29(cacheDir, "index-cache.json");
17474
17867
  }
17475
17868
  load() {
17476
17869
  if (this.cache)
@@ -17486,7 +17879,7 @@ class IndexCache {
17486
17879
  }
17487
17880
  save(result) {
17488
17881
  this.cache = result;
17489
- const dir = join28(this.cachePath, "..");
17882
+ const dir = join29(this.cachePath, "..");
17490
17883
  if (!existsSync36(dir))
17491
17884
  mkdirSync16(dir, { recursive: true });
17492
17885
  writeFileSync13(this.cachePath, JSON.stringify(result), "utf-8");
@@ -17503,7 +17896,7 @@ class IndexCache {
17503
17896
  var init_cache = () => {};
17504
17897
 
17505
17898
  // src/modules/indexer/module.ts
17506
- import { dirname as dirname7 } from "path";
17899
+ import { dirname as dirname8 } from "path";
17507
17900
 
17508
17901
  class IndexerModule {
17509
17902
  name = "indexer";
@@ -17620,7 +18013,7 @@ ${t("indexer.and_more", { count: result.files.length - 100 })}` : "";
17620
18013
  const counts = {};
17621
18014
  for (const f of result.files) {
17622
18015
  const normalized = f.path.replace(/\\/g, "/");
17623
- const dir = dirname7(normalized);
18016
+ const dir = dirname8(normalized);
17624
18017
  const key = dir === "." ? "(root)" : dir;
17625
18018
  counts[key] = (counts[key] || 0) + 1;
17626
18019
  }
@@ -17851,13 +18244,13 @@ var init_mcp = __esm(() => {
17851
18244
 
17852
18245
  // src/modules/memory/module.ts
17853
18246
  import { homedir as homedir10 } from "os";
17854
- import { join as join29 } from "path";
18247
+ import { join as join30 } from "path";
17855
18248
 
17856
18249
  class MemoryModule {
17857
18250
  name = "memory";
17858
18251
  store;
17859
18252
  constructor(memoryDir) {
17860
- const dir = memoryDir || join29(homedir10(), ".mma", "memory");
18253
+ const dir = memoryDir || join30(homedir10(), ".mma", "memory");
17861
18254
  this.store = new MemoryStore(dir);
17862
18255
  }
17863
18256
  getSystemPromptBlock() {
@@ -17905,7 +18298,7 @@ __export(exports_bootstrap, {
17905
18298
  bootstrap: () => bootstrap
17906
18299
  });
17907
18300
  import { homedir as homedir11 } from "os";
17908
- import { join as join30, resolve as resolve21 } from "path";
18301
+ import { join as join31, resolve as resolve21 } from "path";
17909
18302
  import { existsSync as existsSync37, readFileSync as readFileSync24, writeFileSync as writeFileSync14 } from "fs";
17910
18303
  function buildSystemInfo(config, baseDir, profileCompressed) {
17911
18304
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
@@ -17931,8 +18324,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
17931
18324
  `);
17932
18325
  }
17933
18326
  async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
17934
- const dir = configDir || join30(homedir11(), ".mma");
17935
- const projectConfigPath = projectDir ? join30(projectDir, ".mmrc") : join30(process.cwd(), ".mmrc");
18327
+ const dir = configDir || join31(homedir11(), ".mma");
18328
+ const projectConfigPath = projectDir ? join31(projectDir, ".mmrc") : join31(process.cwd(), ".mmrc");
17936
18329
  const config = loadConfig({ configDir: dir, projectConfigPath });
17937
18330
  setLocale(config.locale);
17938
18331
  try {
@@ -17942,7 +18335,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
17942
18335
  }
17943
18336
  } catch {}
17944
18337
  const logger = new Logger(config.logLevel);
17945
- logger.setLogDir(join30(dir, "logs"));
18338
+ logger.setLogDir(join31(dir, "logs"));
17946
18339
  logger.debug("MMA bootstrap", {
17947
18340
  version: config.version,
17948
18341
  model: config.model
@@ -17964,7 +18357,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
17964
18357
  logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
17965
18358
  }
17966
18359
  }
17967
- const profile = new UserProfile(join30(dir));
18360
+ const profile = new UserProfile(join31(dir));
17968
18361
  profile.load() || profile.collect();
17969
18362
  profile.save();
17970
18363
  const llmProvider = new OpenAICompatProvider({
@@ -17976,7 +18369,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
17976
18369
  rateLimits: config.security?.rateLimits
17977
18370
  });
17978
18371
  const baseDir = projectDir ? resolve21(projectDir) : process.cwd();
17979
- const projectMapCacheDir = join30(baseDir, ".mma");
18372
+ const projectMapCacheDir = join31(baseDir, ".mma");
17980
18373
  const indexerModule = new IndexerModule({
17981
18374
  baseDir,
17982
18375
  cacheDir: projectMapCacheDir
@@ -17987,9 +18380,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
17987
18380
  logger.warn(`Project indexing failed: ${err.message}`);
17988
18381
  }
17989
18382
  const skillsLoader = new SkillsLoader;
17990
- const builtinDir = join30(import.meta.dirname, "skills", "builtin");
17991
- const globalDir = join30(homedir11(), ".agents", "skills");
17992
- const projectSkillsDir = join30(baseDir, ".mma", "skills");
18383
+ const builtinDir = join31(import.meta.dirname, "skills", "builtin");
18384
+ const globalDir = join31(homedir11(), ".agents", "skills");
18385
+ const projectSkillsDir = join31(baseDir, ".mma", "skills");
17993
18386
  const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
17994
18387
  const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
17995
18388
  const skillsModule = new SkillsModule(availableSkills, skillsBudget);
@@ -18003,11 +18396,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
18003
18396
  essential: true,
18004
18397
  estimatedTokens: Math.ceil(systemInfoContent.length / 4)
18005
18398
  };
18006
- const agentsMdGlobal = join30(dir, "AGENTS.md");
18399
+ const agentsMdGlobal = join31(dir, "AGENTS.md");
18007
18400
  if (!existsSync37(agentsMdGlobal)) {
18008
18401
  writeFileSync14(agentsMdGlobal, "", "utf-8");
18009
18402
  }
18010
- const sessionDir = join30(dir, "sessions");
18403
+ const sessionDir = join31(dir, "sessions");
18011
18404
  const sessionStore = new SessionStore(sessionDir);
18012
18405
  sessionStore.init();
18013
18406
  const sessionManager = new SessionManager(sessionStore, {
@@ -18074,7 +18467,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
18074
18467
  const mcpModule = new MCPModule(config);
18075
18468
  await mcpModule.initialize();
18076
18469
  moduleRegistry.register(mcpModule);
18077
- const memoryModule = new MemoryModule(join30(dir, "memory"));
18470
+ const memoryModule = new MemoryModule(join31(dir, "memory"));
18078
18471
  moduleRegistry.register(memoryModule);
18079
18472
  if (config.browser.enabled) {
18080
18473
  const browserModule = new BrowserModule;
@@ -18124,8 +18517,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
18124
18517
  pluginManager.register(plugin);
18125
18518
  pluginManager.register(plugin2);
18126
18519
  const pluginLoader = new PluginLoader;
18127
- const globalPluginsDir = join30(homedir11(), ".mma", "plugins");
18128
- const projectPluginsDir = join30(baseDir, ".mma", "plugins");
18520
+ const globalPluginsDir = join31(homedir11(), ".mma", "plugins");
18521
+ const projectPluginsDir = join31(baseDir, ".mma", "plugins");
18129
18522
  pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger);
18130
18523
  pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger);
18131
18524
  contextManager.onCompact = (summary) => {
@@ -18143,9 +18536,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
18143
18536
  const skipAgentsMd = noAgentsMd === true;
18144
18537
  if (!skipAgentsMd) {
18145
18538
  const agentsMdCandidates = [
18146
- join30(baseDir, "AGENTS.md"),
18147
- join30(baseDir, ".mma", "AGENTS.md"),
18148
- join30(dir, "AGENTS.md")
18539
+ join31(baseDir, "AGENTS.md"),
18540
+ join31(baseDir, ".mma", "AGENTS.md"),
18541
+ join31(dir, "AGENTS.md")
18149
18542
  ];
18150
18543
  for (const p of agentsMdCandidates) {
18151
18544
  if (existsSync37(p)) {
@@ -19000,7 +19393,7 @@ __export(exports_manifest, {
19000
19393
  });
19001
19394
  import { existsSync as existsSync38, readFileSync as readFileSync25, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15 } from "fs";
19002
19395
  import { homedir as homedir13 } from "os";
19003
- import { join as join32 } from "path";
19396
+ import { join as join33 } from "path";
19004
19397
  function readManifest(path = MANIFEST_PATH) {
19005
19398
  try {
19006
19399
  if (existsSync38(path)) {
@@ -19011,7 +19404,7 @@ function readManifest(path = MANIFEST_PATH) {
19011
19404
  return { version: 1, certifications: [] };
19012
19405
  }
19013
19406
  function saveManifest(m, path = MANIFEST_PATH) {
19014
- mkdirSync17(join32(homedir13(), ".mma"), { recursive: true });
19407
+ mkdirSync17(join33(homedir13(), ".mma"), { recursive: true });
19015
19408
  writeFileSync15(path, JSON.stringify(m, null, 2), "utf-8");
19016
19409
  }
19017
19410
  function upsertCertification(entry, path = MANIFEST_PATH) {
@@ -19046,7 +19439,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
19046
19439
  }
19047
19440
  var MANIFEST_PATH;
19048
19441
  var init_manifest = __esm(() => {
19049
- MANIFEST_PATH = join32(homedir13(), ".mma", "certifications.json");
19442
+ MANIFEST_PATH = join33(homedir13(), ".mma", "certifications.json");
19050
19443
  });
19051
19444
 
19052
19445
  // node_modules/yaml/dist/nodes/identity.js
@@ -26170,7 +26563,7 @@ var init_scenarios = __esm(() => {
26170
26563
 
26171
26564
  // src/modules/certification/loader.ts
26172
26565
  import { existsSync as existsSync39, readdirSync as readdirSync14, readFileSync as readFileSync26 } from "fs";
26173
- import { join as join33 } from "path";
26566
+ import { join as join34 } from "path";
26174
26567
  function validateScenario(s) {
26175
26568
  const errors2 = [];
26176
26569
  const isSkip = s.mode === "skip";
@@ -26224,7 +26617,7 @@ function loadScenarios(userDir) {
26224
26617
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
26225
26618
  continue;
26226
26619
  try {
26227
- const raw = readFileSync26(join33(userDir, file), "utf-8");
26620
+ const raw = readFileSync26(join34(userDir, file), "utf-8");
26228
26621
  const data = $parse(raw);
26229
26622
  const parsed = normalizeScenario(data, file);
26230
26623
  const errs = validateScenario(parsed);
@@ -26278,7 +26671,7 @@ var init_loader3 = __esm(() => {
26278
26671
 
26279
26672
  // src/modules/certification/fact-checker.ts
26280
26673
  import { existsSync as existsSync40, readFileSync as readFileSync27, statSync as statSync8 } from "fs";
26281
- import { join as join34 } from "path";
26674
+ import { join as join35 } from "path";
26282
26675
  function checkSandbox(sandboxDir, checks, exitCode, output) {
26283
26676
  const failures = [];
26284
26677
  for (const check of checks) {
@@ -26295,13 +26688,13 @@ function runCheck(sandboxDir, check, exitCode, output) {
26295
26688
  case "outputContains":
26296
26689
  return output.includes(check.text);
26297
26690
  case "fileExists":
26298
- return isFile(join34(sandboxDir, check.path));
26691
+ return isFile(join35(sandboxDir, check.path));
26299
26692
  case "fileNotExists":
26300
- return !existsSync40(join34(sandboxDir, check.path));
26693
+ return !existsSync40(join35(sandboxDir, check.path));
26301
26694
  case "dirExists":
26302
- return isDir(join34(sandboxDir, check.path));
26695
+ return isDir(join35(sandboxDir, check.path));
26303
26696
  case "fileContent": {
26304
- const abs = join34(sandboxDir, check.path);
26697
+ const abs = join35(sandboxDir, check.path);
26305
26698
  if (!isFile(abs))
26306
26699
  return false;
26307
26700
  const content = readFileSync27(abs, "utf-8");
@@ -26312,7 +26705,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
26312
26705
  return false;
26313
26706
  }
26314
26707
  case "fileRegex": {
26315
- const abs = join34(sandboxDir, check.path);
26708
+ const abs = join35(sandboxDir, check.path);
26316
26709
  if (!isFile(abs))
26317
26710
  return false;
26318
26711
  return new RegExp(check.pattern).test(readFileSync27(abs, "utf-8"));
@@ -26360,10 +26753,10 @@ function describe(check) {
26360
26753
  var init_fact_checker = () => {};
26361
26754
 
26362
26755
  // src/modules/certification/runner.ts
26363
- import { spawn as spawn6 } from "child_process";
26756
+ import { spawn as spawn7 } from "child_process";
26364
26757
  import { existsSync as existsSync41, mkdirSync as mkdirSync18, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
26365
26758
  import { platform as platform5 } from "os";
26366
- import { join as join35, resolve as resolve22, dirname as dirname8 } from "path";
26759
+ import { join as join36, resolve as resolve22, dirname as dirname9 } from "path";
26367
26760
  async function runScenario(scenario, opts) {
26368
26761
  if (scenario.mode === "skip") {
26369
26762
  return {
@@ -26382,7 +26775,7 @@ async function runScenario(scenario, opts) {
26382
26775
  let passed = 0;
26383
26776
  let firstError;
26384
26777
  for (let i = 1;i <= reps; i++) {
26385
- const sandbox = join35(opts.sandboxBase, `run-${scenario.id}-${i}`);
26778
+ const sandbox = join36(opts.sandboxBase, `run-${scenario.id}-${i}`);
26386
26779
  let failures = [];
26387
26780
  let exitCode = -1;
26388
26781
  let output = "";
@@ -26443,20 +26836,20 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
26443
26836
  rmSync4(sandbox, { recursive: true, force: true });
26444
26837
  mkdirSync18(sandbox, { recursive: true });
26445
26838
  for (const f of scenario.fixtures ?? []) {
26446
- const src = join35(mmaRoot, f.source);
26839
+ const src = join36(mmaRoot, f.source);
26447
26840
  if (!existsSync41(src)) {
26448
26841
  throw new Error(`fixture missing: ${f.source}`);
26449
26842
  }
26450
- const dest = join35(sandbox, f.dest);
26451
- mkdirSync18(dirname8(dest), { recursive: true });
26843
+ const dest = join36(sandbox, f.dest);
26844
+ mkdirSync18(dirname9(dest), { recursive: true });
26452
26845
  cpSync2(src, dest);
26453
26846
  }
26454
26847
  }
26455
26848
  function resolveMmaEntry(mmaRoot) {
26456
- const dev = join35(mmaRoot, "src", "cli", "main.ts");
26849
+ const dev = join36(mmaRoot, "src", "cli", "main.ts");
26457
26850
  if (existsSync41(dev))
26458
26851
  return dev;
26459
- return join35(mmaRoot, "dist", "main.js");
26852
+ return join36(mmaRoot, "dist", "main.js");
26460
26853
  }
26461
26854
  function findMmaRoot(fromDir) {
26462
26855
  const candidates = [
@@ -26464,7 +26857,7 @@ function findMmaRoot(fromDir) {
26464
26857
  resolve22(fromDir, "..")
26465
26858
  ];
26466
26859
  for (const c of candidates) {
26467
- if (existsSync41(join35(c, "package.json")))
26860
+ if (existsSync41(join36(c, "package.json")))
26468
26861
  return c;
26469
26862
  }
26470
26863
  return process.cwd();
@@ -26474,7 +26867,7 @@ function killTree2(child) {
26474
26867
  if (!pid)
26475
26868
  return;
26476
26869
  if (platform5() === "win32") {
26477
- spawn6("taskkill", ["/pid", String(pid), "/T", "/F"], {
26870
+ spawn7("taskkill", ["/pid", String(pid), "/T", "/F"], {
26478
26871
  windowsHide: true,
26479
26872
  stdio: "ignore"
26480
26873
  });
@@ -26489,7 +26882,7 @@ function killTree2(child) {
26489
26882
  }
26490
26883
  }
26491
26884
  var defaultRunner = (env2, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
26492
- const child = spawn6(process.execPath, args, {
26885
+ const child = spawn7(process.execPath, args, {
26493
26886
  cwd,
26494
26887
  env: env2,
26495
26888
  windowsHide: true,
@@ -26532,11 +26925,11 @@ __export(exports_cli, {
26532
26925
  });
26533
26926
  import { rmSync as rmSync5 } from "fs";
26534
26927
  import { homedir as homedir14 } from "os";
26535
- import { join as join36, dirname as dirname9 } from "path";
26536
- import { fileURLToPath } from "url";
26928
+ import { join as join37, dirname as dirname10 } from "path";
26929
+ import { fileURLToPath as fileURLToPath2 } from "url";
26537
26930
  import { existsSync as existsSync42, readFileSync as readFileSync28 } from "fs";
26538
26931
  function readVersion() {
26539
- const candidates = [join36(MMA_ROOT, "package.json")];
26932
+ const candidates = [join37(MMA_ROOT, "package.json")];
26540
26933
  for (const p of candidates) {
26541
26934
  if (existsSync42(p)) {
26542
26935
  try {
@@ -26576,7 +26969,7 @@ async function certify(opts) {
26576
26969
  return;
26577
26970
  }
26578
26971
  console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
26579
- const sandboxBase = join36(process.cwd(), ".mma", "certification");
26972
+ const sandboxBase = join37(process.cwd(), ".mma", "certification");
26580
26973
  const results = [];
26581
26974
  const total = selected.length;
26582
26975
  let idx = 0;
@@ -26688,9 +27081,9 @@ var init_cli = __esm(() => {
26688
27081
  init_loader3();
26689
27082
  init_runner2();
26690
27083
  init_manifest();
26691
- HERE = dirname9(fileURLToPath(import.meta.url));
27084
+ HERE = dirname10(fileURLToPath2(import.meta.url));
26692
27085
  MMA_ROOT = findMmaRoot(HERE);
26693
- USER_SCENARIO_DIR = join36(homedir14(), ".mma", "certification", "scenarios");
27086
+ USER_SCENARIO_DIR = join37(homedir14(), ".mma", "certification", "scenarios");
26694
27087
  });
26695
27088
 
26696
27089
  // src/cli/repl-commands.ts
@@ -26699,15 +27092,15 @@ __export(exports_repl_commands, {
26699
27092
  registerAllCommands: () => registerAllCommands,
26700
27093
  COMMAND_GROUPS: () => COMMAND_GROUPS
26701
27094
  });
26702
- import { join as join38, dirname as dirname11 } from "path";
27095
+ import { join as join39, dirname as dirname12 } from "path";
26703
27096
  import { homedir as homedir16 } from "os";
26704
27097
  import { existsSync as existsSync44, readFileSync as readFileSync30 } from "fs";
26705
- import { fileURLToPath as fileURLToPath3 } from "url";
27098
+ import { fileURLToPath as fileURLToPath4 } from "url";
26706
27099
  function readVersion3() {
26707
- const here = dirname11(fileURLToPath3(import.meta.url));
27100
+ const here = dirname12(fileURLToPath4(import.meta.url));
26708
27101
  const candidates = [
26709
- join38(here, "..", "..", "package.json"),
26710
- join38(here, "..", "package.json")
27102
+ join39(here, "..", "..", "package.json"),
27103
+ join39(here, "..", "package.json")
26711
27104
  ];
26712
27105
  for (const p of candidates) {
26713
27106
  if (existsSync44(p)) {
@@ -26875,7 +27268,7 @@ function registerMmaCommands(ctx) {
26875
27268
  console.log(pc2.yellow(t("repl.wizard_running")));
26876
27269
  await ctx.withExclusiveInput(async () => {
26877
27270
  const answers = await runSetup(ctx.rl);
26878
- const configPath = join38(homedir16(), ".mma", "config.json");
27271
+ const configPath = join39(homedir16(), ".mma", "config.json");
26879
27272
  ctx.config.provider.type = answers.provider;
26880
27273
  ctx.config.provider.baseUrl = answers.apiBase;
26881
27274
  ctx.config.provider.apiKey = answers.apiKey;
@@ -26929,7 +27322,7 @@ Excluded blocks: ${info.excluded.length}`));
26929
27322
  return;
26930
27323
  }
26931
27324
  ctx.config.provider.type = name;
26932
- const configPath = join38(homedir16(), ".mma", "config.json");
27325
+ const configPath = join39(homedir16(), ".mma", "config.json");
26933
27326
  saveConfig(ctx.config, configPath);
26934
27327
  await ctx.agent.reconfigure(ctx.config);
26935
27328
  console.log(pc2.green(t("repl.provider_set", { name })));
@@ -26985,7 +27378,7 @@ Excluded blocks: ${info.excluded.length}`));
26985
27378
  return;
26986
27379
  }
26987
27380
  ctx.config.model = name;
26988
- const configPath = join38(homedir16(), ".mma", "config.json");
27381
+ const configPath = join39(homedir16(), ".mma", "config.json");
26989
27382
  saveConfig(ctx.config, configPath);
26990
27383
  await ctx.agent.reconfigure(ctx.config);
26991
27384
  console.log(pc2.green(t("repl.model_set", { name })));
@@ -27010,7 +27403,7 @@ Excluded blocks: ${info.excluded.length}`));
27010
27403
  return;
27011
27404
  }
27012
27405
  ctx.config.contextWindow = size;
27013
- const configPath = join38(homedir16(), ".mma", "config.json");
27406
+ const configPath = join39(homedir16(), ".mma", "config.json");
27014
27407
  saveConfig(ctx.config, configPath);
27015
27408
  await ctx.agent.reconfigure(ctx.config);
27016
27409
  console.log(pc2.green(t("cli.context_set", { size })));
@@ -27029,10 +27422,10 @@ Excluded blocks: ${info.excluded.length}`));
27029
27422
  ctx.agent.shutdown();
27030
27423
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
27031
27424
  const { homedir: homedir17 } = await import("os");
27032
- const { join: join39 } = await import("path");
27425
+ const { join: join40 } = await import("path");
27033
27426
  const configDir = ctx.configDir;
27034
27427
  const baseDir = ctx.baseDir;
27035
- const projectConfigPath = join39(baseDir, ".mmrc");
27428
+ const projectConfigPath = join40(baseDir, ".mmrc");
27036
27429
  const freshConfig = loadConfig2({ configDir, projectConfigPath });
27037
27430
  Object.assign(ctx.config, freshConfig);
27038
27431
  const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
@@ -27332,14 +27725,14 @@ init_bootstrap();
27332
27725
  init_config2();
27333
27726
  init_setup();
27334
27727
  init_i18n();
27335
- import { join as join37, dirname as dirname10 } from "path";
27728
+ import { join as join38, dirname as dirname11 } from "path";
27336
27729
  import { homedir as homedir15 } from "os";
27337
27730
  import { existsSync as existsSync43, readFileSync as readFileSync29 } from "fs";
27338
27731
 
27339
27732
  // src/cli/security-commands.ts
27340
27733
  init_bootstrap();
27341
27734
  init_config2();
27342
- import { join as join31 } from "path";
27735
+ import { join as join32 } from "path";
27343
27736
  import { homedir as homedir12 } from "os";
27344
27737
 
27345
27738
  // src/modules/security/security-policies.ts
@@ -27869,7 +28262,7 @@ function createSecurityCommand(program2) {
27869
28262
  }
27870
28263
  });
27871
28264
  securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
27872
- const configPath = join31(homedir12(), ".mma", "config.json");
28265
+ const configPath = join32(homedir12(), ".mma", "config.json");
27873
28266
  const { config: appConfig } = await bootstrap();
27874
28267
  const validPresets = ["strict", "balanced", "permissive"];
27875
28268
  if (!validPresets.includes(preset)) {
@@ -27884,7 +28277,7 @@ function createSecurityCommand(program2) {
27884
28277
  console.log(t("cli.security.policy_description", { description: policy.description }));
27885
28278
  });
27886
28279
  securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
27887
- const configPath = join31(homedir12(), ".mma", "config.json");
28280
+ const configPath = join32(homedir12(), ".mma", "config.json");
27888
28281
  const { config: appConfig } = await bootstrap();
27889
28282
  appConfig.security = appConfig.security || {};
27890
28283
  appConfig.security.sessionEncryption = {
@@ -27896,7 +28289,7 @@ function createSecurityCommand(program2) {
27896
28289
  console.log(t("cli.security.encryption_enabled"));
27897
28290
  });
27898
28291
  securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
27899
- const configPath = join31(homedir12(), ".mma", "config.json");
28292
+ const configPath = join32(homedir12(), ".mma", "config.json");
27900
28293
  const { config: appConfig } = await bootstrap();
27901
28294
  appConfig.security = appConfig.security || {};
27902
28295
  appConfig.security.sessionEncryption = {
@@ -27908,7 +28301,7 @@ function createSecurityCommand(program2) {
27908
28301
  console.log(t("cli.security.encryption_disabled"));
27909
28302
  });
27910
28303
  securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
27911
- const configPath = join31(homedir12(), ".mma", "config.json");
28304
+ const configPath = join32(homedir12(), ".mma", "config.json");
27912
28305
  const { config: appConfig } = await bootstrap();
27913
28306
  appConfig.security = appConfig.security || {};
27914
28307
  appConfig.security.auditNotifier = {
@@ -27922,7 +28315,7 @@ function createSecurityCommand(program2) {
27922
28315
  console.log(t("cli.security.audit_enabled"));
27923
28316
  });
27924
28317
  securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
27925
- const configPath = join31(homedir12(), ".mma", "config.json");
28318
+ const configPath = join32(homedir12(), ".mma", "config.json");
27926
28319
  const { config: appConfig } = await bootstrap();
27927
28320
  appConfig.security = appConfig.security || {};
27928
28321
  appConfig.security.auditNotifier = {
@@ -27954,12 +28347,12 @@ function createSecurityCommand(program2) {
27954
28347
  }
27955
28348
 
27956
28349
  // src/cli/commands.ts
27957
- import { fileURLToPath as fileURLToPath2 } from "url";
28350
+ import { fileURLToPath as fileURLToPath3 } from "url";
27958
28351
  function readVersion2() {
27959
- const here = dirname10(fileURLToPath2(import.meta.url));
28352
+ const here = dirname11(fileURLToPath3(import.meta.url));
27960
28353
  const candidates = [
27961
- join37(here, "..", "..", "package.json"),
27962
- join37(here, "..", "package.json")
28354
+ join38(here, "..", "..", "package.json"),
28355
+ join38(here, "..", "package.json")
27963
28356
  ];
27964
28357
  for (const p of candidates) {
27965
28358
  if (existsSync43(p)) {
@@ -27977,7 +28370,7 @@ function createProgram() {
27977
28370
  const program2 = new Command().name("mma").description(t("cli.description")).version(version).option("--no-agents-md", t("cli.no_agents_md")).option("-d, --dir <path>", t("cli.dir")).option("-e, --exit-on-complete", t("cli.exit_on_complete")).option("-j, --json", t("cli.json"));
27978
28371
  program2.command("init").description(t("cli.init")).action(async () => {
27979
28372
  const answers = await runSetup();
27980
- const configPath = join37(homedir15(), ".mma", "config.json");
28373
+ const configPath = join38(homedir15(), ".mma", "config.json");
27981
28374
  const { config } = await bootstrap();
27982
28375
  config.provider.type = answers.provider;
27983
28376
  config.provider.baseUrl = answers.apiBase;
@@ -28022,7 +28415,7 @@ function createProgram() {
28022
28415
  });
28023
28416
  const configCmd = program2.command("config").description(t("cli.manage_config"));
28024
28417
  configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
28025
- const configPath = join37(homedir15(), ".mma", "config.json");
28418
+ const configPath = join38(homedir15(), ".mma", "config.json");
28026
28419
  const { config } = await bootstrap();
28027
28420
  const keys = key.split(".");
28028
28421
  let obj = config;
@@ -28085,7 +28478,7 @@ function createProgram() {
28085
28478
  console.log(t("cli.model_hint"));
28086
28479
  });
28087
28480
  model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
28088
- const configPath = join37(homedir15(), ".mma", "config.json");
28481
+ const configPath = join38(homedir15(), ".mma", "config.json");
28089
28482
  const { config } = await bootstrap();
28090
28483
  config.model = name;
28091
28484
  saveConfig(config, configPath);
@@ -28121,7 +28514,7 @@ function createProgram() {
28121
28514
  await uncertify2(name, config);
28122
28515
  });
28123
28516
  program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
28124
- const configPath = join37(homedir15(), ".mma", "config.json");
28517
+ const configPath = join38(homedir15(), ".mma", "config.json");
28125
28518
  const { config } = await bootstrap();
28126
28519
  const contextWindow = parseInt(size, 10);
28127
28520
  if (isNaN(contextWindow) || contextWindow < 1024) {
@@ -28139,7 +28532,7 @@ function createProgram() {
28139
28532
  console.log(t("cli.base_url"), config.provider.baseUrl);
28140
28533
  });
28141
28534
  provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
28142
- const configPath = join37(homedir15(), ".mma", "config.json");
28535
+ const configPath = join38(homedir15(), ".mma", "config.json");
28143
28536
  const { config } = await bootstrap();
28144
28537
  config.provider.type = name;
28145
28538
  saveConfig(config, configPath);
@@ -28192,9 +28585,9 @@ init_bootstrap();
28192
28585
  init_colors();
28193
28586
  import * as readline2 from "readline";
28194
28587
  import { existsSync as existsSync45, readFileSync as readFileSync31, writeFileSync as writeFileSync16 } from "fs";
28195
- import { join as join39, dirname as dirname12 } from "path";
28588
+ import { join as join40, dirname as dirname13 } from "path";
28196
28589
  import { homedir as homedir17 } from "os";
28197
- import { fileURLToPath as fileURLToPath4 } from "url";
28590
+ import { fileURLToPath as fileURLToPath5 } from "url";
28198
28591
 
28199
28592
  // src/cli/completer.ts
28200
28593
  class SlashCommandProvider {
@@ -28704,10 +29097,10 @@ init_box();
28704
29097
  init_i18n();
28705
29098
  init_repl_commands();
28706
29099
  function readVersion4() {
28707
- const here = dirname12(fileURLToPath4(import.meta.url));
29100
+ const here = dirname13(fileURLToPath5(import.meta.url));
28708
29101
  const candidates = [
28709
- join39(here, "..", "..", "package.json"),
28710
- join39(here, "..", "package.json")
29102
+ join40(here, "..", "..", "package.json"),
29103
+ join40(here, "..", "package.json")
28711
29104
  ];
28712
29105
  for (const p of candidates) {
28713
29106
  if (existsSync45(p)) {
@@ -28766,10 +29159,10 @@ class Repl {
28766
29159
  this.skillsModule = skillsModule;
28767
29160
  this.pluginManager = pluginManager;
28768
29161
  this.logger = logger;
28769
- this.configDir = configDir || join39(homedir17(), ".mma");
29162
+ this.configDir = configDir || join40(homedir17(), ".mma");
28770
29163
  this.baseDir = baseDir || process.cwd();
28771
29164
  this.noAgentsMd = noAgentsMd === true;
28772
- this.historyPath = join39(homedir17(), ".mma", "repl-history");
29165
+ this.historyPath = join40(homedir17(), ".mma", "repl-history");
28773
29166
  this.loadHistory();
28774
29167
  this.rl = readline2.createInterface({
28775
29168
  input: process.stdin,
@@ -29123,9 +29516,9 @@ ${t("image.clipboard_empty")}`));
29123
29516
  row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
29124
29517
  } else {
29125
29518
  const agentsMdCandidates = [
29126
- join39(this.baseDir, "AGENTS.md"),
29127
- join39(this.baseDir, ".mma", "AGENTS.md"),
29128
- join39(this.configDir, "AGENTS.md")
29519
+ join40(this.baseDir, "AGENTS.md"),
29520
+ join40(this.baseDir, ".mma", "AGENTS.md"),
29521
+ join40(this.configDir, "AGENTS.md")
29129
29522
  ];
29130
29523
  const foundAgents = agentsMdCandidates.filter((p) => existsSync45(p));
29131
29524
  if (foundAgents.length > 0) {
@@ -29138,7 +29531,7 @@ ${t("image.clipboard_empty")}`));
29138
29531
  }
29139
29532
  const meta = this.sessionManager?.getActiveMeta();
29140
29533
  if (meta) {
29141
- const sessionPath = join39(this.configDir, "sessions", meta.id);
29534
+ const sessionPath = join40(this.configDir, "sessions", meta.id);
29142
29535
  row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
29143
29536
  }
29144
29537
  const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
@@ -29165,9 +29558,9 @@ init_config2();
29165
29558
  init_i18n();
29166
29559
  init_colors();
29167
29560
  import { existsSync as existsSync46, readFileSync as readFileSync32 } from "fs";
29168
- import { join as join40, dirname as dirname13 } from "path";
29561
+ import { join as join41, dirname as dirname14 } from "path";
29169
29562
  import { homedir as homedir18 } from "os";
29170
- import { fileURLToPath as fileURLToPath5 } from "url";
29563
+ import { fileURLToPath as fileURLToPath6 } from "url";
29171
29564
 
29172
29565
  // src/modules/updater/checker.ts
29173
29566
  var defaultRunner2 = async (command, args, options) => {
@@ -29316,10 +29709,10 @@ class UpdaterModule {
29316
29709
  }
29317
29710
  // src/cli/main.ts
29318
29711
  function readVersion5() {
29319
- const here = dirname13(fileURLToPath5(import.meta.url));
29712
+ const here = dirname14(fileURLToPath6(import.meta.url));
29320
29713
  const candidates = [
29321
- join40(here, "..", "..", "package.json"),
29322
- join40(here, "..", "package.json")
29714
+ join41(here, "..", "..", "package.json"),
29715
+ join41(here, "..", "package.json")
29323
29716
  ];
29324
29717
  for (const p of candidates) {
29325
29718
  if (existsSync46(p)) {
@@ -29404,15 +29797,15 @@ async function main() {
29404
29797
  }
29405
29798
  agent.shutdown();
29406
29799
  } else {
29407
- const configPath = join40(homedir18(), ".mma", "config.json");
29800
+ const configPath = join41(homedir18(), ".mma", "config.json");
29408
29801
  if (!existsSync46(configPath)) {
29409
29802
  console.log(pc2.yellow(`
29410
29803
  ` + t("cli.first_run") + `
29411
29804
  `));
29412
29805
  const answers = await runSetup();
29413
29806
  const config2 = loadConfig({
29414
- configDir: join40(homedir18(), ".mma"),
29415
- projectConfigPath: projectDir ? join40(projectDir, ".mmrc") : join40(process.cwd(), ".mmrc")
29807
+ configDir: join41(homedir18(), ".mma"),
29808
+ projectConfigPath: projectDir ? join41(projectDir, ".mmrc") : join41(process.cwd(), ".mmrc")
29416
29809
  });
29417
29810
  config2.provider.type = answers.provider;
29418
29811
  config2.provider.baseUrl = answers.apiBase;