micro-models-agent 0.39.0 → 0.40.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 (96) hide show
  1. package/bin/mma.mjs +41 -41
  2. package/dist/cli/commands.js +116 -3
  3. package/dist/cli/main.js +35 -8
  4. package/dist/cli/repl-commands.js +633 -0
  5. package/dist/cli/repl.js +110 -611
  6. package/dist/cli/setup.js +32 -12
  7. package/dist/config/config.js +46 -30
  8. package/dist/config/defaults.js +10 -1
  9. package/dist/config/security.js +15 -8
  10. package/dist/core/agent-moe.js +24 -12
  11. package/dist/core/agent.js +281 -47
  12. package/dist/core/bootstrap.js +52 -36
  13. package/dist/core/session-logger.js +35 -2
  14. package/dist/core/workspace.js +76 -0
  15. package/dist/i18n/en.json +79 -15
  16. package/dist/i18n/index.js +12 -9
  17. package/dist/i18n/ru.json +79 -15
  18. package/dist/index.js +13 -13
  19. package/dist/llm/openai-compat.js +39 -10
  20. package/dist/logger/app-logger.js +83 -16
  21. package/dist/logger/file-log.js +151 -0
  22. package/dist/main.js +537 -284
  23. package/dist/modules/browser/bridge-server.mjs +113 -105
  24. package/dist/modules/browser/session.js +108 -60
  25. package/dist/modules/certification/cli.js +176 -0
  26. package/dist/modules/certification/fact-checker.js +84 -0
  27. package/dist/modules/certification/loader.js +111 -0
  28. package/dist/modules/certification/manifest.js +50 -0
  29. package/dist/modules/certification/runner.js +162 -0
  30. package/dist/modules/certification/scenarios.js +124 -0
  31. package/dist/modules/certification/types.js +1 -0
  32. package/dist/modules/context/manager.js +119 -10
  33. package/dist/modules/execution/auditor.js +33 -39
  34. package/dist/modules/execution/index.js +8 -6
  35. package/dist/modules/execution/module.js +474 -32
  36. package/dist/modules/execution/moe-executor.js +97 -40
  37. package/dist/modules/execution/plan-coverage.js +68 -0
  38. package/dist/modules/execution/plan-persister.js +46 -0
  39. package/dist/modules/execution/plan-store.js +159 -0
  40. package/dist/modules/execution/planner.js +63 -13
  41. package/dist/modules/execution/stuck-detector.js +252 -39
  42. package/dist/modules/execution/tracker.js +21 -7
  43. package/dist/modules/execution/verifier.js +46 -17
  44. package/dist/modules/hallucination/confidence.js +7 -2
  45. package/dist/modules/hallucination/consistency.js +8 -42
  46. package/dist/modules/hallucination/detector.js +26 -21
  47. package/dist/modules/hallucination/factual.js +170 -150
  48. package/dist/modules/hallucination/index.js +5 -4
  49. package/dist/modules/hallucination/js-identifiers.js +72 -0
  50. package/dist/modules/hallucination/llm-judge.js +103 -0
  51. package/dist/modules/index.js +5 -5
  52. package/dist/modules/lsp/client.js +235 -0
  53. package/dist/modules/lsp/config.js +81 -0
  54. package/dist/modules/lsp/index.js +3 -0
  55. package/dist/modules/lsp/module.js +68 -0
  56. package/dist/modules/lsp/types.js +1 -0
  57. package/dist/modules/mcp/client.js +8 -2
  58. package/dist/modules/memory/store.js +4 -0
  59. package/dist/modules/plugins/builtin/lint-on-write.js +143 -38
  60. package/dist/modules/processes/index.js +1 -2
  61. package/dist/modules/processes/registry.js +125 -35
  62. package/dist/modules/processes/runner.js +9 -110
  63. package/dist/modules/security/audit-log.js +30 -10
  64. package/dist/modules/security/command-validator.js +42 -16
  65. package/dist/modules/security/content-scanner.js +9 -8
  66. package/dist/modules/security/network-validator.js +2 -2
  67. package/dist/modules/security/path-validator.js +64 -10
  68. package/dist/modules/security/security-policies.js +221 -67
  69. package/dist/modules/security/session-encryption.js +42 -25
  70. package/dist/modules/session/manager.js +15 -10
  71. package/dist/modules/session/store.js +62 -8
  72. package/dist/modules/skills/index.js +2 -3
  73. package/dist/modules/skills/module.js +10 -23
  74. package/dist/tools/bash.js +287 -90
  75. package/dist/tools/create-dir.js +0 -1
  76. package/dist/tools/delete-file.js +0 -1
  77. package/dist/tools/edit-file.js +10 -8
  78. package/dist/tools/executor.js +57 -7
  79. package/dist/tools/grep-tool.js +51 -29
  80. package/dist/tools/index.js +55 -40
  81. package/dist/tools/load-skill.js +14 -18
  82. package/dist/tools/move-file.js +3 -2
  83. package/dist/tools/pipeline-run.js +1 -1
  84. package/dist/tools/read-file.js +15 -5
  85. package/dist/tools/search-history.js +42 -22
  86. package/dist/tools/subagent.js +21 -12
  87. package/dist/tools/web-browse.js +54 -25
  88. package/dist/tools/web-fetch.js +60 -34
  89. package/dist/tools/web-search.js +39 -20
  90. package/dist/tools/write-file.js +13 -10
  91. package/dist/ui/diff.js +9 -16
  92. package/dist/ui/renderer.js +69 -6
  93. package/package.json +48 -45
  94. package/dist/modules/context/history.js +0 -15
  95. package/dist/modules/processes/detect.js +0 -34
  96. package/dist/modules/skills/matcher.js +0 -27
