From f764ade37e86995ff395271722cea7322b6035fa Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sat, 4 Jul 2026 12:32:10 +0000 Subject: [PATCH 1/2] feat(m3.4): @tronbrowser/sdk and `tron run` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Public developer SDK + a script runner (PRD M3.4), building on the M3.1–M3.3 Node automation runtime. import { tron } from '@tronbrowser/sdk'; const browser = await tron.launch({ headless: true }); const page = await browser.newPage(); await page.goto(url); const snap = await page.snapshot(); await browser.close(); tron run ./agent.ts # TS runs directly (Node >=24 strips types) tron run ./agent.js --headless --trace ./trace - packages/sdk: Browser (session lifecycle: launch via the tron-session engine, hand out Pages, tear down the temp profile on close) and Page (goto/reload/ back/forward, snapshot, click/fill/type by ref, extract, screenshot, pdf, eval, url/title). analyze/step/runTask are declared but throw until M3.5. Side-effects are injectable; launch reuses TRON_SESSION_BIN so binary resolution isn't duplicated. - tron-run.mjs + tron-run-hooks.mjs: the runner registers an ESM resolver hook mapping @tronbrowser/sdk + /browser-core to the shipped runtime, then imports the user script (no node_modules, no build). --headless/--profile/--trace arrive via env and are honored by tron.launch(). - trace.ts: minimal --trace bundle (metadata.json + actions.jsonl) with values redacted (full trace/replay is M3.7). - install.sh routes `tron run`; build-release ships browser-core + sdk dist and the runner files in the launcher payload. Tests (+8): SDK lifecycle/cleanup/launch-failure with fakes, and an end-to-end run over the real CDP WebSocket transport incl. multi-page Target.createTarget. Verified `tron run` for JS and TS (no build) and --trace end-to-end against a WS CDP stub. Full workspace suite green. Co-Authored-By: Claude Opus 4.8 --- apps/desktop/launcher/tron-run-hooks.mjs | 15 +++ apps/desktop/launcher/tron-run.mjs | 57 ++++++++++ apps/desktop/scripts/build-release.sh | 24 ++-- apps/web/public/install.sh | 10 ++ docs/sdk-and-run.md | 63 +++++++++++ packages/sdk/package.json | 3 + packages/sdk/src/browser.ts | 115 +++++++++++++++++++ packages/sdk/src/deps.ts | 74 ++++++++++++ packages/sdk/src/index.ts | 36 +++++- packages/sdk/src/page.ts | 137 +++++++++++++++++++++++ packages/sdk/src/sdk-e2e.test.ts | 116 +++++++++++++++++++ packages/sdk/src/sdk.test.ts | 114 +++++++++++++++++++ packages/sdk/src/trace.ts | 47 ++++++++ pnpm-lock.yaml | 5 +- 14 files changed, 803 insertions(+), 13 deletions(-) create mode 100644 apps/desktop/launcher/tron-run-hooks.mjs create mode 100644 apps/desktop/launcher/tron-run.mjs create mode 100644 docs/sdk-and-run.md create mode 100644 packages/sdk/src/browser.ts create mode 100644 packages/sdk/src/deps.ts create mode 100644 packages/sdk/src/page.ts create mode 100644 packages/sdk/src/sdk-e2e.test.ts create mode 100644 packages/sdk/src/sdk.test.ts create mode 100644 packages/sdk/src/trace.ts diff --git a/apps/desktop/launcher/tron-run-hooks.mjs b/apps/desktop/launcher/tron-run-hooks.mjs new file mode 100644 index 0000000..66c904d --- /dev/null +++ b/apps/desktop/launcher/tron-run-hooks.mjs @@ -0,0 +1,15 @@ +// ESM resolver hook for `tron run`: maps the bare `@tronbrowser/*` specifiers a +// user script imports to the runtime shipped in the launcher payload, so scripts +// need no node_modules of their own. Registered by tron-run.mjs. +let map = {}; + +export async function initialize(data) { + map = data ?? {}; +} + +export async function resolve(specifier, context, next) { + if (Object.prototype.hasOwnProperty.call(map, specifier)) { + return { url: map[specifier], shortCircuit: true }; + } + return next(specifier, context); +} diff --git a/apps/desktop/launcher/tron-run.mjs b/apps/desktop/launcher/tron-run.mjs new file mode 100644 index 0000000..4111e3e --- /dev/null +++ b/apps/desktop/launcher/tron-run.mjs @@ -0,0 +1,57 @@ +// `tron run