@proagentstore/cli 0.4.0 → 0.4.2
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.
|
@@ -712,8 +712,7 @@ export class LocalRunner {
|
|
|
712
712
|
return mcp.callTool("browser_select_option", { element: label, target: this.refOf(a), values: [a.text ?? ""] });
|
|
713
713
|
case "key":
|
|
714
714
|
return mcp.callTool("browser_press_key", { key: a.key || "Enter" });
|
|
715
|
-
|
|
716
|
-
return mcp.callTool("browser_evaluate", { function: `() => window.scrollBy(0, ${Math.round(a.dy ?? 600)})` });
|
|
715
|
+
// scroll is handled before this mapper (mouse-wheel on the live page).
|
|
717
716
|
case "wait":
|
|
718
717
|
return mcp.callTool("browser_wait_for", { time: Math.min(5, Math.max(0.1, (a.ms ?? 1000) / 1000)) });
|
|
719
718
|
default:
|
|
@@ -764,9 +763,45 @@ export class LocalRunner {
|
|
|
764
763
|
}
|
|
765
764
|
if (this.applyResumePath)
|
|
766
765
|
this.armFileAutoAttach(page, this.applyResumePath);
|
|
766
|
+
// Scroll is a VIEWPORT primitive, not an element action — no ref, no standard
|
|
767
|
+
// tool in @playwright/mcp 0.0.77. Use the mouse wheel on the live page (as the
|
|
768
|
+
// prior runtime did): it scrolls the actual hovered/inner scroll container,
|
|
769
|
+
// whereas window.scrollBy is a no-op on sites that scroll an inner panel (e.g.
|
|
770
|
+
// PageUp/Coles), which made the brain scroll-loop forever.
|
|
771
|
+
if (action.action === "scroll") {
|
|
772
|
+
await page.mouse.wheel(0, Math.round(action.dy ?? 600)).catch(() => undefined);
|
|
773
|
+
await page.waitForTimeout(300).catch(() => undefined);
|
|
774
|
+
const active = await this.getActivePage();
|
|
775
|
+
return {
|
|
776
|
+
ok: true,
|
|
777
|
+
url: active.url(),
|
|
778
|
+
title: await active.title().catch(() => ""),
|
|
779
|
+
challenge: await detectHumanChallenge(active),
|
|
780
|
+
};
|
|
781
|
+
}
|
|
767
782
|
const mcp = await this.getMcp();
|
|
768
783
|
const res = await this.callBrowserTool(mcp, action);
|
|
769
784
|
const text = mcp.textOf(res).trim();
|
|
785
|
+
// A native page dialog (alert/confirm/beforeunload) puts the standard server
|
|
786
|
+
// into a modal state that blocks EVERY other tool until it's handled. The brain
|
|
787
|
+
// has no dialog vocabulary (the old runtime relied on Playwright's default
|
|
788
|
+
// auto-dismiss, which @playwright/mcp overrides), so clear it transparently and
|
|
789
|
+
// report it as a successful, informative step — the brain proceeds on the next
|
|
790
|
+
// snapshot instead of thrashing into a needless human handoff.
|
|
791
|
+
if (res.isError && /modal state/i.test(text) && /dialog/i.test(text)) {
|
|
792
|
+
const dialogMsg = (text.match(/dialog with message "([^"]*)"/)?.[1] || "").slice(0, 160);
|
|
793
|
+
await mcp.callTool("browser_handle_dialog", { accept: true }).catch(() => undefined);
|
|
794
|
+
await page.waitForTimeout(400).catch(() => undefined);
|
|
795
|
+
const settled = await this.getActivePage();
|
|
796
|
+
await settled.waitForLoadState("domcontentloaded", { timeout: 6_000 }).catch(() => undefined);
|
|
797
|
+
return {
|
|
798
|
+
ok: true,
|
|
799
|
+
url: settled.url(),
|
|
800
|
+
title: await settled.title().catch(() => ""),
|
|
801
|
+
challenge: await detectHumanChallenge(settled),
|
|
802
|
+
feedback: dialogMsg ? `a native dialog was accepted: "${dialogMsg}"` : "a native dialog was accepted",
|
|
803
|
+
};
|
|
804
|
+
}
|
|
770
805
|
if (res.isError)
|
|
771
806
|
throw new RunnerInputError(this.conciseFeedback(text) || `${action.action} failed`);
|
|
772
807
|
// A click may trigger SPA navigation or open a new tab/popup. Give it a beat
|