open-agents-ai 0.187.469 → 0.187.470
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/index.js +245 -8
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -250490,6 +250490,11 @@ import { execSync as execSync20, exec } from "node:child_process";
|
|
|
250490
250490
|
import { existsSync as existsSync24, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8 } from "node:fs";
|
|
250491
250491
|
import { join as join37, dirname as dirname11 } from "node:path";
|
|
250492
250492
|
import { homedir as homedir9 } from "node:os";
|
|
250493
|
+
function pushBounded(buf, item) {
|
|
250494
|
+
buf.push(item);
|
|
250495
|
+
if (buf.length > MAX_BUFFER)
|
|
250496
|
+
buf.splice(0, buf.length - MAX_BUFFER);
|
|
250497
|
+
}
|
|
250493
250498
|
async function ensurePlaywright() {
|
|
250494
250499
|
if (pw)
|
|
250495
250500
|
return null;
|
|
@@ -250529,28 +250534,78 @@ async function ensureBrowser() {
|
|
|
250529
250534
|
userAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
250530
250535
|
});
|
|
250531
250536
|
page = await context.newPage();
|
|
250532
|
-
page
|
|
250533
|
-
try {
|
|
250534
|
-
await dialog.dismiss();
|
|
250535
|
-
} catch {
|
|
250536
|
-
}
|
|
250537
|
-
});
|
|
250537
|
+
attachDiagnosticListeners(page);
|
|
250538
250538
|
} catch (err) {
|
|
250539
250539
|
return `Failed to launch browser: ${err instanceof Error ? err.message : String(err)}`;
|
|
250540
250540
|
}
|
|
250541
250541
|
}
|
|
250542
250542
|
if (!page || page.isClosed?.()) {
|
|
250543
250543
|
page = await context.newPage();
|
|
250544
|
+
attachDiagnosticListeners(page);
|
|
250544
250545
|
}
|
|
250545
250546
|
return null;
|
|
250546
250547
|
}
|
|
250548
|
+
function attachDiagnosticListeners(p2) {
|
|
250549
|
+
p2.on("dialog", async (dialog) => {
|
|
250550
|
+
try {
|
|
250551
|
+
await dialog.dismiss();
|
|
250552
|
+
} catch {
|
|
250553
|
+
}
|
|
250554
|
+
});
|
|
250555
|
+
p2.on("console", (msg) => {
|
|
250556
|
+
try {
|
|
250557
|
+
const loc = msg.location?.();
|
|
250558
|
+
pushBounded(consoleBuffer, {
|
|
250559
|
+
ts: Date.now(),
|
|
250560
|
+
type: String(msg.type?.() ?? "log"),
|
|
250561
|
+
text: String(msg.text?.() ?? "").slice(0, 600),
|
|
250562
|
+
loc: loc?.url ? `${loc.url}:${loc.lineNumber ?? 0}:${loc.columnNumber ?? 0}` : void 0
|
|
250563
|
+
});
|
|
250564
|
+
} catch {
|
|
250565
|
+
}
|
|
250566
|
+
});
|
|
250567
|
+
p2.on("pageerror", (err) => {
|
|
250568
|
+
pushBounded(errorBuffer, {
|
|
250569
|
+
ts: Date.now(),
|
|
250570
|
+
message: String(err?.message ?? err).slice(0, 600),
|
|
250571
|
+
stack: typeof err?.stack === "string" ? err.stack.slice(0, 1500) : void 0
|
|
250572
|
+
});
|
|
250573
|
+
});
|
|
250574
|
+
p2.on("requestfailed", (req2) => {
|
|
250575
|
+
pushBounded(networkBuffer, {
|
|
250576
|
+
ts: Date.now(),
|
|
250577
|
+
method: String(req2.method?.() ?? "GET"),
|
|
250578
|
+
url: String(req2.url?.() ?? "").slice(0, 600),
|
|
250579
|
+
failure: String(req2.failure?.()?.errorText ?? "request failed").slice(0, 200),
|
|
250580
|
+
ok: false
|
|
250581
|
+
});
|
|
250582
|
+
});
|
|
250583
|
+
p2.on("response", (resp) => {
|
|
250584
|
+
try {
|
|
250585
|
+
const status = Number(resp.status?.() ?? 0);
|
|
250586
|
+
pushBounded(networkBuffer, {
|
|
250587
|
+
ts: Date.now(),
|
|
250588
|
+
method: String(resp.request?.()?.method?.() ?? "GET"),
|
|
250589
|
+
url: String(resp.url?.() ?? "").slice(0, 600),
|
|
250590
|
+
status,
|
|
250591
|
+
ok: status >= 200 && status < 400
|
|
250592
|
+
});
|
|
250593
|
+
} catch {
|
|
250594
|
+
}
|
|
250595
|
+
});
|
|
250596
|
+
}
|
|
250597
|
+
function clearDiagnosticBuffers() {
|
|
250598
|
+
consoleBuffer = [];
|
|
250599
|
+
networkBuffer = [];
|
|
250600
|
+
errorBuffer = [];
|
|
250601
|
+
}
|
|
250547
250602
|
function ok(output, start2) {
|
|
250548
250603
|
return { success: true, output, durationMs: Date.now() - start2 };
|
|
250549
250604
|
}
|
|
250550
250605
|
function fail(error, start2) {
|
|
250551
250606
|
return { success: false, output: "", error, durationMs: Date.now() - start2 };
|
|
250552
250607
|
}
|
|
250553
|
-
var pw, browser2, context, page, dynamicImport, PlaywrightBrowserTool;
|
|
250608
|
+
var pw, browser2, context, page, MAX_BUFFER, consoleBuffer, networkBuffer, errorBuffer, dynamicImport, PlaywrightBrowserTool;
|
|
250554
250609
|
var init_playwright_browser = __esm({
|
|
250555
250610
|
"packages/execution/dist/tools/playwright-browser.js"() {
|
|
250556
250611
|
"use strict";
|
|
@@ -250558,10 +250613,14 @@ var init_playwright_browser = __esm({
|
|
|
250558
250613
|
browser2 = null;
|
|
250559
250614
|
context = null;
|
|
250560
250615
|
page = null;
|
|
250616
|
+
MAX_BUFFER = 200;
|
|
250617
|
+
consoleBuffer = [];
|
|
250618
|
+
networkBuffer = [];
|
|
250619
|
+
errorBuffer = [];
|
|
250561
250620
|
dynamicImport = new Function("mod", "return import(mod)");
|
|
250562
250621
|
PlaywrightBrowserTool = class {
|
|
250563
250622
|
name = "playwright_browser";
|
|
250564
|
-
description = "Full-scope Playwright browser automation. Launches a persistent headless Chromium session
|
|
250623
|
+
description = "Full-scope Playwright browser automation + diagnostic capture. Launches a persistent headless Chromium session. Beyond navigation/interaction, this tool buffers everything the running app emits (console messages, network requests, JS exceptions, accessibility tree) so the agent can verify what is ACTUALLY happening — not just what the build/test reports. Auto-installs Playwright + Chromium on first use. Diagnostic actions: console_logs, network_log, page_errors, a11y_snapshot, bounding_box, query_all, performance, cookies, storage, viewport, clear_diagnostics. Interaction actions: navigate, click, fill, type, press, select, check, hover. Capture actions: screenshot, pdf, content, innerText, innerHTML, getAttribute, evaluate. Workflow: navigate → screenshot or content → console_logs/network_log/page_errors to verify state → click/fill/type to drive UI → repeat.";
|
|
250565
250624
|
parameters = {
|
|
250566
250625
|
type: "object",
|
|
250567
250626
|
properties: {
|
|
@@ -250593,6 +250652,18 @@ var init_playwright_browser = __esm({
|
|
|
250593
250652
|
"goBack",
|
|
250594
250653
|
"goForward",
|
|
250595
250654
|
"reload",
|
|
250655
|
+
// FEAT-1: diagnostic capture actions
|
|
250656
|
+
"console_logs",
|
|
250657
|
+
"network_log",
|
|
250658
|
+
"page_errors",
|
|
250659
|
+
"a11y_snapshot",
|
|
250660
|
+
"bounding_box",
|
|
250661
|
+
"query_all",
|
|
250662
|
+
"performance",
|
|
250663
|
+
"cookies",
|
|
250664
|
+
"storage",
|
|
250665
|
+
"viewport",
|
|
250666
|
+
"clear_diagnostics",
|
|
250596
250667
|
"close"
|
|
250597
250668
|
],
|
|
250598
250669
|
description: "Action to perform:\n- navigate: go to a URL\n- click: click element by selector\n- fill: clear input and type text (for form fields)\n- type: type text character by character (simulates real typing)\n- press: press a key (Enter, Tab, Escape, etc.)\n- screenshot: capture page screenshot (saves to file)\n- evaluate: run JavaScript in page context\n- content: get page text content (readable, stripped)\n- innerText: get innerText of a specific element\n- select: select dropdown option by value\n- check/uncheck: toggle checkbox\n- hover: hover over element\n- wait: wait for a selector to appear\n- waitForNavigation: wait for page navigation to complete\n- waitForSelector: wait for element matching selector\n- title: get page title\n- url: get current URL\n- getAttribute: get element attribute value\n- innerHTML: get element's innerHTML\n- textContent: get element's textContent\n- goBack/goForward/reload: browser navigation\n- pdf: save page as PDF\n- close: close browser session"
|
|
@@ -250641,6 +250712,7 @@ var init_playwright_browser = __esm({
|
|
|
250641
250712
|
page = null;
|
|
250642
250713
|
context = null;
|
|
250643
250714
|
browser2 = null;
|
|
250715
|
+
clearDiagnosticBuffers();
|
|
250644
250716
|
return { success: true, output: "Browser closed.", durationMs: Date.now() - start2 };
|
|
250645
250717
|
}
|
|
250646
250718
|
const err = await ensureBrowser();
|
|
@@ -250831,6 +250903,171 @@ var init_playwright_browser = __esm({
|
|
|
250831
250903
|
await page.pdf({ path: pdfPath, format: "A4" });
|
|
250832
250904
|
return ok(`PDF saved to ${pdfPath}`, start2);
|
|
250833
250905
|
}
|
|
250906
|
+
// ── FEAT-1: Diagnostic capture ────────────────────────────────────
|
|
250907
|
+
case "console_logs": {
|
|
250908
|
+
const filter2 = (text || "").toLowerCase();
|
|
250909
|
+
const entries = filter2 ? consoleBuffer.filter((e2) => e2.type.toLowerCase().includes(filter2)) : consoleBuffer;
|
|
250910
|
+
const tail = entries.slice(-50);
|
|
250911
|
+
if (tail.length === 0) {
|
|
250912
|
+
return ok(`No console messages buffered yet${filter2 ? ` (filter="${filter2}")` : ""}. Buffer holds last 200 messages.`, start2);
|
|
250913
|
+
}
|
|
250914
|
+
const lines = tail.map((e2) => {
|
|
250915
|
+
const at = new Date(e2.ts).toISOString().slice(11, 19);
|
|
250916
|
+
return `[${at}] ${e2.type.toUpperCase()}: ${e2.text}${e2.loc ? ` (${e2.loc})` : ""}`;
|
|
250917
|
+
});
|
|
250918
|
+
return ok(`Console messages (${tail.length}/${entries.length} shown${filter2 ? `, filter="${filter2}"` : ""}):
|
|
250919
|
+
${lines.join("\n")}`, start2);
|
|
250920
|
+
}
|
|
250921
|
+
case "network_log": {
|
|
250922
|
+
const mode = (text || "").toLowerCase();
|
|
250923
|
+
let entries = networkBuffer;
|
|
250924
|
+
if (mode === "failed" || mode === "errors") {
|
|
250925
|
+
entries = entries.filter((e2) => e2.ok === false);
|
|
250926
|
+
}
|
|
250927
|
+
const tail = entries.slice(-50);
|
|
250928
|
+
if (tail.length === 0) {
|
|
250929
|
+
return ok(`No network entries buffered${mode ? ` (mode="${mode}")` : ""}. Navigate to a URL to populate.`, start2);
|
|
250930
|
+
}
|
|
250931
|
+
const lines = tail.map((e2) => {
|
|
250932
|
+
const at = new Date(e2.ts).toISOString().slice(11, 19);
|
|
250933
|
+
const tag = e2.failure ? `FAILED (${e2.failure})` : `${e2.status ?? "?"}`;
|
|
250934
|
+
return `[${at}] ${e2.method} ${tag} ${e2.url}`;
|
|
250935
|
+
});
|
|
250936
|
+
return ok(`Network log (${tail.length}/${entries.length} shown${mode ? `, mode="${mode}"` : ""}):
|
|
250937
|
+
${lines.join("\n")}`, start2);
|
|
250938
|
+
}
|
|
250939
|
+
case "page_errors": {
|
|
250940
|
+
if (errorBuffer.length === 0) {
|
|
250941
|
+
return ok("No uncaught page errors recorded.", start2);
|
|
250942
|
+
}
|
|
250943
|
+
const lines = errorBuffer.map((e2) => {
|
|
250944
|
+
const at = new Date(e2.ts).toISOString().slice(11, 19);
|
|
250945
|
+
return `[${at}] ${e2.message}${e2.stack ? `
|
|
250946
|
+
${e2.stack.split("\n").slice(0, 4).join("\n ")}` : ""}`;
|
|
250947
|
+
});
|
|
250948
|
+
return ok(`Uncaught page errors (${errorBuffer.length}):
|
|
250949
|
+
${lines.join("\n\n")}`, start2);
|
|
250950
|
+
}
|
|
250951
|
+
case "a11y_snapshot": {
|
|
250952
|
+
const root = selector ? await page.locator(selector).first().elementHandle() : null;
|
|
250953
|
+
const tree2 = await page.accessibility.snapshot({ root: root ?? void 0, interestingOnly: true });
|
|
250954
|
+
if (!tree2)
|
|
250955
|
+
return ok("No accessibility tree (page may be empty).", start2);
|
|
250956
|
+
const render2 = (n2, depth = 0) => {
|
|
250957
|
+
const pad = " ".repeat(depth);
|
|
250958
|
+
const role = n2.role ?? "?";
|
|
250959
|
+
const name10 = n2.name ? ` "${String(n2.name).slice(0, 80)}"` : "";
|
|
250960
|
+
const value3 = n2.value ? ` value="${String(n2.value).slice(0, 60)}"` : "";
|
|
250961
|
+
const checked = n2.checked != null ? ` checked=${n2.checked}` : "";
|
|
250962
|
+
const lines = [`${pad}${role}${name10}${value3}${checked}`];
|
|
250963
|
+
for (const child of (n2.children ?? []).slice(0, 30)) {
|
|
250964
|
+
lines.push(render2(child, depth + 1));
|
|
250965
|
+
}
|
|
250966
|
+
return lines.join("\n");
|
|
250967
|
+
};
|
|
250968
|
+
const out = render2(tree2).slice(0, 6e3);
|
|
250969
|
+
return ok(`Accessibility snapshot:
|
|
250970
|
+
${out}`, start2);
|
|
250971
|
+
}
|
|
250972
|
+
case "bounding_box": {
|
|
250973
|
+
if (!selector)
|
|
250974
|
+
return fail("selector is required", start2);
|
|
250975
|
+
const loc = page.locator(selector).first();
|
|
250976
|
+
const box = await loc.boundingBox();
|
|
250977
|
+
if (!box)
|
|
250978
|
+
return fail(`Element ${selector} has no bounding box (not rendered or detached)`, start2);
|
|
250979
|
+
return ok(JSON.stringify(box), start2);
|
|
250980
|
+
}
|
|
250981
|
+
case "query_all": {
|
|
250982
|
+
if (!selector)
|
|
250983
|
+
return fail("selector is required", start2);
|
|
250984
|
+
const handles = await page.locator(selector).all();
|
|
250985
|
+
if (handles.length === 0)
|
|
250986
|
+
return ok(`No elements matched ${selector}.`, start2);
|
|
250987
|
+
const max = Math.min(handles.length, 30);
|
|
250988
|
+
const lines = [];
|
|
250989
|
+
for (let i2 = 0; i2 < max; i2++) {
|
|
250990
|
+
try {
|
|
250991
|
+
const h = handles[i2];
|
|
250992
|
+
const txt = (await h.textContent())?.trim().slice(0, 120) ?? "";
|
|
250993
|
+
const tag = await h.evaluate((el) => (el.tagName || "?").toLowerCase());
|
|
250994
|
+
const id = await h.evaluate((el) => el.id || "");
|
|
250995
|
+
const cls = await h.evaluate((el) => (el.className || "").toString().slice(0, 80));
|
|
250996
|
+
lines.push(`[${i2}] <${tag}${id ? ` id="${id}"` : ""}${cls ? ` class="${cls}"` : ""}> ${txt}`);
|
|
250997
|
+
} catch (e2) {
|
|
250998
|
+
lines.push(`[${i2}] (error: ${e2 instanceof Error ? e2.message.slice(0, 80) : String(e2).slice(0, 80)})`);
|
|
250999
|
+
}
|
|
251000
|
+
}
|
|
251001
|
+
if (handles.length > max)
|
|
251002
|
+
lines.push(`... +${handles.length - max} more`);
|
|
251003
|
+
return ok(`Matched ${handles.length} element(s) for ${selector}:
|
|
251004
|
+
${lines.join("\n")}`, start2);
|
|
251005
|
+
}
|
|
251006
|
+
case "performance": {
|
|
251007
|
+
const data = await page.evaluate(`(() => {
|
|
251008
|
+
const perf = window.performance;
|
|
251009
|
+
const nav = (perf.getEntriesByType('navigation') || [])[0];
|
|
251010
|
+
const paints = (perf.getEntriesByType('paint') || []);
|
|
251011
|
+
return {
|
|
251012
|
+
url: window.location.href,
|
|
251013
|
+
domContentLoaded: nav ? nav.domContentLoadedEventEnd : null,
|
|
251014
|
+
loadComplete: nav ? nav.loadEventEnd : null,
|
|
251015
|
+
firstPaint: (paints.find(p => p.name === 'first-paint') || {}).startTime || null,
|
|
251016
|
+
firstContentfulPaint: (paints.find(p => p.name === 'first-contentful-paint') || {}).startTime || null,
|
|
251017
|
+
transferSize: nav ? nav.transferSize : null,
|
|
251018
|
+
encodedBodySize: nav ? nav.encodedBodySize : null,
|
|
251019
|
+
decodedBodySize: nav ? nav.decodedBodySize : null,
|
|
251020
|
+
};
|
|
251021
|
+
})()`);
|
|
251022
|
+
return ok(`Performance metrics:
|
|
251023
|
+
${JSON.stringify(data, null, 2)}`, start2);
|
|
251024
|
+
}
|
|
251025
|
+
case "cookies": {
|
|
251026
|
+
const ck = await context.cookies();
|
|
251027
|
+
if (!ck || ck.length === 0)
|
|
251028
|
+
return ok("No cookies set.", start2);
|
|
251029
|
+
const lines = ck.slice(0, 50).map((c9) => ` ${c9.name}=${String(c9.value).slice(0, 80)} (domain=${c9.domain}, path=${c9.path}${c9.httpOnly ? ", httpOnly" : ""}${c9.secure ? ", secure" : ""})`);
|
|
251030
|
+
return ok(`Cookies (${ck.length}):
|
|
251031
|
+
${lines.join("\n")}`, start2);
|
|
251032
|
+
}
|
|
251033
|
+
case "storage": {
|
|
251034
|
+
const data = await page.evaluate(`(() => {
|
|
251035
|
+
const dump = function(s) {
|
|
251036
|
+
var o = {};
|
|
251037
|
+
for (var i = 0; i < s.length; i++) {
|
|
251038
|
+
var k = s.key(i);
|
|
251039
|
+
if (k) o[k] = String(s.getItem(k) || '').slice(0, 200);
|
|
251040
|
+
}
|
|
251041
|
+
return o;
|
|
251042
|
+
};
|
|
251043
|
+
return {
|
|
251044
|
+
localStorage: dump(window.localStorage),
|
|
251045
|
+
sessionStorage: dump(window.sessionStorage),
|
|
251046
|
+
};
|
|
251047
|
+
})()`);
|
|
251048
|
+
return ok(`Storage:
|
|
251049
|
+
${JSON.stringify(data, null, 2)}`, start2);
|
|
251050
|
+
}
|
|
251051
|
+
case "viewport": {
|
|
251052
|
+
const v = (text || value2 || "").trim();
|
|
251053
|
+
const m2 = v.match(/^(\d+)\s*[x×]\s*(\d+)$/);
|
|
251054
|
+
if (m2) {
|
|
251055
|
+
const w = parseInt(m2[1], 10), h = parseInt(m2[2], 10);
|
|
251056
|
+
await page.setViewportSize({ width: w, height: h });
|
|
251057
|
+
return ok(`Viewport set to ${w}x${h}`, start2);
|
|
251058
|
+
}
|
|
251059
|
+
const dev = pw?.devices?.[v];
|
|
251060
|
+
if (dev) {
|
|
251061
|
+
await page.setViewportSize(dev.viewport);
|
|
251062
|
+
return ok(`Viewport set to ${v} (${dev.viewport.width}x${dev.viewport.height})`, start2);
|
|
251063
|
+
}
|
|
251064
|
+
return fail(`viewport: provide "WxH" (e.g. "375x667") or a Playwright device name (e.g. "iPhone 13")`, start2);
|
|
251065
|
+
}
|
|
251066
|
+
case "clear_diagnostics": {
|
|
251067
|
+
const sizes = `console=${consoleBuffer.length} network=${networkBuffer.length} errors=${errorBuffer.length}`;
|
|
251068
|
+
clearDiagnosticBuffers();
|
|
251069
|
+
return ok(`Cleared diagnostic buffers (${sizes}).`, start2);
|
|
251070
|
+
}
|
|
250834
251071
|
default:
|
|
250835
251072
|
return fail(`Unknown action: ${action}`, start2);
|
|
250836
251073
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "open-agents-ai",
|
|
3
|
-
"version": "0.187.
|
|
3
|
+
"version": "0.187.470",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "open-agents-ai",
|
|
9
|
-
"version": "0.187.
|
|
9
|
+
"version": "0.187.470",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "CC-BY-NC-4.0",
|
|
12
12
|
"dependencies": {
|
package/package.json
CHANGED