@@ -1,110 +1,110 @@
1
- import { createRequire } from 'module'
2
- import readline from 'readline'
1
+ import { createRequire } from "module";
2
+ import readline from "readline";
3
3
 
4
- const require = createRequire(import.meta.url)
5
- const { chromium } = require('playwright')
4
+ const require = createRequire(import.meta.url);
5
+ const { chromium } = require("playwright");
6
6
 
7
- const CONSOLE_CAP = 500
8
- const NETWORK_CAP = 100
9
- let maxLineChars = 400
7
+ const CONSOLE_CAP = 500;
8
+ const NETWORK_CAP = 100;
9
+ let maxLineChars = 400;
10
10
 
11
- let browser = null
12
- let context = null
13
- let page = null
14
- let consoleBuf = []
15
- let networkBuf = []
16
- let lastUrl = ''
11
+ let browser = null;
12
+ let context = null;
13
+ let page = null;
14
+ let consoleBuf = [];
15
+ let networkBuf = [];
16
+ let lastUrl = "";
17
17
 
18
18
  function pushConsole(type, text) {
19
- if (consoleBuf.length >= CONSOLE_CAP) return
20
- const clean = String(text).replace(/\s+/g, ' ').trim()
21
- if (!clean) return
22
- const line = clean.length > maxLineChars ? clean.slice(0, maxLineChars) + '' : clean
23
- consoleBuf.push({ type, text: line })
19
+ if (consoleBuf.length >= CONSOLE_CAP) return;
20
+ const clean = String(text).replace(/\s+/g, " ").trim();
21
+ if (!clean) return;
22
+ const line = clean.length > maxLineChars ? clean.slice(0, maxLineChars) + "" : clean;
23
+ consoleBuf.push({ type, text: line });
24
24
  }
25
25
 
26
26
  function pushNetwork(err) {
27
- if (networkBuf.length >= NETWORK_CAP) return
28
- networkBuf.push(err)
27
+ if (networkBuf.length >= NETWORK_CAP) return;
28
+ networkBuf.push(err);
29
29
  }
30
30
 
31
31
  function drain() {
32
- const consoleEvents = consoleBuf
33
- const networkEvents = networkBuf
34
- consoleBuf = []
35
- networkBuf = []
36
- return { console: consoleEvents, network: networkEvents }
32
+ const consoleEvents = consoleBuf;
33
+ const networkEvents = networkBuf;
34
+ consoleBuf = [];
35
+ networkBuf = [];
36
+ return { console: consoleEvents, network: networkEvents };
37
37
  }
38
38
 
