Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173export { Sandbox } from "../../worker/sandbox";import runtime, { PersonalAgent as FixturePersonalAgent, Conversation as FixtureConversation,} from "./think-worker";import type { Env } from "../../worker/personal-agent";import type { BrowserBinding } from "agents/browser";import { createBrowserSession } from "agents/browser";import { getAgentByName } from "agents";import { browserRace } from "./browser-races";
const sessions: { id: string; deleted: boolean }[] = [];const requests: string[] = [];let failDeletes = 0;let delayCreate = 0;const dynamicHtml = `<!doctype html><html><head><title>Initial title</title><link rel="canonical" href="https://untrusted.example.com/fake"></head><body><main id="main">Loading</main><script>setTimeout(() => { document.title = 'Rendered title 🐟'; history.replaceState({}, '', '/rendered-final'); document.getElementById('main').innerHTML = '<article id="ready">Evidence added by JavaScript <a href="/follow">Next source</a><a href="http://127.0.0.1/secret">Private link</a><a href="javascript:alert(1)">Script link</a></article>'; }, 800);</script></body></html>`;const originalFetch = globalThis.fetch;globalThis.fetch = ((input: RequestInfo | URL, init?: RequestInit) => { const url = new URL( typeof input === "string" ? input : input instanceof URL ? input.href : input.url, ); return url.hostname === "browser.fixture.example.com" ? Promise.resolve( new Response(dynamicHtml, { headers: { "content-type": "text/html" } }), ) : originalFetch(input, init);}) as typeof fetch;
function fixtureBrowser(browser: BrowserBinding): BrowserBinding { return { async fetch(input, init) { if (init?.method === "DELETE" && failDeletes-- > 0) return new Response(null, { status: 503 }); const response = await browser.fetch(input, init); if (init?.method === "POST") { const { sessionId } = (await response.clone().json()) as { sessionId: string; }; sessions.push({ id: sessionId, deleted: false }); if (delayCreate) await new Promise((resolve) => setTimeout(resolve, delayCreate)); } if (init?.method === "DELETE") { const found = sessions.find( (session) => session.id === String(input).split("/").at(-1), ); if (found && (response.ok || response.status === 404)) found.deleted = true; } if (response.webSocket) { const socket = response.webSocket; const send = socket.send.bind(socket); const paused = new Map<string, string>(); socket.addEventListener("message", (message) => { const event = JSON.parse(String(message.data)); if (event.method === "Fetch.requestPaused") { paused.set(event.params.requestId, event.params.request.url); requests.push(event.params.request.url); } }); socket.send = (message) => { const command = JSON.parse(String(message)); if (command.method === "Fetch.continueRequest") { const url = new URL(paused.get(command.params.requestId)!); if (url.hostname === "browser.fixture.example.com") { const path = url.pathname; const body = path === "/follow" ? "<html><title>Followed source</title><body><main>Follow-up evidence</main></body></html>" : path === "/large" ? "<html><body><main>" + "🐟".repeat(12_000) + "</main></body></html>" : path === "/slow" ? "<html><body><main>Waiting</main></body></html>" : dynamicHtml; command.method = "Fetch.fulfillRequest"; command.params = { requestId: command.params.requestId, responseCode: path === "/private" ? 302 : path === "/error" ? 429 : 200, responseHeaders: [ { name: "content-type", value: "text/html; charset=utf-8" }, ...(path === "/private" ? [{ name: "location", value: "http://127.0.0.1/secret" }] : []), ], body: btoa( String.fromCharCode(...new TextEncoder().encode(body)), ), }; } } send(JSON.stringify(command)); }; } return response; }, };}export class PersonalAgent extends FixturePersonalAgent { constructor(ctx: DurableObjectState, env: Env) { super(ctx, { ...env, BROWSER: fixtureBrowser(env.BROWSER) as Fetcher }); } inspectBrowsers() { return this.sql`SELECT * FROM flarebot_browser_leases`; } async seedBrowser(conversationId: string, ms: number) { const { sessionId } = await createBrowserSession(this.env.BROWSER, { keepAliveMs: 60_000, }); await this.registerResearchBrowser( conversationId, sessionId, Date.now() + ms, ); return sessionId; }}export class Conversation extends FixtureConversation { constructor(ctx: DurableObjectState, env: Env) { super(ctx, { ...env, BROWSER: fixtureBrowser(env.BROWSER) as Fetcher }); }}export default { async fetch( request: Request<unknown, IncomingRequestCfProperties>, env: Env, ctx: ExecutionContext, ) { const url = new URL(request.url); if (url.pathname === "/__fixture/browser-probe") { const response = await env.BROWSER.fetch( `https://localhost/v1/devtools/browser/${url.searchParams.get("id")}/json/list`, ); return Response.json({ status: response.status }); } if (url.pathname === "/__fixture/browser-status") { const parent = await getAgentByName(env.PersonalAgent, "personal"); return Response.json({ sessions, requests, leases: await (parent as unknown as PersonalAgent).inspectBrowsers(), }); } if (url.pathname === "/__fixture/browser-fault") { failDeletes = Number(url.searchParams.get("deletes") ?? 0); delayCreate = Number(url.searchParams.get("create") ?? 0); return new Response("ok"); } if (url.pathname === "/__fixture/browser-seed") { const parent = await getAgentByName(env.PersonalAgent, "personal"); return Response.json( await (parent as unknown as PersonalAgent).seedBrowser( url.searchParams.get("id")!, Number(url.searchParams.get("ms")), ), ); } if (url.pathname === "/__fixture/browser-race") return Response.json( await browserRace(url.searchParams.get("scenario")!), ); return runtime.fetch(request, env, ctx); },};