This commit is contained in:
k
2026-09-21 19:14:55 +02:00
parent 2a34d16b52
commit 5903b77d95
16 changed files with 958 additions and 125 deletions
+86
View File
@@ -0,0 +1,86 @@
/**
* POC — drive chatgpt.com inside a totally temporary Firefox profile
* (puppeteer-core, WebDriver BiDi, headed). The profile is created in
* /tmp at launch and deleted on exit; login is done manually in the
* window when the script asks for it.
*
* Usage:
* bun scripts/poc-chatgpt.ts # send default test message
* bun scripts/poc-chatgpt.ts --message "hello" # custom message (\n supported)
* bun scripts/poc-chatgpt.ts --message $'l1\nl2' # multi-line test
* bun scripts/poc-chatgpt.ts --probe # just open + report page state
* bun scripts/poc-chatgpt.ts --timeout-s 600 # longer response timeout
*/
import { ChatGPTBrowserEngine } from "../src/drivers/browser.ts";
const DEFAULT_MESSAGE = "Hello! Answer with one short sentence so we know the pipeline works.";
function flag(name: string): boolean {
return process.argv.includes(name);
}
function option(name: string): string | undefined {
const i = process.argv.indexOf(name);
return i !== -1 && i + 1 < process.argv.length ? process.argv[i + 1] : undefined;
}
const exe = process.env.PUPPETEER_EXECUTABLE ?? "firefox";
const executablePath = exe.includes("/") ? exe : Bun.which(exe);
if (!executablePath) {
console.error("firefox not found — set PUPPETEER_EXECUTABLE to the Firefox binary path");
process.exit(1);
}
const responseTimeoutS = Number(option("--timeout-s") ?? 300);
if (!Number.isFinite(responseTimeoutS) || responseTimeoutS <= 0) {
console.error("--timeout-s must be a positive number of seconds");
process.exit(1);
}
const engine = new ChatGPTBrowserEngine({
executablePath,
headless: false,
loginTimeoutMs: 600_000,
responseTimeoutMs: responseTimeoutS * 1000,
});
let interrupted = 0;
process.on("SIGINT", () => {
interrupted++;
if (interrupted > 1) process.exit(130);
console.log("\n[interrupt] closing browser and deleting the temporary profile…");
void engine.close().finally(() => process.exit(130));
});
const t0 = Date.now();
const step = (msg: string) => console.log(`[${((Date.now() - t0) / 1000).toFixed(1)}s] ${msg}`);
try {
if (flag("--probe")) {
step(`launching Firefox (${executablePath}) with a fresh throwaway profile`);
const info = await engine.probe();
console.log(JSON.stringify(info, null, 2));
step(info.composer ? `composer ready: ${info.composer}` : "composer NOT found — login wall or challenge page");
} else {
const message = option("--message") ?? DEFAULT_MESSAGE;
step(`launching Firefox (${executablePath}) — temporary profile, deleted on exit`);
let streamed = "";
const final = await engine.send(message, {
onLoginHint: () => step("login required: log in inside the Firefox window (waiting up to 10 min)"),
onToken: (delta) => {
streamed += delta;
process.stdout.write(delta);
},
});
console.log();
if (!streamed.trim()) console.log(final);
step(`done — response above (${final.length} chars)`);
}
process.exitCode = 0;
} catch (e) {
console.error(`\n[error] ${(e as Error).message}`);
process.exitCode = 1;
} finally {
await engine.close();
step("browser closed, temporary profile deleted");
}