39
39
  function readInt(v, fallback) {
40
- const n = Number(v)
41
- return Number.isFinite(n) && n > 0 ? n : fallback
40
+ const n = Number(v);
41
+ return Number.isFinite(n) && n > 0 ? n : fallback;
42
42
  }
43
43
 
44
44
  async function handleLaunch(params) {
45
- if (browser) return { ok: true }
46
- maxLineChars = readInt(params?.maxConsoleLineChars, 400)
45
+ if (browser) return { ok: true };
46
+ maxLineChars = readInt(params?.maxConsoleLineChars, 400);
47
47
  browser = await chromium.launch({
48
48
  headless: params?.headless !== false,
49
49
  timeout: readInt(params?.timeoutMs, 30000),
50
- })
50
+ });
51
51
  context = await browser.newContext({
52
52
  viewport: params?.viewport || { width: 1280, height: 720 },
53
- })
54
- page = await context.newPage()
55
- page.setDefaultTimeout(readInt(params?.timeoutMs, 30000))
56
-
57
- page.on('console', (msg) => pushConsole(msg.type(), msg.text()))
58
- page.on('pageerror', (err) => pushConsole('pageerror', `Page error: ${err.message}`))
59
- page.on('requestfailed', (req) => {
60
- const failure = req.failure()
61
- pushNetwork({ method: req.method(), url: req.url(), error: failure?.errorText || 'unknown' })
62
- })
63
-
64
- return { ok: true }
53
+ });
54
+ page = await context.newPage();
55
+ page.setDefaultTimeout(readInt(params?.timeoutMs, 30000));
56
+
57
+ page.on("console", (msg) => pushConsole(msg.type(), msg.text()));
58
+ page.on("pageerror", (err) => pushConsole("pageerror", `Page error: ${err.message}`));
59
+ page.on("requestfailed", (req) => {
60
+ const failure = req.failure();
61
+ pushNetwork({ method: req.method(), url: req.url(), error: failure?.errorText || "unknown" });
62
+ });
63
+
64
+ return { ok: true };
65
65
  }
66
66
 
67
67
  async function handleGoto(params) {
68
- if (!page) return { ok: false, error: 'No page open' }
69
- const url = String(params?.url || '')
70
- const timeoutMs = readInt(params?.timeoutMs, 15000)
71
- consoleBuf = []
72
- networkBuf = []
68
+ if (!page) return { ok: false, error: "No page open" };
69
+ const url = String(params?.url || "");
70
+ const timeoutMs = readInt(params?.timeoutMs, 15000);
71
+ consoleBuf = [];
72
+ networkBuf = [];
73
73
  try {
74
- await page.goto(url, { waitUntil: 'domcontentloaded', timeout: timeoutMs })
75
- lastUrl = page.url()
76
- return { ok: true, data: { url: lastUrl } }
74
+ await page.goto(url, { waitUntil: "domcontentloaded", timeout: timeoutMs });
75
+ lastUrl = page.url();
76
+ return { ok: true, data: { url: lastUrl } };
77
77
  } catch (err) {
78
- lastUrl = page.url()
79
- return { ok: false, error: err.message, data: { url: lastUrl } }
78
+ lastUrl = page.url();
79
+ return { ok: false, error: err.message, data: { url: lastUrl } };
80
80
  }
81
81
  }
82
82
 
83
83
  async function handleEvaluate(params) {
84
- if (!page) return { ok: false, error: 'No page open' }
85
- const js = String(params?.js || '')
84
+ if (!page) return { ok: false, error: "No page open" };
85
+ const js = String(params?.js || "");
86
86
  try {
87
- const result = await page.evaluate(js)
88
- return { ok: true, data: { result } }
87
+ const result = await page.evaluate(js);
88
+ return { ok: true, data: { result } };
89
89
  } catch (err) {
90
- return { ok: false, error: err.message }
90
+ return { ok: false, error: err.message };
91
91
  }
92
92
  }
93
93
 
