// SPDX-License-Identifier: Apache-2.0 // Hand one step to a person: a "Your turn" page with your message, their browser live and a Done button. // Here the step is a verification code "sent to their phone" (the fixture's /verify page), which no agent can know. // // export WEBPILOT_URL=http://localhost:8931 WEBPILOT_TOKEN=cbu_... // python examples/fixture_site.py & # the page that asks for the code // node handoff.ts # waits up to 10 minutes // node handoff.ts 120 # waits up to 2 minutes // // Open the printed link, type any 6 digits in the browser you see there, press Verify, then press Done. // (Typing in the viewer needs take-over rights: the user's site policy `viewer_interactive`, or the host's // CBU_VNC_INTERACTIVE=1.) A program acting for the person can also call wp.handoffs.resolve(id). import { WebPilot } from "webpilot-si"; const FIXTURE = process.env["WEBPILOT_FIXTURE"] ?? "http://host.docker.internal:8765"; const waitS = Number(process.argv[2] ?? 600); const wp = new WebPilot(); const tab = await wp.open(`${FIXTURE}/verify`, { mode: "act" }); try { let h = await wp.handoffs.create("Please enter the 6-digit code we sent to your phone, press Verify, then press Done.", { reason: "two_factor", tabId: tab.id, expiresInS: Math.max(60, Math.floor(waitS)), }); console.log(`hand-off ${h.id}: send this link to the person:\n ${h.url}`); h = await wp.handoffs.wait(h.id, { timeoutS: waitS }); // long-polls; returns when Done is pressed or it expires console.log(`hand-off ${h.status}${h.note ? ` (${h.note})` : ""}`); if (h.status === "resolved") { const lines = (await tab.readText()).trim().split("\n"); console.log("the page now says:", (lines.at(-1) ?? "").slice(0, 120)); } else { console.log("nobody finished the step; report it and stop (do not try to get around it)."); } } finally { await tab.close(); }