Add opt-in browser tools for desktop tabs
* Add opt-in browser tools for desktop tabs Adds the daemon opt-in, desktop tab routing, MCP tools, and real browser automation surfaces for Paseo desktop browser tabs. * Fix browser tools CI expectations * Address browser tools review findings * Restrict browser file automation paths * Fix browser upload test on Windows * Harden browser navigation inputs * Make browser tools create usable tabs * Update browser MCP empty-state test * Fail browser tab creation when registration times out * Fix browser screenshots for agents * Hide disabled browser tools from agents * Address browser tools architecture review * Replace browser tools review tests * Wrap browser tab registration errors * Mock Expo Router in app unit tests * Handle invalid browser automation requests * Return browser failure on desktop disconnect * Update browser disconnect websocket test * Relax browser timeout polling test * Handle invalid browser responses * Return browser failure when send fails * Remove local diagnostics and fixture paths * Fix dev service home fallback * Use worktree home for dev services * Use managed daemon in desktop dev * fix(browser): keep agent tabs addressable Track agent-active browser targets separately from human-focused tabs and keep resident webviews alive for automation. Browser tool visibility now comes from registration while the broker reports disabled execution. * refactor(browser): register tools through catalog Move browser tool registration onto the shared Paseo tool catalog so the MCP server remains only the transport adapter. * fix(settings): translate browser tools host error
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { BrowserSnapshotEngine, type SnapshotPage } from "./snapshot-engine.js";
|
||||
|
||||
class SnapshotFixture implements SnapshotPage {
|
||||
public currentUrl = "https://example.com/form";
|
||||
public actionResult: unknown = true;
|
||||
|
||||
public getURL(): string {
|
||||
return this.currentUrl;
|
||||
}
|
||||
|
||||
public async executeJavaScript(code: string): Promise<unknown> {
|
||||
if (code.includes("CANDIDATE_SELECTOR")) {
|
||||
return JSON.stringify([
|
||||
{
|
||||
role: "textbox",
|
||||
tagName: "input",
|
||||
text: "Name",
|
||||
selector: "#name",
|
||||
attributes: { id: "name", type: "text" },
|
||||
},
|
||||
{
|
||||
role: "button",
|
||||
tagName: "button",
|
||||
text: "Drop",
|
||||
selector: "#drop",
|
||||
attributes: { id: "drop" },
|
||||
},
|
||||
]);
|
||||
}
|
||||
return this.actionResult;
|
||||
}
|
||||
}
|
||||
|
||||
describe("BrowserSnapshotEngine", () => {
|
||||
it("treats a false result from a ref action script as a stale ref", async () => {
|
||||
const page = new SnapshotFixture();
|
||||
const engine = new BrowserSnapshotEngine();
|
||||
await engine.snapshot({ browserId: "browser-1", page });
|
||||
|
||||
page.actionResult = false;
|
||||
|
||||
await expect(engine.click({ browserId: "browser-1", page, ref: "@e1" })).resolves.toEqual({
|
||||
ok: false,
|
||||
reason: "stale_ref",
|
||||
});
|
||||
await expect(engine.focus({ browserId: "browser-1", page, ref: "@e1" })).resolves.toEqual({
|
||||
ok: false,
|
||||
reason: "stale_ref",
|
||||
});
|
||||
});
|
||||
|
||||
it("treats a false result from optional ref text/key actions as a stale ref", async () => {
|
||||
const page = new SnapshotFixture();
|
||||
const engine = new BrowserSnapshotEngine();
|
||||
await engine.snapshot({ browserId: "browser-1", page });
|
||||
|
||||
page.actionResult = false;
|
||||
|
||||
await expect(
|
||||
engine.typeText({ browserId: "browser-1", page, ref: "@e1", text: "Ada" }),
|
||||
).resolves.toEqual({ ok: false, reason: "stale_ref" });
|
||||
await expect(
|
||||
engine.keypress({ browserId: "browser-1", page, ref: "@e1", key: "Enter" }),
|
||||
).resolves.toEqual({ ok: false, reason: "stale_ref" });
|
||||
});
|
||||
|
||||
it("treats a false result from drag as a stale ref", async () => {
|
||||
const page = new SnapshotFixture();
|
||||
const engine = new BrowserSnapshotEngine();
|
||||
await engine.snapshot({ browserId: "browser-1", page });
|
||||
|
||||
page.actionResult = false;
|
||||
|
||||
await expect(
|
||||
engine.drag({ browserId: "browser-1", page, sourceRef: "@e1", targetRef: "@e2" }),
|
||||
).resolves.toEqual({ ok: false, reason: "stale_ref" });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user