94
94
  async function handleClose() {
95
95
  try {
96
- if (page) await page.close()
96
+ if (page) await page.close();
97
97
  } catch {}
98
98
  try {
99
- if (context) await context.close()
99
+ if (context) await context.close();
100
100
  } catch {}
101
101
  try {
102
- if (browser) await browser.close()
102
+ if (browser) await browser.close();
103
103
  } catch {}
104
- page = null
105
- context = null
106
- browser = null
107
- return { ok: true }
104
+ page = null;
105
+ context = null;
106
+ browser = null;
107
+ return { ok: true };
108
108
  }
109
109
 
110
110
  const handlers = {
@@ -112,83 +112,91 @@ const handlers = {
112
112
  launch: handleLaunch,
113
113
  goto: handleGoto,
114
114
  evaluate: handleEvaluate,
115
- content: async () => ({ ok: true, data: { html: page ? await page.content() : '' } }),
116
- title: async () => ({ ok: true, data: { title: page ? await page.title() : '' } }),
115
+ content: async () => ({ ok: true, data: { html: page ? await page.content() : "" } }),
116
+ title: async () => ({ ok: true, data: { title: page ? await page.title() : "" } }),
117
117
  url: async () => ({ ok: true, data: { url: page ? page.url() : lastUrl } }),
118
118
  waitLoad: async (params) => {
119
- if (!page) return { ok: false, error: 'No page open' }
119
+ if (!page) return { ok: false, error: "No page open" };
120
120
  try {
121
- await page.waitForLoadState('domcontentloaded', { timeout: readInt(params?.timeoutMs, 15000) })
121
+ await page.waitForLoadState("domcontentloaded", {
122
+ timeout: readInt(params?.timeoutMs, 15000),
123
+ });
122
124
  } catch {}
123
- return { ok: true }
125
+ return { ok: true };
124
126
  },
125
127
  screenshot: async () => {
126
- if (!page) return { ok: false, error: 'No page open' }
128
+ if (!page) return { ok: false, error: "No page open" };
127
129
  try {
128
- const buf = await page.screenshot({ type: 'png', fullPage: false })
129
- return { ok: true, data: { base64: buf.toString('base64') } }
130
+ const buf = await page.screenshot({ type: "png", fullPage: false });
131
+ return { ok: true, data: { base64: buf.toString("base64") } };
130
132
  } catch (err) {
131
- return { ok: false, error: err.message }
133
+ return { ok: false, error: err.message };
132
134
  }
133
135
  },
134
136
  cookies: async () => {
135
- if (!context) return { ok: true, data: { cookies: [] } }
136
- const cookies = await context.cookies()
137
- return { ok: true, data: { cookies } }
137
+ if (!context) return { ok: true, data: { cookies: [] } };
138
+ const cookies = await context.cookies();
139
+ return { ok: true, data: { cookies } };
138
140
  },
139
141
  setCookies: async (params) => {
140
- if (!context) return { ok: false, error: 'No context' }
141
- const cookies = Array.isArray(params?.cookies) ? params.cookies : []
142
+ if (!context) return { ok: false, error: "No context" };
143
+ const cookies = Array.isArray(params?.cookies) ? params.cookies : [];
142
144
  if (cookies.length > 0) {
143
145
  try {
144
- await context.addCookies(cookies)
146
+ await context.addCookies(cookies);
145
147
  } catch (err) {
146
- return { ok: false, error: err.message }
148
+ return { ok: false, error: err.message };
147
149
  }
148
150
  }
149
- return { ok: true }
151
+ return { ok: true };
150
152
  },
151
153
  back: async (params) => {
152
- if (!page) return { ok: false, error: 'No page open' }
154
+ if (!page) return { ok: false, error: "No page open" };
153
155
  try {
154
- await page.goBack({ waitUntil: 'domcontentloaded', timeout: readInt(params?.timeoutMs, 15000) })
156
+ await page.goBack({
157
+ waitUntil: "domcontentloaded",
158
+ timeout: readInt(params?.timeoutMs, 15000),
159
+ });
155
160
  } catch {}
156
- lastUrl = page.url()
157
- return { ok: true, data: { url: lastUrl } }
161
+ lastUrl = page.url();
162
+ return { ok: true, data: { url: lastUrl } };
158
163
  },
159
164
  forward: async (params) => {
160
- if (!page) return { ok: false, error: 'No page open' }
165
+ if (!page) return { ok: false, error: "No page open" };
161
166
  try {
162
- await page.goForward({ waitUntil: 'domcontentloaded', timeout: readInt(params?.timeoutMs, 15000) })
167
+ await page.goForward({
168
+ waitUntil: "domcontentloaded",
169
+ timeout: readInt(params?.timeoutMs, 15000),
170
+ });
163
171
  } catch {}
164
- lastUrl = page.url()
165
- return { ok: true, data: { url: lastUrl } }
172
+ lastUrl = page.url();
173
+ return { ok: true, data: { url: lastUrl } };
166
174
  },
167
175
  close: handleClose,
168
- }
176
+ };
169
177
 
