micro-models-agent 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +172 -31
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2224,6 +2224,8 @@ var init_defaults = __esm(() => {
|
|
|
2224
2224
|
enabled: true,
|
|
2225
2225
|
headless: true,
|
|
2226
2226
|
maxElements: 30,
|
|
2227
|
+
maxContentChars: 2500,
|
|
2228
|
+
maxConsoleEntries: 20,
|
|
2227
2229
|
viewportWidth: 1280,
|
|
2228
2230
|
viewportHeight: 720,
|
|
2229
2231
|
navigationTimeout: 15000
|
|
@@ -2784,6 +2786,10 @@ Use this knowledge to answer the user's question.`,
|
|
|
2784
2786
|
"browser.no_page_short": "No page",
|
|
2785
2787
|
"browser.no_elements": "(no interactive elements on page)",
|
|
2786
2788
|
"browser.more_elements": "... and more elements not shown. Use scroll or search to find others.",
|
|
2789
|
+
"browser.content_header": "Content:",
|
|
2790
|
+
"browser.console_header": "Console:",
|
|
2791
|
+
"browser.network_errors_header": "Network errors:",
|
|
2792
|
+
"browser.truncated": "... (truncated)",
|
|
2787
2793
|
"pipeline.invalid": "Invalid pipeline: name and steps required",
|
|
2788
2794
|
"pipeline.step_missing_fields": "Step missing required fields (id, agent, prompt): {step}",
|
|
2789
2795
|
"pipeline.circular": "Circular dependency: {stepId}",
|
|
@@ -3357,6 +3363,10 @@ var init_ru = __esm(() => {
|
|
|
3357
3363
|
"browser.no_page_short": "Нет страницы",
|
|
3358
3364
|
"browser.no_elements": "(нет интерактивных элементов на странице)",
|
|
3359
3365
|
"browser.more_elements": "... и другие элементы не показаны. Используйте прокрутку или поиск.",
|
|
3366
|
+
"browser.content_header": "Содержимое:",
|
|
3367
|
+
"browser.console_header": "Консоль:",
|
|
3368
|
+
"browser.network_errors_header": "Сетевые ошибки:",
|
|
3369
|
+
"browser.truncated": "... (обрезано)",
|
|
3360
3370
|
"pipeline.invalid": "Невалидный пайплайн: требуются name и steps",
|
|
3361
3371
|
"pipeline.step_missing_fields": "Шаг не содержит обязательных полей (id, agent, prompt): {step}",
|
|
3362
3372
|
"pipeline.circular": "Циклическая зависимость: {stepId}",
|
|
@@ -13660,6 +13670,22 @@ var init_recall = __esm(() => {
|
|
|
13660
13670
|
};
|
|
13661
13671
|
});
|
|
13662
13672
|
|
|
13673
|
+
// src/modules/browser/types.ts
|
|
13674
|
+
var DEFAULT_BROWSER_CONFIG;
|
|
13675
|
+
var init_types = __esm(() => {
|
|
13676
|
+
DEFAULT_BROWSER_CONFIG = {
|
|
13677
|
+
headless: true,
|
|
13678
|
+
maxElements: 30,
|
|
13679
|
+
maxContentChars: 2500,
|
|
13680
|
+
maxConsoleEntries: 20,
|
|
13681
|
+
screenshotMaxWidth: 1280,
|
|
13682
|
+
cookieDir: "",
|
|
13683
|
+
viewportWidth: 1280,
|
|
13684
|
+
viewportHeight: 720,
|
|
13685
|
+
navigationTimeout: 15000
|
|
13686
|
+
};
|
|
13687
|
+
});
|
|
13688
|
+
|
|
13663
13689
|
// src/modules/browser/snapshot.ts
|
|
13664
13690
|
function inferRole(tag, type) {
|
|
13665
13691
|
const t2 = tag.toLowerCase();
|
|
@@ -13747,35 +13773,69 @@ function extractInteractiveElements(html, maxElements = 30) {
|
|
|
13747
13773
|
}
|
|
13748
13774
|
return elements;
|
|
13749
13775
|
}
|
|
13750
|
-
function
|
|
13776
|
+
function truncateText(text, maxChars) {
|
|
13777
|
+
if (maxChars <= 0)
|
|
13778
|
+
return "";
|
|
13779
|
+
if (text.length <= maxChars)
|
|
13780
|
+
return text;
|
|
13781
|
+
const cut = text.slice(0, maxChars);
|
|
13782
|
+
const lastNewline = cut.lastIndexOf(`
|
|
13783
|
+
`);
|
|
13784
|
+
const safe = lastNewline > maxChars * 0.6 ? cut.slice(0, lastNewline) : cut;
|
|
13785
|
+
return `${safe}
|
|
13786
|
+
${t("browser.truncated")}`;
|
|
13787
|
+
}
|
|
13788
|
+
function formatSnapshot(snapshot, maxContentChars = DEFAULT_BROWSER_CONFIG.maxContentChars) {
|
|
13751
13789
|
const lines = [];
|
|
13752
13790
|
lines.push(`Page: "${snapshot.title}"`);
|
|
13753
13791
|
lines.push(`URL: ${snapshot.url}`);
|
|
13754
13792
|
lines.push("");
|
|
13755
13793
|
if (snapshot.elements.length === 0 && !snapshot.truncated) {
|
|
13756
13794
|
lines.push(t("browser.no_elements"));
|
|
13757
|
-
|
|
13758
|
-
|
|
13795
|
+
} else {
|
|
13796
|
+
for (const el of snapshot.elements) {
|
|
13797
|
+
let line = `[${el.index}] ${el.role}`;
|
|
13798
|
+
if (el.name)
|
|
13799
|
+
line += ` "${el.name}"`;
|
|
13800
|
+
if (el.href)
|
|
13801
|
+
line += ` → ${el.href}`;
|
|
13802
|
+
if (el.value)
|
|
13803
|
+
line += ` = "${el.value}"`;
|
|
13804
|
+
lines.push(line);
|
|
13805
|
+
}
|
|
13806
|
+
if (snapshot.truncated) {
|
|
13807
|
+
lines.push("");
|
|
13808
|
+
lines.push(t("browser.more_elements"));
|
|
13809
|
+
}
|
|
13810
|
+
}
|
|
13811
|
+
if (snapshot.content) {
|
|
13812
|
+
lines.push("");
|
|
13813
|
+
lines.push(t("browser.content_header"));
|
|
13814
|
+
for (const line of truncateText(snapshot.content, maxContentChars).split(`
|
|
13815
|
+
`)) {
|
|
13816
|
+
lines.push(`- ${line}`);
|
|
13817
|
+
}
|
|
13759
13818
|
}
|
|
13760
|
-
|
|
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) {
|
|
13819
|
+
if (snapshot.console.length > 0) {
|
|
13771
13820
|
lines.push("");
|
|
13772
|
-
lines.push(t("browser.
|
|
13821
|
+
lines.push(t("browser.console_header"));
|
|
13822
|
+
for (const entry of snapshot.console) {
|
|
13823
|
+
lines.push(`[${entry.type}] ${entry.text}`);
|
|
13824
|
+
}
|
|
13825
|
+
}
|
|
13826
|
+
if (snapshot.networkErrors.length > 0) {
|
|
13827
|
+
lines.push("");
|
|
13828
|
+
lines.push(t("browser.network_errors_header"));
|
|
13829
|
+
for (const err of snapshot.networkErrors) {
|
|
13830
|
+
lines.push(`${err.method} ${err.url} → ${err.error}`);
|
|
13831
|
+
}
|
|
13773
13832
|
}
|
|
13774
13833
|
return lines.join(`
|
|
13775
13834
|
`);
|
|
13776
13835
|
}
|
|
13777
13836
|
var init_snapshot = __esm(() => {
|
|
13778
13837
|
init_i18n();
|
|
13838
|
+
init_types();
|
|
13779
13839
|
});
|
|
13780
13840
|
|
|
13781
13841
|
// src/modules/browser/actions.ts
|
|
@@ -13822,6 +13882,36 @@ function buildIndexInjectionScript() {
|
|
|
13822
13882
|
});
|
|
13823
13883
|
`;
|
|
13824
13884
|
}
|
|
13885
|
+
function buildTextExtractionScript() {
|
|
13886
|
+
return `
|
|
13887
|
+
const contentTags = new Set(['h1','h2','h3','h4','h5','h6','p','li','article','main','section','blockquote','pre','td','th','dt','dd','figcaption']);
|
|
13888
|
+
const out = [];
|
|
13889
|
+
const seen = new Set();
|
|
13890
|
+
const isHidden = (el) => {
|
|
13891
|
+
const st = window.getComputedStyle(el);
|
|
13892
|
+
return st.display === 'none' || st.visibility === 'hidden';
|
|
13893
|
+
};
|
|
13894
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {
|
|
13895
|
+
acceptNode: (node) => {
|
|
13896
|
+
const tag = node.tagName ? node.tagName.toLowerCase() : '';
|
|
13897
|
+
if (!contentTags.has(tag)) return NodeFilter.FILTER_SKIP;
|
|
13898
|
+
if (isHidden(node)) return NodeFilter.FILTER_REJECT;
|
|
13899
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
13900
|
+
}
|
|
13901
|
+
});
|
|
13902
|
+
let node;
|
|
13903
|
+
while ((node = walker.nextNode())) {
|
|
13904
|
+
const tag = node.tagName.toLowerCase();
|
|
13905
|
+
const text = (node.textContent || '').replace(/\\s+/g, ' ').trim();
|
|
13906
|
+
if (!text) continue;
|
|
13907
|
+
if (seen.has(text)) continue;
|
|
13908
|
+
seen.add(text);
|
|
13909
|
+
const line = text.length > 200 ? text.slice(0, 200) + '…' : text;
|
|
13910
|
+
out.push('[' + tag + '] ' + line);
|
|
13911
|
+
}
|
|
13912
|
+
return out.join('\\n');
|
|
13913
|
+
`;
|
|
13914
|
+
}
|
|
13825
13915
|
|
|
13826
13916
|
// src/modules/browser/cookie-store.ts
|
|
13827
13917
|
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
@@ -13855,6 +13945,33 @@ import {
|
|
|
13855
13945
|
chromium
|
|
13856
13946
|
} from "playwright";
|
|
13857
13947
|
|
|
13948
|
+
class ConsoleBuffer {
|
|
13949
|
+
entries = [];
|
|
13950
|
+
maxEntries;
|
|
13951
|
+
constructor(maxEntries = 20) {
|
|
13952
|
+
this.maxEntries = maxEntries;
|
|
13953
|
+
}
|
|
13954
|
+
add(type, text) {
|
|
13955
|
+
const clean = String(text).replace(/\s+/g, " ").trim();
|
|
13956
|
+
if (!clean)
|
|
13957
|
+
return;
|
|
13958
|
+
const line = clean.length > CONSOLE_MAX_LINE ? clean.slice(0, CONSOLE_MAX_LINE) + "…" : clean;
|
|
13959
|
+
this.entries.push({ type, text: line });
|
|
13960
|
+
if (this.entries.length > this.maxEntries) {
|
|
13961
|
+
this.entries.splice(0, this.entries.length - this.maxEntries);
|
|
13962
|
+
}
|
|
13963
|
+
}
|
|
13964
|
+
clear() {
|
|
13965
|
+
this.entries = [];
|
|
13966
|
+
}
|
|
13967
|
+
getAll() {
|
|
13968
|
+
return [...this.entries];
|
|
13969
|
+
}
|
|
13970
|
+
get size() {
|
|
13971
|
+
return this.entries.length;
|
|
13972
|
+
}
|
|
13973
|
+
}
|
|
13974
|
+
|
|
13858
13975
|
class BrowserActionTracker {
|
|
13859
13976
|
history = [];
|
|
13860
13977
|
threshold;
|
|
@@ -13893,9 +14010,12 @@ class BrowserSession {
|
|
|
13893
14010
|
elementCount: 0
|
|
13894
14011
|
};
|
|
13895
14012
|
actionTracker = new BrowserActionTracker(3);
|
|
14013
|
+
consoleBuffer;
|
|
14014
|
+
networkErrors = [];
|
|
13896
14015
|
constructor(config) {
|
|
13897
14016
|
this.config = config;
|
|
13898
14017
|
this.cookieStore = new CookieStore(config.cookieDir);
|
|
14018
|
+
this.consoleBuffer = new ConsoleBuffer(config.maxConsoleEntries);
|
|
13899
14019
|
}
|
|
13900
14020
|
getState() {
|
|
13901
14021
|
return { ...this.state };
|
|
@@ -13981,6 +14101,20 @@ class BrowserSession {
|
|
|
13981
14101
|
}
|
|
13982
14102
|
this.page = await this.context.newPage();
|
|
13983
14103
|
this.page.setDefaultTimeout(this.config.navigationTimeout);
|
|
14104
|
+
this.page.on("console", (msg) => {
|
|
14105
|
+
this.consoleBuffer.add(msg.type(), msg.text());
|
|
14106
|
+
});
|
|
14107
|
+
this.page.on("pageerror", (err) => {
|
|
14108
|
+
this.consoleBuffer.add("pageerror", `Page error: ${err.message}`);
|
|
14109
|
+
});
|
|
14110
|
+
this.page.on("requestfailed", (req) => {
|
|
14111
|
+
const failure = req.failure();
|
|
14112
|
+
this.networkErrors.push({
|
|
14113
|
+
method: req.method(),
|
|
14114
|
+
url: req.url(),
|
|
14115
|
+
error: failure?.errorText || "unknown"
|
|
14116
|
+
});
|
|
14117
|
+
});
|
|
13984
14118
|
}
|
|
13985
14119
|
async saveCookies() {
|
|
13986
14120
|
if (!this.context)
|
|
@@ -13995,6 +14129,12 @@ class BrowserSession {
|
|
|
13995
14129
|
const html = await this.page.content();
|
|
13996
14130
|
const url = this.page.url();
|
|
13997
14131
|
const title = await this.page.title();
|
|
14132
|
+
let content = "";
|
|
14133
|
+
try {
|
|
14134
|
+
content = await this.page.evaluate(buildTextExtractionScript());
|
|
14135
|
+
} catch {
|
|
14136
|
+
content = "";
|
|
14137
|
+
}
|
|
13998
14138
|
const allElements = extractInteractiveElements(html, this.config.maxElements + 5);
|
|
13999
14139
|
const truncated = allElements.length > this.config.maxElements;
|
|
14000
14140
|
const elements = allElements.slice(0, this.config.maxElements);
|
|
@@ -14004,7 +14144,15 @@ class BrowserSession {
|
|
|
14004
14144
|
title,
|
|
14005
14145
|
elementCount: elements.length
|
|
14006
14146
|
};
|
|
14007
|
-
return formatSnapshot({
|
|
14147
|
+
return formatSnapshot({
|
|
14148
|
+
url,
|
|
14149
|
+
title,
|
|
14150
|
+
elements,
|
|
14151
|
+
content,
|
|
14152
|
+
console: this.consoleBuffer.getAll(),
|
|
14153
|
+
networkErrors: this.networkErrors.slice(-5),
|
|
14154
|
+
truncated
|
|
14155
|
+
});
|
|
14008
14156
|
}
|
|
14009
14157
|
async open(url) {
|
|
14010
14158
|
if (!url)
|
|
@@ -14017,6 +14165,8 @@ class BrowserSession {
|
|
|
14017
14165
|
if (!this.page)
|
|
14018
14166
|
return { success: false, output: t("browser.create_page_failed") };
|
|
14019
14167
|
this.actionTracker.reset();
|
|
14168
|
+
this.consoleBuffer.clear();
|
|
14169
|
+
this.networkErrors = [];
|
|
14020
14170
|
try {
|
|
14021
14171
|
await this.page.goto(url, {
|
|
14022
14172
|
waitUntil: "domcontentloaded",
|
|
@@ -14173,26 +14323,13 @@ class BrowserSession {
|
|
|
14173
14323
|
return { success: true, output: t("browser.closed") };
|
|
14174
14324
|
}
|
|
14175
14325
|
}
|
|
14326
|
+
var CONSOLE_MAX_LINE = 200;
|
|
14176
14327
|
var init_session = __esm(() => {
|
|
14177
14328
|
init_snapshot();
|
|
14178
14329
|
init_cookie_store();
|
|
14179
14330
|
init_i18n();
|
|
14180
14331
|
});
|
|
14181
14332
|
|
|
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
14333
|
// src/tools/browser.ts
|
|
14197
14334
|
import { join as join18 } from "path";
|
|
14198
14335
|
function getSession(ctx) {
|
|
@@ -14202,6 +14339,8 @@ function getSession(ctx) {
|
|
|
14202
14339
|
...DEFAULT_BROWSER_CONFIG,
|
|
14203
14340
|
headless: ctx.config.browser?.headless ?? true,
|
|
14204
14341
|
maxElements: ctx.config.browser?.maxElements ?? 30,
|
|
14342
|
+
maxContentChars: ctx.config.browser?.maxContentChars ?? 2500,
|
|
14343
|
+
maxConsoleEntries: ctx.config.browser?.maxConsoleEntries ?? 20,
|
|
14205
14344
|
navigationTimeout: ctx.config.browser?.navigationTimeout ?? 15000,
|
|
14206
14345
|
viewportWidth: ctx.config.browser?.viewportWidth ?? 1280,
|
|
14207
14346
|
viewportHeight: ctx.config.browser?.viewportHeight ?? 720,
|
|
@@ -14230,7 +14369,8 @@ function createBrowserTool() {
|
|
|
14230
14369
|
tags: ["browser", "vision"],
|
|
14231
14370
|
description: [
|
|
14232
14371
|
"Control a headless browser. Navigate pages, click elements, type text, scroll, take screenshots.",
|
|
14233
|
-
"
|
|
14372
|
+
"Each snapshot returns: a numbered list of interactive elements, the visible page text (Content section), browser console messages, and network errors.",
|
|
14373
|
+
"Use the Content section to understand what the page says; use element numbers as targets for click/type.",
|
|
14234
14374
|
"Actions: open (url), click (target), type (target, text), scroll (direction), back, forward, screenshot, snapshot, close, wait (ms)."
|
|
14235
14375
|
].join(" "),
|
|
14236
14376
|
parameters: {
|
|
@@ -17002,6 +17142,7 @@ class BrowserModule {
|
|
|
17002
17142
|
content: [
|
|
17003
17143
|
"You have a headless browser tool. Use it to navigate websites, click links, fill forms, and read page content.",
|
|
17004
17144
|
"Workflow: open(url) → read snapshot → click/type on element numbers → read updated snapshot.",
|
|
17145
|
+
'Each snapshot includes a "Content" section with the visible page text, a "Console" section with browser messages, and network errors. Use these to understand the page, detect JS errors, and verify the result of your actions.',
|
|
17005
17146
|
'Always start with "open" action. Use element numbers from snapshot for click/type targets.',
|
|
17006
17147
|
'Use "screenshot" action only if the model supports vision. Otherwise rely on the text snapshot.'
|
|
17007
17148
|
].join(`
|