170
- const rl = readline.createInterface({ input: process.stdin })
171
- rl.on('line', async (line) => {
172
- let req
178
+ const rl = readline.createInterface({ input: process.stdin });
179
+ rl.on("line", async (line) => {
180
+ let req;
173
181
  try {
174
- req = JSON.parse(line)
182
+ req = JSON.parse(line);
175
183
  } catch {
176
- return
184
+ return;
177
185
  }
178
- const handler = handlers[req.cmd]
179
- let resp
186
+ const handler = handlers[req.cmd];
187
+ let resp;
180
188
  if (!handler) {
181
- resp = { id: req.id, ok: false, error: `Unknown command: ${req.cmd}`, ...drain() }
189
+ resp = { id: req.id, ok: false, error: `Unknown command: ${req.cmd}`, ...drain() };
182
190
  } else {
183
191
  try {
184
- const result = await handler(req.params || {})
185
- resp = { id: req.id, ...result, ...drain() }
192
+ const result = await handler(req.params || {});
193
+ resp = { id: req.id, ...result, ...drain() };
186
194
  } catch (err) {
187
- resp = { id: req.id, ok: false, error: err.message, ...drain() }
195
+ resp = { id: req.id, ok: false, error: err.message, ...drain() };
188
196
  }
189
197
  }
190
- process.stdout.write(JSON.stringify(resp) + '\n')
191
- })
198
+ process.stdout.write(JSON.stringify(resp) + "\n");
199
+ });
192
200
 
193
- process.on('SIGTERM', () => process.exit(0))
194
- process.on('SIGINT', () => process.exit(0))
201
+ process.on("SIGTERM", () => process.exit(0));
202
+ process.on("SIGINT", () => process.exit(0));
@@ -1,8 +1,8 @@
1
- import { chromium } from 'playwright';
2
- import { extractInteractiveElements, formatSnapshot } from './snapshot';
3
- import { buildClickScript, buildTypeScript, buildScrollScript, buildIndexInjectionScript } from './actions';
4
- import { CookieStore } from './cookie-store';
5
- import { t } from '../../i18n/index';
1
+ import { chromium, } from "playwright";
2
+ import { extractInteractiveElements, formatSnapshot } from "./snapshot";
3
+ import { buildClickScript, buildTypeScript, buildScrollScript, buildIndexInjectionScript, } from "./actions";
4
+ import { CookieStore } from "./cookie-store";
5
+ import { t } from "../../i18n/index";
6
6
  export class BrowserActionTracker {
7
7
  history = [];
8
8
  threshold;
@@ -14,11 +14,14 @@ export class BrowserActionTracker {
14
14
  if (this.history.length < this.threshold)
15
15
  return null;
16
16
  const recent = this.history.slice(-this.threshold);
17
- const allSame = recent.every(h => h.action === recent[0].action &&
17
+ const allSame = recent.every((h) => h.action === recent[0].action &&
18
18
  h.url === recent[0].url &&
19
19
  JSON.stringify(h.args) === JSON.stringify(recent[0].args));
20
20
  if (allSame) {
21
- return t('browser.repeated_action', { action, threshold: this.threshold });
21
+ return t("browser.repeated_action", {
22
+ action,
23
+ threshold: this.threshold,
24
+ });
22
25
  }
23
26
  return null;
24
27
  }
@@ -32,7 +35,12 @@ export class BrowserSession {
32
35
  page = null;
33
36
  config;
34
37
  cookieStore;
35
- state = { isOpen: false, url: null, title: null, elementCount: 0 };
38
+ state = {
39
+ isOpen: false,
40
+ url: null,
41
+ title: null,
42
+ elementCount: 0,
43
+ };
36
44
  actionTracker = new BrowserActionTracker(3);
37
45
  constructor(config) {
38
46
  this.config = config;
@@ -45,53 +53,60 @@ export class BrowserSession {
45
53
  try {
46
54
  let result;
47
55
  switch (action) {
48
- case 'open':
49
- result = await this.open(String(args.url || ''));
56
+ case "open":
57
+ result = await this.open(String(args.url || ""));
50
58
  break;
51
- case 'click':
59
+ case "click":
52
60
  result = await this.click(Number(args.target));
53
61
  break;
54
- case 'type':
55
- result = await this.type(Number(args.target), String(args.text || ''));
62
+ case "type":
63
+ result = await this.type(Number(args.target), String(args.text || ""));
56
64
  break;
57
- case 'scroll':
58
- result = await this.scroll(String(args.direction || 'down'));
65
+ case "scroll":
66
+ result = await this.scroll(String(args.direction || "down"));
59
67
  break;
60
- case 'back':
68
+ case "back":
61
69
  result = await this.back();
62
70
  break;
63
- case 'forward':
71
+ case "forward":
64
72
  result = await this.forward();
65
73
  break;
66
- case 'screenshot':
74
+ case "screenshot":
67
75
  result = await this.screenshot();
68
76
  break;
69
- case 'snapshot':
77
+ case "snapshot":
70
78
  result = await this.snapshot();
71
79
  break;
72
- case 'close':
80
+ case "close":
73
81
  result = await this.close();
74
82
  break;
75
- case 'wait':
83
+ case "wait":
76
84
  result = await this.wait(Number(args.ms || 1000));
77
85
  break;
78
- default: return { success: false, output: t('browser.unknown_action', { action }) };
86
+ default:
87
+ return {
88
+ success: false,
89
+ output: t("browser.unknown_action", { action }),
90
+ };
79
91
  }
80
- if (action !== 'open') {
81
- const warning = this.actionTracker.record(action, args, this.page?.url() || '');
92
+ if (action !== "open") {
93
+ const warning = this.actionTracker.record(action, args, this.page?.url() || "");
82
94
  if (warning && result.success) {
83
- result.output = result.output + '\n\n⚠️ ' + warning;
95
+ result.output = result.output + "\n\n⚠️ " + warning;
84
96
  }
85
97
  }
86
98
  return result;
87
99
  }
88
100
  catch (err) {
89
- return { success: false, output: t('browser.error', { message: err.message }) };
101
+ return {
102
+ success: false,
103
+ output: t("browser.error", { message: err.message }),
104
+ };
90
105
  }
91
106
  }
92
107
  async ensurePage() {
93
108
  if (!this.page) {
94
- return { success: false, output: t('browser.no_page') };
109
+ return { success: false, output: t("browser.no_page") };
95
110
  }
96
111
  return null;
97
112
  }
@@ -100,11 +115,14 @@ export class BrowserSession {
100
115
  return;
101
116
  this.browser = await chromium.launch({ headless: this.config.headless });
102
117
  this.context = await this.browser.newContext({
103
- viewport: { width: this.config.viewportWidth, height: this.config.viewportHeight },
118
+ viewport: {
119
+ width: this.config.viewportWidth,
120
+ height: this.config.viewportHeight,
121
+ },
104
122
  });
105
123
  const savedCookies = await this.cookieStore.load();
106
124
  if (savedCookies.length > 0) {
107
- await this.context.addCookies(savedCookies.map(c => ({
125
+ await this.context.addCookies(savedCookies.map((c) => ({
108
126
  ...c,
109
127
  sameSite: c.sameSite,
110
128
  })));
@@ -120,7 +138,7 @@ export class BrowserSession {
120
138
  }
121
139
  async takeSnapshot() {
122
140
  if (!this.page)
123
- return 'No page open.';
141
+ return "No page open.";
124
142
  await this.page.evaluate(buildIndexInjectionScript());
125
143
  const html = await this.page.content();
126
144
  const url = this.page.url();
@@ -138,19 +156,28 @@ export class BrowserSession {
138
156
  }
139
157
  async open(url) {
140
158
  if (!url)
141
- return { success: false, output: t('browser.url_required') };
142
- if (!url.startsWith('http://') && !url.startsWith('https://')) {
143
- url = 'https://' + url;
159
+ return { success: false, output: t("browser.url_required") };
160
+ if (!url.startsWith("http://") &&
161
+ !url.startsWith("https://") &&
162
+ !url.startsWith("file://")) {
163
+ const isLocalhost = /^(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?$/i.test(url);
164
+ url = isLocalhost ? "http://" + url : "https://" + url;
144
165
  }
145
166
  await this.launch();
146
167
  if (!this.page)
147
- return { success: false, output: t('browser.create_page_failed') };
168
+ return { success: false, output: t("browser.create_page_failed") };
148
169
  this.actionTracker.reset();
149
170
  try {
150
- await this.page.goto(url, { waitUntil: 'domcontentloaded', timeout: this.config.navigationTimeout });
171
+ await this.page.goto(url, {
172
+ waitUntil: "domcontentloaded",
173
+ timeout: this.config.navigationTimeout,
174
+ });
151
175
  }
152
176
  catch (err) {
153
- return { success: false, output: t('browser.nav_failed', { message: err.message }) };
177
+ return {
178
+ success: false,
179
+ output: t("browser.nav_failed", { message: err.message }),
180
+ };
154
181
  }
155
182
  const snapshot = await this.takeSnapshot();
156
183
  await this.saveCookies();
@@ -161,21 +188,26 @@ export class BrowserSession {
161
188
  if (err)
162
189
  return err;
163
190
  if (!this.page)
164
- return { success: false, output: 'No page' };
191
+ return { success: false, output: "No page" };
165
192
  if (!target || target < 1) {
166
- return { success: false, output: t('browser.invalid_target') };
193
+ return { success: false, output: t("browser.invalid_target") };
167
194
  }
168
195
  try {
169
196
  const script = buildClickScript(target);
170
197
  await this.page.evaluate(script);
171
- await this.page.waitForLoadState('domcontentloaded', { timeout: 5000 }).catch(() => { });
172
- await new Promise(r => setTimeout(r, 500));
198
+ await this.page
199
+ .waitForLoadState("domcontentloaded", { timeout: 5000 })
200
+ .catch(() => { });
201
+ await new Promise((r) => setTimeout(r, 500));
173
202
  const snapshot = await this.takeSnapshot();
174
203
  await this.saveCookies();
175
204
  return { success: true, output: snapshot };
176
205
  }
177
206
  catch (err) {
178
- return { success: false, output: t('browser.click_failed', { message: err.message }) };
207
+ return {
208
+ success: false,
209
+ output: t("browser.click_failed", { message: err.message }),
210
+ };
179
211
  }
180
212
  }
181
213
  async type(target, text) {
@@ -183,12 +215,12 @@ export class BrowserSession {
183
215
  if (err)
184
216
  return err;
185
217
  if (!this.page)
186
- return { success: false, output: 'No page' };
218
+ return { success: false, output: "No page" };
187
219
  if (!target || target < 1) {
188
- return { success: false, output: t('browser.invalid_target_short') };
220
+ return { success: false, output: t("browser.invalid_target_short") };
189
221
  }
190
222
  if (!text) {
191
- return { success: false, output: t('browser.text_required') };
223
+ return { success: false, output: t("browser.text_required") };
192
224
  }
193
225
  try {
194
226
  const script = buildTypeScript(target, text);
@@ -197,7 +229,10 @@ export class BrowserSession {
197
229
  return { success: true, output: snapshot };
198
230
  }
199
231
  catch (err) {
200
- return { success: false, output: t('browser.type_failed', { message: err.message }) };
232
+ return {
233
+ success: false,
234
+ output: t("browser.type_failed", { message: err.message }),
235
+ };
201
236
  }
202
237
  }
203
238
  async scroll(direction) {
@@ -205,19 +240,22 @@ export class BrowserSession {
205
240
  if (err)
206
241
  return err;
207
242
  if (!this.page)
208
- return { success: false, output: 'No page' };
243
+ return { success: false, output: "No page" };
209
244
  const dir = direction;
210
- if (!['up', 'down', 'top', 'bottom'].includes(dir)) {
211
- return { success: false, output: t('browser.direction_invalid') };
245
+ if (!["up", "down", "top", "bottom"].includes(dir)) {
246
+ return { success: false, output: t("browser.direction_invalid") };
212
247
  }
213
248
  try {
214
249
  await this.page.evaluate(buildScrollScript(dir));
215
- await new Promise(r => setTimeout(r, 300));
250
+ await new Promise((r) => setTimeout(r, 300));
216
251
  const snapshot = await this.takeSnapshot();
217
252
  return { success: true, output: snapshot };
218
253
  }
219
254
  catch (err) {
220
- return { success: false, output: t('browser.scroll_failed', { message: err.message }) };
255
+ return {
256
+ success: false,
257
+ output: t("browser.scroll_failed", { message: err.message }),
258
+ };
221
259
  }
222
260
  }
223
261
  async back() {
@@ -225,9 +263,14 @@ export class BrowserSession {
225
263
  if (err)
226
264
  return err;
227
265
  if (!this.page)
228
- return { success: false, output: 'No page' };
229
- await this.page.goBack({ waitUntil: 'domcontentloaded', timeout: this.config.navigationTimeout }).catch(() => { });
230
- await new Promise(r => setTimeout(r, 300));
266
+ return { success: false, output: "No page" };
267
+ await this.page
268
+ .goBack({
269
+ waitUntil: "domcontentloaded",
270
+ timeout: this.config.navigationTimeout,
271
+ })
272
+ .catch(() => { });
273
+ await new Promise((r) => setTimeout(r, 300));
231
274
  const snapshot = await this.takeSnapshot();
232
275
  return { success: true, output: snapshot };
233
276
  }
@@ -236,9 +279,14 @@ export class BrowserSession {
236
279
  if (err)
237
280
  return err;
238
281
  if (!this.page)
239
- return { success: false, output: 'No page' };
240
- await this.page.goForward({ waitUntil: 'domcontentloaded', timeout: this.config.navigationTimeout }).catch(() => { });
241
- await new Promise(r => setTimeout(r, 300));
282
+ return { success: false, output: "No page" };
283
+ await this.page
284
+ .goForward({
285
+ waitUntil: "domcontentloaded",
286
+ timeout: this.config.navigationTimeout,
287
+ })
288
+ .catch(() => { });
289
+ await new Promise((r) => setTimeout(r, 300));
242
290
  const snapshot = await this.takeSnapshot();
243
291
  return { success: true, output: snapshot };
244
292
  }
@@ -247,8 +295,8 @@ export class BrowserSession {
247
295
  if (err)
248
296
  return err;
249
297
  if (!this.page)
250
- return { success: false, output: 'No page' };
251
- const buffer = await this.page.screenshot({ type: 'png', fullPage: false });
298
+ return { success: false, output: "No page" };
299
+ const buffer = await this.page.screenshot({ type: "png", fullPage: false });
252
300
  const snapshot = await this.takeSnapshot();
253
301
  return { success: true, output: snapshot, screenshot: buffer };
254
302
  }
@@ -263,7 +311,7 @@ export class BrowserSession {
263
311
  const err = await this.ensurePage();
264
312
  if (err)
265
313
  return err;
266
- await new Promise(r => setTimeout(r, Math.min(ms, 10000)));
314
+ await new Promise((r) => setTimeout(r, Math.min(ms, 10000)));
267
315
  const snapshot = await this.takeSnapshot();
268
316
  return { success: true, output: snapshot };
269
317
  }
@@ -282,6 +330,6 @@ export class BrowserSession {
282
330
  this.browser = null;
283
331
  }
284
332
  this.state = { isOpen: false, url: null, title: null, elementCount: 0 };
285
- return { success: true, output: t('browser.closed') };
333
+ return { success: true, output: t("browser.closed") };
286
334
  }
287
335
  }