@wrongstack/tools 0.296.2 → 0.296.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,6 @@
1
1
  import type { BrowserArtifact, BrowserArtifactKind } from './types.js';
2
+ /** Reset module state — test hook (per-process sweep memo only). */
3
+ export declare function _resetArtifactSweepForTests(): void;
2
4
  export declare class BrowserArtifactStore {
3
5
  private readonly root;
4
6
  constructor(root: string);
@@ -1 +1 @@
1
- {"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../../src/browser/artifacts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEvE,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,MAAM,EAAI;IAEvC,KAAK,CACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,mBAAmB,EACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,eAAe,CAAC,CAM1B;YAEa,MAAM;IA0CpB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAM1E;IAEK,QAAQ,CACZ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,CAE1B;CACF"}
1
+ {"version":3,"file":"artifacts.d.ts","sourceRoot":"","sources":["../../src/browser/artifacts.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAgBvE,oEAAoE;AACpE,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAiDD,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,MAAM,EAExC;IAEK,KAAK,CACT,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,mBAAmB,EACzB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,eAAe,CAAC,CAM1B;YAEa,MAAM;IA0CpB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAM1E;IAEK,QAAQ,CACZ,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC,CAE1B;CACF"}
@@ -4,9 +4,50 @@ import { createReadStream } from "node:fs";
4
4
  import * as fs from "node:fs/promises";
5
5
  import * as path from "node:path";
6
6
  import { atomicWrite, ulid } from "@wrongstack/core/utils";
7
+ var ARTIFACT_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
8
+ var sweptRoots = /* @__PURE__ */ new Set();
9
+ function sweepOldArtifacts(root) {
10
+ if (sweptRoots.has(root)) return;
11
+ sweptRoots.add(root);
12
+ void (async () => {
13
+ const cutoff = Date.now() - ARTIFACT_RETENTION_MS;
14
+ let sessionDirs;
15
+ try {
16
+ const entries = await fs.readdir(root, { withFileTypes: true });
17
+ sessionDirs = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
18
+ } catch {
19
+ return;
20
+ }
21
+ for (const sessionDir of sessionDirs) {
22
+ const dir = path.join(root, sessionDir);
23
+ let names;
24
+ try {
25
+ names = await fs.readdir(dir);
26
+ } catch {
27
+ continue;
28
+ }
29
+ let removed = 0;
30
+ for (const name of names) {
31
+ const target = path.join(dir, name);
32
+ try {
33
+ const stat3 = await fs.stat(target);
34
+ if (stat3.isFile() && stat3.mtimeMs < cutoff) {
35
+ await fs.rm(target, { force: true });
36
+ removed++;
37
+ }
38
+ } catch {
39
+ }
40
+ }
41
+ if (removed === names.length && names.length > 0) {
42
+ await fs.rmdir(dir).catch(() => void 0);
43
+ }
44
+ }
45
+ })();
46
+ }
7
47
  var BrowserArtifactStore = class {
8
48
  constructor(root) {
9
49
  this.root = root;
50
+ sweepOldArtifacts(root);
10
51
  }
11
52
  root;
12
53
  async write(sessionId, kind, extension, mimeType, content) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/browser/artifacts.ts", "../../src/browser/manager.ts", "../../src/browser/network-guard-proxy.ts", "../../src/browser/security.ts", "../../src/browser/tools.ts"],
4
- "sourcesContent": ["import { createHash } from 'node:crypto';\nimport { createReadStream } from 'node:fs';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite, ulid } from '@wrongstack/core/utils';\nimport type { BrowserArtifact, BrowserArtifactKind } from './types.js';\n\nexport class BrowserArtifactStore {\n constructor(private readonly root: string) {}\n\n async write(\n sessionId: string,\n kind: BrowserArtifactKind,\n extension: string,\n mimeType: string,\n content: Uint8Array,\n ): Promise<BrowserArtifact> {\n const id = ulid();\n const dir = path.join(this.root, safeSegment(sessionId));\n const target = path.join(dir, `${id}.${extension.replace(/^\\./, '')}`);\n await atomicWrite(target, content, { mode: 0o600 });\n return this.record(id, sessionId, kind, target, mimeType);\n }\n\n private async record(\n id: string,\n sessionId: string,\n kind: BrowserArtifactKind,\n target: string,\n mimeType: string,\n ): Promise<BrowserArtifact> {\n await fs.chmod(target, 0o600).catch(() => undefined);\n const [stat, sha256] = await Promise.all([fs.stat(target), hashFile(target)]);\n const artifact: BrowserArtifact = {\n id,\n kind,\n sensitivity: 'sensitive',\n path: target,\n mimeType,\n sizeBytes: stat.size,\n sha256,\n createdAt: new Date().toISOString(),\n };\n const metadataPath = path.join(path.dirname(target), `${id}.metadata.json`);\n try {\n await atomicWrite(\n metadataPath,\n `${JSON.stringify({\n id: artifact.id,\n sessionId: safeSegment(sessionId),\n kind: artifact.kind,\n sensitivity: artifact.sensitivity,\n mimeType: artifact.mimeType,\n sizeBytes: artifact.sizeBytes,\n sha256: artifact.sha256,\n createdAt: artifact.createdAt,\n })}\\n`,\n { mode: 0o600 },\n );\n } catch (error) {\n await fs.rm(target, { force: true }).catch(() => undefined);\n throw error;\n }\n return artifact;\n }\n\n pathFor(sessionId: string, extension: string): { id: string; path: string } {\n const id = ulid();\n return {\n id,\n path: path.join(this.root, safeSegment(sessionId), `${id}.${extension.replace(/^\\./, '')}`),\n };\n }\n\n async describe(\n id: string,\n kind: BrowserArtifactKind,\n target: string,\n mimeType: string,\n ): Promise<BrowserArtifact> {\n return this.record(id, path.basename(path.dirname(target)), kind, target, mimeType);\n }\n}\n\nasync function hashFile(target: string): Promise<string> {\n const hash = createHash('sha256');\n await new Promise<void>((resolve, reject) => {\n const stream = createReadStream(target);\n stream.on('data', (chunk) => hash.update(chunk));\n stream.once('error', reject);\n stream.once('end', resolve);\n });\n return hash.digest('hex');\n}\n\nfunction safeSegment(value: string): string {\n return value.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 80);\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Browser, BrowserContext, Page } from '@playwright/test';\nimport { ulid } from '@wrongstack/core/utils';\nimport { BrowserArtifactStore } from './artifacts.js';\nimport { BrowserNetworkGuardProxy } from './network-guard-proxy.js';\nimport { assertBrowserUrlAllowed, redactBrowserText, safeBrowserUrl } from './security.js';\nimport type {\n BrowserArtifact,\n BrowserConsoleEntry,\n BrowserManagerOptions,\n BrowserNetworkEntry,\n BrowserOpenOptions,\n BrowserSessionSummary,\n BrowserSnapshot,\n} from './types.js';\n\nconst DEFAULT_OPERATION_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_SNAPSHOT_CHARS = 64 * 1024;\nconst DEFAULT_MAX_ENTRIES = 100;\n\ninterface LiveSession {\n id: string;\n ownerId: string;\n context: BrowserContext;\n page: Page;\n createdAt: string;\n lastUsedAt: string;\n tracing: boolean;\n console: BrowserConsoleEntry[];\n network: BrowserNetworkEntry[];\n}\n\nexport type BrowserLauncher = (headless: boolean) => Promise<Browser>;\n\nexport class BrowserSessionManager {\n private readonly sessions = new Map<string, LiveSession>();\n private readonly artifacts: BrowserArtifactStore;\n private readonly allowPrivateHosts: boolean;\n private readonly allowedPrivateOrigins: readonly string[];\n private readonly networkProxy: BrowserNetworkGuardProxy;\n private readonly headless: boolean;\n private readonly operationTimeoutMs: number;\n private readonly maxSnapshotChars: number;\n private readonly maxConsoleEntries: number;\n private readonly maxNetworkEntries: number;\n private browser?: Browser | undefined;\n private launching?: Promise<Browser> | undefined;\n\n constructor(\n options: BrowserManagerOptions,\n private readonly launcher: BrowserLauncher = defaultLauncher,\n ) {\n this.artifacts = new BrowserArtifactStore(options.artifactRoot);\n this.allowPrivateHosts = options.allowPrivateHosts ?? true;\n this.allowedPrivateOrigins = options.allowedPrivateOrigins ?? [];\n this.networkProxy = new BrowserNetworkGuardProxy({\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n });\n this.headless = options.headless ?? true;\n this.operationTimeoutMs = options.operationTimeoutMs ?? DEFAULT_OPERATION_TIMEOUT_MS;\n this.maxSnapshotChars = options.maxSnapshotChars ?? DEFAULT_MAX_SNAPSHOT_CHARS;\n this.maxConsoleEntries = options.maxConsoleEntries ?? DEFAULT_MAX_ENTRIES;\n this.maxNetworkEntries = options.maxNetworkEntries ?? DEFAULT_MAX_ENTRIES;\n }\n\n async open(\n ownerId: string,\n input: BrowserOpenOptions,\n signal: AbortSignal,\n ): Promise<BrowserSessionSummary> {\n signal.throwIfAborted();\n if (input.url) {\n await assertBrowserUrlAllowed(input.url, {\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n navigation: true,\n });\n }\n const browser = await this.ensureBrowser(signal);\n const proxyServer = await this.networkProxy.start();\n const context = await abortable(\n signal,\n async () => {\n const created = await browser.newContext({\n acceptDownloads: false,\n ignoreHTTPSErrors: false,\n serviceWorkers: 'block',\n proxy: { server: proxyServer },\n viewport: input.viewport ?? { width: 1440, height: 900 },\n });\n if (signal.aborted) {\n await created.close().catch(() => undefined);\n signal.throwIfAborted();\n }\n return created;\n },\n () => undefined,\n );\n const session: LiveSession = {\n id: ulid(),\n ownerId,\n context,\n page: await context.newPage(),\n createdAt: new Date().toISOString(),\n lastUsedAt: new Date().toISOString(),\n tracing: input.trace ?? true,\n console: [],\n network: [],\n };\n this.sessions.set(session.id, session);\n this.attachEvidenceCollectors(session);\n await context.route('**/*', async (route) => {\n try {\n await assertBrowserUrlAllowed(route.request().url(), {\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n navigation: false,\n });\n await route.continue();\n } catch {\n this.pushNetwork(session, {\n method: route.request().method(),\n url: safeBrowserUrl(route.request().url()),\n failed: true,\n at: new Date().toISOString(),\n });\n await route.abort('blockedbyclient');\n }\n });\n try {\n if (session.tracing) {\n await context.tracing.start({ screenshots: true, snapshots: true, sources: false });\n }\n if (input.url) await this.navigate(session.id, ownerId, input.url, signal);\n return await this.summary(session);\n } catch (err) {\n await context.close().catch(() => undefined);\n this.sessions.delete(session.id);\n await this.closeBrowserIfIdle();\n throw err;\n }\n }\n\n async list(ownerId: string): Promise<BrowserSessionSummary[]> {\n const owned = [...this.sessions.values()].filter((session) => session.ownerId === ownerId);\n return Promise.all(owned.map((session) => this.summary(session)));\n }\n\n async navigate(\n id: string,\n ownerId: string,\n rawUrl: string,\n signal: AbortSignal,\n ): Promise<BrowserSessionSummary> {\n await assertBrowserUrlAllowed(rawUrl, {\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n navigation: true,\n });\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.goto(rawUrl, {\n waitUntil: 'domcontentloaded',\n timeout: this.operationTimeoutMs,\n }),\n );\n return this.summary(session);\n }\n\n async snapshot(id: string, ownerId: string, signal: AbortSignal): Promise<BrowserSnapshot> {\n const session = this.requireOwned(id, ownerId);\n const raw = await this.runPageOperation(session, signal, async () => {\n try {\n return await session.page\n .locator('body')\n .ariaSnapshot({ timeout: this.operationTimeoutMs });\n } catch {\n return await session.page.locator('body').innerText({ timeout: this.operationTimeoutMs });\n }\n });\n const aria = redactBrowserText(raw);\n const truncated = aria.length > this.maxSnapshotChars;\n return {\n session: await this.summary(session),\n aria: truncated ? `${aria.slice(0, this.maxSnapshotChars)}\\n\u2026[snapshot truncated]` : aria,\n console: session.console.map((entry) => ({ ...entry })),\n network: session.network.map((entry) => ({ ...entry })),\n truncated,\n };\n }\n\n async screenshot(\n id: string,\n ownerId: string,\n input: { fullPage?: boolean | undefined; selector?: string | undefined },\n signal: AbortSignal,\n ): Promise<BrowserArtifact> {\n const session = this.requireOwned(id, ownerId);\n const bytes = await this.runPageOperation(session, signal, () =>\n input.selector\n ? session.page\n .locator(input.selector)\n .screenshot({ type: 'png', timeout: this.operationTimeoutMs })\n : session.page.screenshot({ type: 'png', fullPage: input.fullPage ?? false }),\n );\n signal.throwIfAborted();\n return this.artifacts.write(session.id, 'screenshot', 'png', 'image/png', bytes);\n }\n\n async click(id: string, ownerId: string, selector: string, signal: AbortSignal): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).click({ timeout: this.operationTimeoutMs }),\n );\n }\n\n async type(\n id: string,\n ownerId: string,\n selector: string,\n text: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).fill(text, { timeout: this.operationTimeoutMs }),\n );\n }\n\n async select(\n id: string,\n ownerId: string,\n selector: string,\n value: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).selectOption(value, { timeout: this.operationTimeoutMs }),\n );\n }\n\n async press(id: string, ownerId: string, key: string, signal: AbortSignal): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () => session.page.keyboard.press(key));\n }\n\n async hover(id: string, ownerId: string, selector: string, signal: AbortSignal): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).hover({ timeout: this.operationTimeoutMs }),\n );\n }\n\n async wait(\n id: string,\n ownerId: string,\n input: { selector?: string | undefined; timeoutMs?: number | undefined },\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n const timeout = Math.min(\n Math.max(input.timeoutMs ?? this.operationTimeoutMs, 0),\n this.operationTimeoutMs,\n );\n await this.runPageOperation(session, signal, () =>\n input.selector\n ? session.page.locator(input.selector).waitFor({ state: 'visible', timeout })\n : session.page.waitForTimeout(timeout),\n );\n }\n\n async drag(\n id: string,\n ownerId: string,\n from: string,\n to: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(from).dragTo(session.page.locator(to), {\n timeout: this.operationTimeoutMs,\n }),\n );\n }\n\n async upload(\n id: string,\n ownerId: string,\n selector: string,\n files: string[],\n projectRoot: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n const root = path.resolve(projectRoot);\n const realRoot = await fs.realpath(root);\n const resolved: string[] = [];\n for (const file of files) {\n const absolute = path.resolve(root, file);\n const relative = path.relative(root, absolute);\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('browser: upload files must stay inside the project root');\n }\n const realFile = await fs.realpath(absolute);\n const realRelative = path.relative(realRoot, realFile);\n if (realRelative.startsWith('..') || path.isAbsolute(realRelative)) {\n throw new Error('browser: upload files must not escape the project root through a symlink');\n }\n const stat = await fs.stat(realFile);\n if (!stat.isFile()) throw new Error(`browser: upload target is not a file: ${file}`);\n resolved.push(realFile);\n }\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).setInputFiles(resolved, { timeout: this.operationTimeoutMs }),\n );\n }\n\n async evaluate(\n id: string,\n ownerId: string,\n expression: string,\n signal: AbortSignal,\n ): Promise<unknown> {\n const session = this.requireOwned(id, ownerId);\n const result = await this.runPageOperation(session, signal, () =>\n session.page.evaluate(expression),\n );\n const serialized = JSON.stringify(result);\n if (serialized && serialized.length > this.maxSnapshotChars) {\n throw new Error(`browser: evaluation result exceeds ${this.maxSnapshotChars} characters`);\n }\n return result;\n }\n\n async close(id: string, ownerId: string): Promise<{ trace?: BrowserArtifact | undefined }> {\n const session = this.requireOwned(id, ownerId);\n let trace: BrowserArtifact | undefined;\n try {\n if (session.tracing) {\n const target = this.artifacts.pathFor(session.id, 'zip');\n await fs.mkdir(path.dirname(target.path), { recursive: true });\n await session.context.tracing.stop({ path: target.path });\n trace = await this.artifacts.describe(target.id, 'trace', target.path, 'application/zip');\n }\n } finally {\n await session.context.close().catch(() => undefined);\n this.sessions.delete(id);\n await this.closeBrowserIfIdle();\n }\n return trace ? { trace } : {};\n }\n\n async closeOwner(ownerId: string): Promise<void> {\n const ids = [...this.sessions.values()]\n .filter((session) => session.ownerId === ownerId)\n .map((session) => session.id);\n for (const id of ids) await this.close(id, ownerId).catch(() => undefined);\n }\n\n /** True when the manager owns no live browser contexts. */\n isIdle(): boolean {\n return this.sessions.size === 0;\n }\n\n async dispose(): Promise<void> {\n for (const session of [...this.sessions.values()]) {\n await session.context.close().catch(() => undefined);\n }\n this.sessions.clear();\n const browser = this.browser;\n this.browser = undefined;\n this.launching = undefined;\n await browser?.close().catch(() => undefined);\n await this.networkProxy.close();\n }\n\n private async ensureBrowser(signal: AbortSignal): Promise<Browser> {\n if (this.browser?.isConnected()) return this.browser;\n if (!this.launching) {\n this.launching = this.launcher(this.headless).then((browser) => {\n this.browser = browser;\n browser.on('disconnected', () => {\n if (this.browser === browser) this.browser = undefined;\n for (const [id, session] of this.sessions) {\n if (session.context.browser() === browser) this.sessions.delete(id);\n }\n });\n return browser;\n });\n }\n try {\n return await abortable(\n signal,\n () => this.launching!,\n async () => {\n const browser = await this.launching?.catch(() => undefined);\n await browser?.close().catch(() => undefined);\n },\n );\n } finally {\n this.launching = undefined;\n }\n }\n\n private requireOwned(id: string, ownerId: string): LiveSession {\n const session = this.sessions.get(id);\n if (!session) throw new Error(`browser: unknown session \"${id}\"`);\n if (session.ownerId !== ownerId) throw new Error('browser: session belongs to another agent');\n session.lastUsedAt = new Date().toISOString();\n return session;\n }\n\n private async summary(session: LiveSession): Promise<BrowserSessionSummary> {\n return {\n id: session.id,\n ownerId: session.ownerId,\n url: safeBrowserUrl(session.page.url()),\n title: redactBrowserText(await session.page.title().catch(() => '')),\n createdAt: session.createdAt,\n lastUsedAt: session.lastUsedAt,\n tracing: session.tracing,\n };\n }\n\n private attachEvidenceCollectors(session: LiveSession): void {\n session.page.on('console', (message) => {\n pushBounded(\n session.console,\n {\n level: message.type(),\n text: redactBrowserText(message.text()).slice(0, 4_096),\n at: new Date().toISOString(),\n },\n this.maxConsoleEntries,\n );\n });\n session.page.on('response', (response) => {\n this.pushNetwork(session, {\n method: response.request().method(),\n url: safeBrowserUrl(response.url()),\n status: response.status(),\n at: new Date().toISOString(),\n });\n });\n session.page.on('requestfailed', (request) => {\n this.pushNetwork(session, {\n method: request.method(),\n url: safeBrowserUrl(request.url()),\n failed: true,\n at: new Date().toISOString(),\n });\n });\n }\n\n private pushNetwork(session: LiveSession, entry: BrowserNetworkEntry): void {\n pushBounded(session.network, entry, this.maxNetworkEntries);\n }\n\n private async runPageOperation<T>(\n session: LiveSession,\n signal: AbortSignal,\n operation: () => Promise<T>,\n ): Promise<T> {\n signal.throwIfAborted();\n session.lastUsedAt = new Date().toISOString();\n return abortable(signal, operation, async () => {\n await session.context.close().catch(() => undefined);\n this.sessions.delete(session.id);\n await this.closeBrowserIfIdle();\n });\n }\n\n private async closeBrowserIfIdle(): Promise<void> {\n if (this.sessions.size > 0 || !this.browser) return;\n const browser = this.browser;\n this.browser = undefined;\n await browser.close().catch(() => undefined);\n }\n}\n\nasync function defaultLauncher(headless: boolean): Promise<Browser> {\n try {\n const { chromium } = await import('@playwright/test');\n return await chromium.launch({ headless });\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(\n `browser: Playwright Chromium is unavailable (${detail}). Run \"pnpm exec playwright install chromium\".`,\n );\n }\n}\n\nexport async function browserInstallationDiagnostics(): Promise<{\n available: boolean;\n executablePath?: string | undefined;\n message: string;\n}> {\n try {\n const { chromium } = await import('@playwright/test');\n const executablePath = chromium.executablePath();\n await fs.access(executablePath);\n return { available: true, executablePath, message: 'Playwright Chromium is available.' };\n } catch {\n return {\n available: false,\n message: 'Playwright Chromium is unavailable. Run \"pnpm exec playwright install chromium\".',\n };\n }\n}\n\nfunction pushBounded<T>(target: T[], value: T, limit: number): void {\n target.push(value);\n if (target.length > limit) target.splice(0, target.length - limit);\n}\n\nasync function abortable<T>(\n signal: AbortSignal,\n operation: () => Promise<T>,\n onAbort: () => void | Promise<void>,\n): Promise<T> {\n signal.throwIfAborted();\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n let aborting = false;\n const finish = (fn: () => void) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', abort);\n fn();\n };\n const abort = () => {\n aborting = true;\n void Promise.resolve(onAbort()).finally(() => {\n finish(() => reject(signal.reason instanceof Error ? signal.reason : new Error('Aborted')));\n });\n };\n signal.addEventListener('abort', abort, { once: true });\n operation().then(\n (value) => {\n if (!aborting) finish(() => resolve(value));\n },\n (err) => {\n if (!aborting) finish(() => reject(err));\n },\n );\n });\n}\n", "import * as http from 'node:http';\nimport * as net from 'node:net';\nimport type { Duplex } from 'node:stream';\nimport type { BrowserDnsLookup } from './security.js';\nimport { resolvePinnedBrowserTarget } from './security.js';\n\nexport interface BrowserNetworkGuardProxyOptions {\n allowPrivateHosts?: boolean | undefined;\n allowedPrivateOrigins?: readonly string[] | undefined;\n lookup?: BrowserDnsLookup | undefined;\n connectTimeoutMs?: number | undefined;\n}\n\n/** Local HTTP proxy that pins every browser socket to its validated DNS answer. */\nexport class BrowserNetworkGuardProxy {\n private readonly server: http.Server;\n private readonly sockets = new Set<net.Socket>();\n private startPromise?: Promise<string> | undefined;\n private url?: string | undefined;\n\n constructor(private readonly options: BrowserNetworkGuardProxyOptions = {}) {\n this.server = http.createServer((request, response) => {\n void this.forwardHttp(request, response);\n });\n this.server.on('connect', (request, socket, head) => {\n void this.forwardConnect(request, socket, head);\n });\n this.server.on('upgrade', (request, socket, head) => {\n void this.forwardUpgrade(request, socket, head);\n });\n this.server.on('connection', (socket) => {\n this.sockets.add(socket);\n socket.once('close', () => this.sockets.delete(socket));\n // Browsers routinely abort speculative/idle connections. On Windows\n // that can surface as an asynchronous ECONNABORTED from a pipe write.\n // A Server's `clientError` event only covers HTTP parser failures; once\n // a socket becomes a CONNECT/WebSocket tunnel, an unhandled socket\n // `error` would otherwise terminate the entire host process.\n socket.on('error', () => {\n socket.destroy();\n });\n });\n this.server.on('clientError', (_error, socket) => {\n socket.end('HTTP/1.1 400 Bad Request\\r\\nConnection: close\\r\\n\\r\\n');\n });\n }\n\n async start(): Promise<string> {\n if (this.url) return this.url;\n if (this.startPromise) return this.startPromise;\n this.startPromise = new Promise<string>((resolve, reject) => {\n const onError = (error: Error) => {\n this.server.off('listening', onListening);\n reject(error);\n };\n const onListening = () => {\n this.server.off('error', onError);\n const address = this.server.address();\n if (!address || typeof address === 'string') {\n reject(new Error('browser: network guard proxy failed to bind'));\n return;\n }\n this.url = `http://127.0.0.1:${address.port}`;\n resolve(this.url);\n };\n this.server.once('error', onError);\n this.server.once('listening', onListening);\n this.server.listen(0, '127.0.0.1');\n }).finally(() => {\n this.startPromise = undefined;\n });\n return this.startPromise;\n }\n\n async close(): Promise<void> {\n this.url = undefined;\n for (const socket of this.sockets) socket.destroy();\n this.sockets.clear();\n if (!this.server.listening) return;\n await new Promise<void>((resolve) => this.server.close(() => resolve()));\n }\n\n private async forwardHttp(\n request: http.IncomingMessage,\n response: http.ServerResponse,\n ): Promise<void> {\n try {\n const target = await this.resolve(request.url ?? '');\n if (target.url.protocol !== 'http:') throw new Error('browser: HTTPS must use CONNECT');\n const headers = sanitizeHeaders(request.headers);\n headers.host = target.url.host;\n const upstream = http.request({\n host: target.address,\n family: target.family,\n port: Number(target.url.port || 80),\n method: request.method,\n path: `${target.url.pathname}${target.url.search}`,\n headers,\n agent: false,\n });\n upstream.setTimeout(this.options.connectTimeoutMs ?? 30_000, () => {\n upstream.destroy(new Error('browser: upstream connection timed out'));\n });\n upstream.on('response', (upstreamResponse) => {\n response.writeHead(\n upstreamResponse.statusCode ?? 502,\n sanitizeHeaders(upstreamResponse.headers),\n );\n upstreamResponse.pipe(response);\n });\n upstream.on('error', () => writeProxyError(response, 502, 'Bad Gateway'));\n request.on('aborted', () => upstream.destroy());\n request.pipe(upstream);\n } catch {\n writeProxyError(response, 403, 'Blocked by browser network policy');\n }\n }\n\n private async forwardConnect(\n request: http.IncomingMessage,\n client: Duplex,\n head: Buffer,\n ): Promise<void> {\n try {\n const authority = request.url ?? '';\n const target = await this.resolve(`https://${authority}`);\n const upstream = net.connect({\n host: target.address,\n family: target.family,\n port: Number(target.url.port || 443),\n });\n upstream.setTimeout(this.options.connectTimeoutMs ?? 30_000, () => upstream.destroy());\n const onConnectError = () => {\n client.end('HTTP/1.1 502 Bad Gateway\\r\\nConnection: close\\r\\n\\r\\n');\n };\n upstream.once('error', onConnectError);\n upstream.once('connect', () => {\n upstream.off('error', onConnectError);\n client.write('HTTP/1.1 200 Connection Established\\r\\n\\r\\n');\n if (head.length > 0) upstream.write(head);\n pipeDuplexPair(upstream, client);\n });\n client.once('close', () => upstream.destroy());\n } catch {\n client.end('HTTP/1.1 403 Forbidden\\r\\nConnection: close\\r\\n\\r\\n');\n }\n }\n\n private async forwardUpgrade(\n request: http.IncomingMessage,\n client: Duplex,\n head: Buffer,\n ): Promise<void> {\n let upstream: http.ClientRequest | undefined;\n try {\n const rawUrl = request.url ?? '';\n const websocketUrl = new URL(rawUrl);\n if (websocketUrl.protocol !== 'ws:') {\n throw new Error('browser: only plain ws upgrades are handled by the HTTP proxy');\n }\n websocketUrl.protocol = 'http:';\n const target = await this.resolve(websocketUrl.toString());\n const headers = sanitizeHeaders(request.headers, true);\n headers.host = target.url.host;\n upstream = http.request({\n host: target.address,\n family: target.family,\n port: Number(target.url.port || 80),\n method: request.method,\n path: `${target.url.pathname}${target.url.search}`,\n headers,\n agent: false,\n });\n upstream.once('upgrade', (response, upstreamSocket, upstreamHead) => {\n writeRawResponseHead(client, response);\n if (head.length > 0) upstreamSocket.write(head);\n if (upstreamHead.length > 0) client.write(upstreamHead);\n pipeDuplexPair(upstreamSocket, client);\n client.once('close', () => upstreamSocket.destroy());\n });\n upstream.once('response', (response) => {\n writeRawResponseHead(client, response);\n response.once('error', () => client.destroy());\n response.pipe(client);\n });\n upstream.once('error', () => {\n client.end('HTTP/1.1 502 Bad Gateway\\r\\nConnection: close\\r\\n\\r\\n');\n });\n client.once('close', () => upstream?.destroy());\n upstream.end();\n } catch {\n upstream?.destroy();\n client.end('HTTP/1.1 403 Forbidden\\r\\nConnection: close\\r\\n\\r\\n');\n }\n }\n\n private resolve(rawUrl: string) {\n return resolvePinnedBrowserTarget(rawUrl, {\n allowPrivateHosts: this.options.allowPrivateHosts,\n allowedPrivateOrigins: this.options.allowedPrivateOrigins,\n lookup: this.options.lookup,\n });\n }\n}\n\n/**\n * Couple both directions of a raw tunnel. `pipe()` deliberately does not\n * forward stream errors, so each destination needs its own listener before\n * either side can write. Destroying the peer also stops the opposite pipe and\n * prevents a disconnected browser socket from accumulating more writes.\n */\nfunction pipeDuplexPair(left: Duplex, right: Duplex): void {\n left.on('error', () => right.destroy());\n right.on('error', () => left.destroy());\n left.pipe(right);\n right.pipe(left);\n}\n\nfunction sanitizeHeaders(\n headers: http.IncomingHttpHeaders,\n preserveUpgrade = false,\n): http.OutgoingHttpHeaders {\n const sanitized: http.OutgoingHttpHeaders = { ...headers };\n delete sanitized['proxy-authorization'];\n delete sanitized['proxy-connection'];\n if (!preserveUpgrade) delete sanitized.connection;\n return sanitized;\n}\n\nfunction writeRawResponseHead(client: Duplex, response: http.IncomingMessage): void {\n const status = response.statusCode ?? 502;\n const statusText = response.statusMessage ?? 'Bad Gateway';\n const lines = [`HTTP/1.1 ${status} ${statusText}`];\n for (let index = 0; index < response.rawHeaders.length; index += 2) {\n lines.push(`${response.rawHeaders[index]}: ${response.rawHeaders[index + 1]}`);\n }\n client.write(`${lines.join('\\r\\n')}\\r\\n\\r\\n`);\n}\n\nfunction writeProxyError(response: http.ServerResponse, status: number, message: string): void {\n if (response.headersSent || response.destroyed) return;\n response.writeHead(status, { 'content-type': 'text/plain', connection: 'close' });\n response.end(message);\n}\n", "import * as dns from 'node:dns/promises';\nimport * as net from 'node:net';\nimport { assertNotPrivateHost, isPrivateIPv4, isPrivateIPv6 } from '@wrongstack/core/utils';\n\nconst SAFE_SUBRESOURCE_PROTOCOLS = new Set(['about:', 'blob:', 'data:']);\n\nexport async function assertBrowserUrlAllowed(\n rawUrl: string,\n opts: {\n allowPrivateHosts?: boolean | undefined;\n allowedPrivateOrigins?: readonly string[] | undefined;\n navigation?: boolean | undefined;\n },\n): Promise<URL> {\n const url = parseBrowserUrl(rawUrl, opts.navigation ?? true);\n if (!opts.navigation && SAFE_SUBRESOURCE_PROTOCOLS.has(url.protocol)) return url;\n if (!opts.allowPrivateHosts && !isAllowedPrivateOrigin(url, opts.allowedPrivateOrigins)) {\n await assertNotPrivateHost(url.hostname);\n }\n return url;\n}\n\nexport interface BrowserResolvedTarget {\n url: URL;\n address: string;\n family: 4 | 6;\n}\n\nexport type BrowserDnsLookup = (\n hostname: string,\n) => Promise<readonly { address: string; family: number }[]>;\n\n/**\n * Resolve once, validate every answer, and return the exact address a socket\n * must use. Callers must connect to `address`, never resolve `url.hostname`\n * again, otherwise DNS rebinding remains possible.\n */\nexport async function resolvePinnedBrowserTarget(\n rawUrl: string,\n opts: {\n allowPrivateHosts?: boolean | undefined;\n allowedPrivateOrigins?: readonly string[] | undefined;\n lookup?: BrowserDnsLookup | undefined;\n } = {},\n): Promise<BrowserResolvedTarget> {\n const url = parseBrowserUrl(rawUrl, true);\n const allowPrivate =\n opts.allowPrivateHosts === true || isAllowedPrivateOrigin(url, opts.allowedPrivateOrigins);\n const hostname = unbracket(url.hostname);\n const literalFamily = net.isIP(hostname);\n if (literalFamily === 4 || literalFamily === 6) {\n if (!allowPrivate && isPrivateAddress(hostname, literalFamily)) {\n throw new Error(`browser: blocked private/loopback address \"${hostname}\"`);\n }\n return { url, address: hostname, family: literalFamily };\n }\n if ((hostname === 'localhost' || hostname.endsWith('.localhost')) && !allowPrivate) {\n throw new Error('browser: blocked localhost target');\n }\n\n const lookup = opts.lookup ?? ((host) => dns.lookup(host, { all: true }));\n let records: readonly { address: string; family: number }[];\n try {\n records = await lookup(hostname);\n } catch (error) {\n throw new Error(\n `browser: DNS resolution failed for \"${hostname}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (records.length === 0) throw new Error(`browser: DNS returned no addresses for \"${hostname}\"`);\n\n for (const record of records) {\n if (record.family !== 4 && record.family !== 6) {\n throw new Error(`browser: DNS returned an unsupported address family for \"${hostname}\"`);\n }\n if (!allowPrivate && isPrivateAddress(record.address, record.family)) {\n throw new Error(`browser: resolved to private address ${record.address}`);\n }\n }\n const selected = records[0]!;\n return { url, address: selected.address, family: selected.family as 4 | 6 };\n}\n\nexport function parsePrivateOriginAllowlist(raw: string | undefined): string[] {\n if (!raw?.trim()) return [];\n const origins = new Set<string>();\n for (const entry of raw.split(',')) {\n const candidate = entry.trim();\n if (!candidate) continue;\n const url = parseBrowserUrl(candidate, true);\n if (url.pathname !== '/' || url.search || url.hash) {\n throw new Error(`browser: private origin allowlist entry must be an origin: \"${candidate}\"`);\n }\n origins.add(url.origin);\n }\n return [...origins];\n}\n\nfunction parseBrowserUrl(rawUrl: string, navigation: boolean): URL {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new Error('browser: url must be an absolute URL');\n }\n if (!navigation && SAFE_SUBRESOURCE_PROTOCOLS.has(url.protocol)) return url;\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(`browser: unsupported protocol \"${url.protocol}\"`);\n }\n if (url.username || url.password) {\n throw new Error('browser: credentials in URLs are not allowed');\n }\n return url;\n}\n\nfunction isAllowedPrivateOrigin(url: URL, origins: readonly string[] | undefined): boolean {\n return origins?.includes(url.origin) ?? false;\n}\n\nfunction isPrivateAddress(address: string, family: 4 | 6): boolean {\n return family === 4 ? isPrivateIPv4(address) : isPrivateIPv6(address);\n}\n\nfunction unbracket(hostname: string): string {\n return hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n}\n\n/** Remove credentials, query strings, and fragments before persistence/output. */\nexport function safeBrowserUrl(rawUrl: string): string {\n try {\n const url = new URL(rawUrl);\n url.username = '';\n url.password = '';\n url.search = '';\n url.hash = '';\n return url.toString();\n } catch {\n return 'about:blank';\n }\n}\n\nexport function redactBrowserText(text: string): string {\n return text\n .replace(/\\bBearer\\s+[A-Za-z0-9._~+/-]+=*/gi, 'Bearer [REDACTED]')\n .replace(\n /\\b(api[-_ ]?key|access[-_ ]?token|auth[-_ ]?token|token|password|secret)\\b\\s*[:=]\\s*[^\\s,;]+/gi,\n '$1=[REDACTED]',\n );\n}\n", "import * as path from 'node:path';\nimport type { Context } from '@wrongstack/core/agent';\nimport { ToolCapabilities } from '@wrongstack/core/security';\nimport type { Tool } from '@wrongstack/core/types';\nimport { resolveWstackPaths } from '@wrongstack/core/utils';\nimport { BrowserSessionManager, browserInstallationDiagnostics } from './manager.js';\nimport { parsePrivateOriginAllowlist } from './security.js';\n\nconst managers = new Map<string, BrowserSessionManager>();\nconst cleanupSignalByContext = new WeakMap<object, AbortSignal>();\n\nfunction managerFor(ctx: Context): BrowserSessionManager {\n const root = path.resolve(ctx.projectRoot);\n let manager = managers.get(root);\n if (!manager) {\n const wpaths = resolveWstackPaths({ projectRoot: root });\n manager = new BrowserSessionManager({\n artifactRoot: path.join(wpaths.projectDir, 'browser-artifacts'),\n allowedPrivateOrigins: parsePrivateOriginAllowlist(\n process.env['WRONGSTACK_BROWSER_PRIVATE_ORIGINS'],\n ),\n });\n managers.set(root, manager);\n }\n const runSignal = ctx.signal;\n if (cleanupSignalByContext.get(ctx) !== runSignal) {\n cleanupSignalByContext.set(ctx, runSignal);\n const managerForRun = manager;\n const rootForRun = root;\n const ownerForRun = owner(ctx);\n ctx.registerAbortHook?.(async () => {\n if (cleanupSignalByContext.get(ctx) === runSignal) {\n cleanupSignalByContext.delete(ctx);\n }\n await managerForRun.closeOwner(ownerForRun);\n // Managers are keyed by project root and own a listening network proxy.\n // Drop the entry as soon as the final owner is gone so project switching\n // cannot accumulate one proxy/server handle per visited repository.\n if (managerForRun.isIdle() && managers.get(rootForRun) === managerForRun) {\n managers.delete(rootForRun);\n await managerForRun.dispose();\n }\n });\n }\n return manager;\n}\n\nfunction owner(ctx: Context): string {\n return ctx.agentId || 'leader';\n}\n\nfunction json(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nconst sessionIdSchema = {\n type: 'string',\n minLength: 1,\n description: 'Browser session id returned by browser_open.',\n} as const;\n\nexport const browserOpenTool: Tool<{\n url?: string | undefined;\n width?: number | undefined;\n height?: number | undefined;\n trace?: boolean | undefined;\n}> = {\n name: 'browser_open',\n description:\n 'Open an isolated first-party Playwright browser session, optionally navigating to a URL.',\n usageHint: 'browser_open({ url?, width?, height?, trace? })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n subjectKey: 'url',\n inputSchema: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'Optional absolute http(s) URL.' },\n width: { type: 'integer', minimum: 320, maximum: 3840 },\n height: { type: 'integer', minimum: 240, maximum: 2160 },\n trace: { type: 'boolean', description: 'Capture a Playwright trace; defaults to true.' },\n },\n },\n async execute(input, ctx, opts) {\n const viewport =\n input.width || input.height\n ? { width: input.width ?? 1440, height: input.height ?? 900 }\n : undefined;\n return json(\n await managerFor(ctx).open(\n owner(ctx),\n { url: input.url, viewport, trace: input.trace },\n opts.signal,\n ),\n );\n },\n};\n\nexport const browserListTool: Tool<Record<string, never>> = {\n name: 'browser_list',\n description:\n 'List browser sessions owned by the current agent without exposing other agents sessions.',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: { type: 'object', properties: {} },\n async execute(_input, ctx) {\n return json(await managerFor(ctx).list(owner(ctx)));\n },\n};\n\nexport const browserStatusTool: Tool<Record<string, never>> = {\n name: 'browser_status',\n description: 'Check whether first-party Playwright Chromium is installed and ready to launch.',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.TOOL_META],\n inputSchema: { type: 'object', properties: {} },\n async execute() {\n return json(await browserInstallationDiagnostics());\n },\n};\n\nexport const browserNavigateTool: Tool<{ sessionId: string; url: string }> = {\n name: 'browser_navigate',\n description: 'Navigate an owned browser session to an approved http(s) URL.',\n usageHint: 'browser_navigate({ sessionId, url })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n subjectKey: 'url',\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema, url: { type: 'string', minLength: 1 } },\n required: ['sessionId', 'url'],\n },\n async execute(input, ctx, opts) {\n return json(\n await managerFor(ctx).navigate(input.sessionId, owner(ctx), input.url, opts.signal),\n );\n },\n};\n\nexport const browserSnapshotTool: Tool<{ sessionId: string }> = {\n name: 'browser_snapshot',\n description: 'Return bounded accessibility state plus redacted console and network summaries.',\n usageHint: 'browser_snapshot({ sessionId })',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema },\n required: ['sessionId'],\n },\n async execute(input, ctx, opts) {\n return json(await managerFor(ctx).snapshot(input.sessionId, owner(ctx), opts.signal));\n },\n};\n\nexport const browserScreenshotTool: Tool<{\n sessionId: string;\n fullPage?: boolean | undefined;\n selector?: string | undefined;\n}> = {\n name: 'browser_screenshot',\n description:\n 'Capture a page or element PNG and return sensitive artifact metadata with integrity hash.',\n usageHint: 'browser_screenshot({ sessionId, fullPage?, selector? })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n fullPage: { type: 'boolean' },\n selector: { type: 'string', minLength: 1 },\n },\n required: ['sessionId'],\n },\n async execute(input, ctx, opts) {\n return json(\n await managerFor(ctx).screenshot(\n input.sessionId,\n owner(ctx),\n { fullPage: input.fullPage, selector: input.selector },\n opts.signal,\n ),\n );\n },\n};\n\ntype SelectorInput = { sessionId: string; selector: string };\n\nfunction selectorTool(\n name: string,\n description: string,\n run: (\n manager: BrowserSessionManager,\n input: SelectorInput,\n ownerId: string,\n signal: AbortSignal,\n ) => Promise<void>,\n): Tool<SelectorInput> {\n return {\n name,\n description,\n usageHint: `${name}({ sessionId, selector })`,\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema, selector: { type: 'string', minLength: 1 } },\n required: ['sessionId', 'selector'],\n },\n async execute(input, ctx, opts) {\n await run(managerFor(ctx), input, owner(ctx), opts.signal);\n return 'ok';\n },\n };\n}\n\nexport const browserClickTool = selectorTool(\n 'browser_click',\n 'Click an element in an owned browser session.',\n (manager, input, ownerId, signal) =>\n manager.click(input.sessionId, ownerId, input.selector, signal),\n);\n\nexport const browserHoverTool = selectorTool(\n 'browser_hover',\n 'Hover an element in an owned browser session.',\n (manager, input, ownerId, signal) =>\n manager.hover(input.sessionId, ownerId, input.selector, signal),\n);\n\nexport const browserTypeTool: Tool<\n SelectorInput & { text?: string | undefined; secretEnv?: string | undefined }\n> = {\n name: 'browser_type',\n description:\n 'Fill an input in an owned browser session. Use secretEnv instead of text for credentials so values stay out of tool arguments and session audit.',\n usageHint: 'browser_type({ sessionId, selector, text? | secretEnv? })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n text: { type: 'string' },\n secretEnv: {\n type: 'string',\n pattern: '^[A-Z_][A-Z0-9_]*$',\n description: 'Host environment variable resolved only at execution time.',\n },\n },\n required: ['sessionId', 'selector'],\n },\n validate(input) {\n return (input.text === undefined) === (input.secretEnv === undefined)\n ? ['exactly one of text or secretEnv is required']\n : [];\n },\n async execute(input, ctx, opts) {\n const value = input.text ?? (input.secretEnv ? process.env[input.secretEnv] : undefined);\n if (value === undefined) {\n throw new Error(`browser: secret environment variable \"${input.secretEnv ?? ''}\" is not set`);\n }\n await managerFor(ctx).type(input.sessionId, owner(ctx), input.selector, value, opts.signal);\n return 'ok';\n },\n};\n\nexport const browserSelectTool: Tool<SelectorInput & { value: string }> = {\n name: 'browser_select',\n description: 'Select an option in an owned browser session.',\n usageHint: 'browser_select({ sessionId, selector, value })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n value: { type: 'string' },\n },\n required: ['sessionId', 'selector', 'value'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).select(\n input.sessionId,\n owner(ctx),\n input.selector,\n input.value,\n opts.signal,\n );\n return 'ok';\n },\n};\n\nexport const browserPressTool: Tool<{ sessionId: string; key: string }> = {\n name: 'browser_press',\n description: 'Press a keyboard key in an owned browser session.',\n usageHint: 'browser_press({ sessionId, key })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema, key: { type: 'string', minLength: 1 } },\n required: ['sessionId', 'key'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).press(input.sessionId, owner(ctx), input.key, opts.signal);\n return 'ok';\n },\n};\n\nexport const browserDragTool: Tool<{ sessionId: string; from: string; to: string }> = {\n name: 'browser_drag',\n description: 'Drag one element to another in an owned browser session.',\n usageHint: 'browser_drag({ sessionId, from, to })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n from: { type: 'string', minLength: 1 },\n to: { type: 'string', minLength: 1 },\n },\n required: ['sessionId', 'from', 'to'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).drag(input.sessionId, owner(ctx), input.from, input.to, opts.signal);\n return 'ok';\n },\n};\n\nexport const browserWaitTool: Tool<{\n sessionId: string;\n selector?: string | undefined;\n timeoutMs?: number | undefined;\n}> = {\n name: 'browser_wait',\n description: 'Wait for an element or a bounded duration in an owned browser session.',\n usageHint: 'browser_wait({ sessionId, selector?, timeoutMs? })',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n timeoutMs: { type: 'integer', minimum: 0, maximum: 30000 },\n },\n required: ['sessionId'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).wait(\n input.sessionId,\n owner(ctx),\n { selector: input.selector, timeoutMs: input.timeoutMs },\n opts.signal,\n );\n return 'ok';\n },\n};\n\nexport const browserEvaluateTool: Tool<{ sessionId: string; expression: string }> = {\n name: 'browser_evaluate',\n description:\n 'Evaluate bounded JavaScript in the page. Requires confirmation because page code is arbitrary.',\n usageHint: 'browser_evaluate({ sessionId, expression })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'destructive',\n capabilities: [ToolCapabilities.NET_OUTBOUND, ToolCapabilities.TOOL_MUTATE_ANY],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n expression: { type: 'string', minLength: 1, maxLength: 16384 },\n },\n required: ['sessionId', 'expression'],\n },\n async execute(input, ctx, opts) {\n return json(\n await managerFor(ctx).evaluate(input.sessionId, owner(ctx), input.expression, opts.signal),\n );\n },\n};\n\nexport const browserUploadTool: Tool<SelectorInput & { files: string[] }> = {\n name: 'browser_upload',\n description: 'Upload project-local files through a file input in an owned browser session.',\n usageHint: 'browser_upload({ sessionId, selector, files })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'destructive',\n capabilities: [ToolCapabilities.NET_OUTBOUND, ToolCapabilities.FS_READ],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n files: { type: 'array', minItems: 1, maxItems: 20, items: { type: 'string', minLength: 1 } },\n },\n required: ['sessionId', 'selector', 'files'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).upload(\n input.sessionId,\n owner(ctx),\n input.selector,\n input.files,\n ctx.projectRoot,\n opts.signal,\n );\n return 'ok';\n },\n};\n\nexport const browserCloseTool: Tool<{ sessionId: string }> = {\n name: 'browser_close',\n description:\n 'Close an owned browser session, reclaim its context, and return sensitive trace metadata.',\n usageHint: 'browser_close({ sessionId })',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema },\n required: ['sessionId'],\n },\n async execute(input, ctx) {\n return json(await managerFor(ctx).close(input.sessionId, owner(ctx)));\n },\n};\n\nexport const browserTools: Tool[] = [\n browserOpenTool,\n browserStatusTool,\n browserListTool,\n browserNavigateTool,\n browserSnapshotTool,\n browserScreenshotTool,\n browserClickTool,\n browserTypeTool,\n browserSelectTool,\n browserPressTool,\n browserHoverTool,\n browserDragTool,\n browserWaitTool,\n browserEvaluateTool,\n browserUploadTool,\n browserCloseTool,\n];\n\nfor (const tool of browserTools) tool.icon = 'web';\nfor (const tool of browserTools) tool.timeoutMs ??= 60_000;\n\nexport async function shutdownBrowserTools(): Promise<void> {\n const active = [...managers.values()];\n managers.clear();\n await Promise.all(active.map((manager) => manager.dispose()));\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createHash } from 'node:crypto';\nimport { createReadStream } from 'node:fs';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { atomicWrite, ulid } from '@wrongstack/core/utils';\nimport type { BrowserArtifact, BrowserArtifactKind } from './types.js';\n\n/**\n * How long a browser artifact (screenshot, trace, download) stays on disk.\n *\n * Artifacts are debugging exhaust: a screenshot is interesting while the run\n * that produced it is being looked at, and dead weight after. Nothing pruned\n * them, so they accumulated for as long as the project existed \u2014 measured at\n * 2.1 GB across 247 files in one project. Seven days matches the tool-output\n * spool, which is the same kind of data with the same access pattern.\n */\nconst ARTIFACT_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** Roots already swept in this process. */\nconst sweptRoots = new Set<string>();\n\n/** Reset module state \u2014 test hook (per-process sweep memo only). */\nexport function _resetArtifactSweepForTests(): void {\n sweptRoots.clear();\n}\n\n/**\n * Delete artifacts older than the retention window. Runs once per root per\n * process, detached and best-effort: a browser tool must never fail because\n * housekeeping could not read a directory.\n */\nfunction sweepOldArtifacts(root: string): void {\n if (sweptRoots.has(root)) return;\n sweptRoots.add(root);\n void (async () => {\n const cutoff = Date.now() - ARTIFACT_RETENTION_MS;\n let sessionDirs: string[];\n try {\n const entries = await fs.readdir(root, { withFileTypes: true });\n sessionDirs = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);\n } catch {\n return; // no artifact root yet \u2014 nothing to sweep\n }\n for (const sessionDir of sessionDirs) {\n const dir = path.join(root, sessionDir);\n let names: string[];\n try {\n names = await fs.readdir(dir);\n } catch {\n continue;\n }\n let removed = 0;\n for (const name of names) {\n const target = path.join(dir, name);\n try {\n const stat = await fs.stat(target);\n if (stat.isFile() && stat.mtimeMs < cutoff) {\n await fs.rm(target, { force: true });\n removed++;\n }\n } catch {\n /* concurrently removed \u2014 ignore */\n }\n }\n // Drop the session directory once it has gone empty, so the artifact\n // root does not accumulate thousands of empty per-session folders.\n if (removed === names.length && names.length > 0) {\n await fs.rmdir(dir).catch(() => undefined);\n }\n }\n })();\n}\n\nexport class BrowserArtifactStore {\n constructor(private readonly root: string) {\n sweepOldArtifacts(root);\n }\n\n async write(\n sessionId: string,\n kind: BrowserArtifactKind,\n extension: string,\n mimeType: string,\n content: Uint8Array,\n ): Promise<BrowserArtifact> {\n const id = ulid();\n const dir = path.join(this.root, safeSegment(sessionId));\n const target = path.join(dir, `${id}.${extension.replace(/^\\./, '')}`);\n await atomicWrite(target, content, { mode: 0o600 });\n return this.record(id, sessionId, kind, target, mimeType);\n }\n\n private async record(\n id: string,\n sessionId: string,\n kind: BrowserArtifactKind,\n target: string,\n mimeType: string,\n ): Promise<BrowserArtifact> {\n await fs.chmod(target, 0o600).catch(() => undefined);\n const [stat, sha256] = await Promise.all([fs.stat(target), hashFile(target)]);\n const artifact: BrowserArtifact = {\n id,\n kind,\n sensitivity: 'sensitive',\n path: target,\n mimeType,\n sizeBytes: stat.size,\n sha256,\n createdAt: new Date().toISOString(),\n };\n const metadataPath = path.join(path.dirname(target), `${id}.metadata.json`);\n try {\n await atomicWrite(\n metadataPath,\n `${JSON.stringify({\n id: artifact.id,\n sessionId: safeSegment(sessionId),\n kind: artifact.kind,\n sensitivity: artifact.sensitivity,\n mimeType: artifact.mimeType,\n sizeBytes: artifact.sizeBytes,\n sha256: artifact.sha256,\n createdAt: artifact.createdAt,\n })}\\n`,\n { mode: 0o600 },\n );\n } catch (error) {\n await fs.rm(target, { force: true }).catch(() => undefined);\n throw error;\n }\n return artifact;\n }\n\n pathFor(sessionId: string, extension: string): { id: string; path: string } {\n const id = ulid();\n return {\n id,\n path: path.join(this.root, safeSegment(sessionId), `${id}.${extension.replace(/^\\./, '')}`),\n };\n }\n\n async describe(\n id: string,\n kind: BrowserArtifactKind,\n target: string,\n mimeType: string,\n ): Promise<BrowserArtifact> {\n return this.record(id, path.basename(path.dirname(target)), kind, target, mimeType);\n }\n}\n\nasync function hashFile(target: string): Promise<string> {\n const hash = createHash('sha256');\n await new Promise<void>((resolve, reject) => {\n const stream = createReadStream(target);\n stream.on('data', (chunk) => hash.update(chunk));\n stream.once('error', reject);\n stream.once('end', resolve);\n });\n return hash.digest('hex');\n}\n\nfunction safeSegment(value: string): string {\n return value.replace(/[^A-Za-z0-9_-]/g, '_').slice(0, 80);\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Browser, BrowserContext, Page } from '@playwright/test';\nimport { ulid } from '@wrongstack/core/utils';\nimport { BrowserArtifactStore } from './artifacts.js';\nimport { BrowserNetworkGuardProxy } from './network-guard-proxy.js';\nimport { assertBrowserUrlAllowed, redactBrowserText, safeBrowserUrl } from './security.js';\nimport type {\n BrowserArtifact,\n BrowserConsoleEntry,\n BrowserManagerOptions,\n BrowserNetworkEntry,\n BrowserOpenOptions,\n BrowserSessionSummary,\n BrowserSnapshot,\n} from './types.js';\n\nconst DEFAULT_OPERATION_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_SNAPSHOT_CHARS = 64 * 1024;\nconst DEFAULT_MAX_ENTRIES = 100;\n\ninterface LiveSession {\n id: string;\n ownerId: string;\n context: BrowserContext;\n page: Page;\n createdAt: string;\n lastUsedAt: string;\n tracing: boolean;\n console: BrowserConsoleEntry[];\n network: BrowserNetworkEntry[];\n}\n\nexport type BrowserLauncher = (headless: boolean) => Promise<Browser>;\n\nexport class BrowserSessionManager {\n private readonly sessions = new Map<string, LiveSession>();\n private readonly artifacts: BrowserArtifactStore;\n private readonly allowPrivateHosts: boolean;\n private readonly allowedPrivateOrigins: readonly string[];\n private readonly networkProxy: BrowserNetworkGuardProxy;\n private readonly headless: boolean;\n private readonly operationTimeoutMs: number;\n private readonly maxSnapshotChars: number;\n private readonly maxConsoleEntries: number;\n private readonly maxNetworkEntries: number;\n private browser?: Browser | undefined;\n private launching?: Promise<Browser> | undefined;\n\n constructor(\n options: BrowserManagerOptions,\n private readonly launcher: BrowserLauncher = defaultLauncher,\n ) {\n this.artifacts = new BrowserArtifactStore(options.artifactRoot);\n this.allowPrivateHosts = options.allowPrivateHosts ?? true;\n this.allowedPrivateOrigins = options.allowedPrivateOrigins ?? [];\n this.networkProxy = new BrowserNetworkGuardProxy({\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n });\n this.headless = options.headless ?? true;\n this.operationTimeoutMs = options.operationTimeoutMs ?? DEFAULT_OPERATION_TIMEOUT_MS;\n this.maxSnapshotChars = options.maxSnapshotChars ?? DEFAULT_MAX_SNAPSHOT_CHARS;\n this.maxConsoleEntries = options.maxConsoleEntries ?? DEFAULT_MAX_ENTRIES;\n this.maxNetworkEntries = options.maxNetworkEntries ?? DEFAULT_MAX_ENTRIES;\n }\n\n async open(\n ownerId: string,\n input: BrowserOpenOptions,\n signal: AbortSignal,\n ): Promise<BrowserSessionSummary> {\n signal.throwIfAborted();\n if (input.url) {\n await assertBrowserUrlAllowed(input.url, {\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n navigation: true,\n });\n }\n const browser = await this.ensureBrowser(signal);\n const proxyServer = await this.networkProxy.start();\n const context = await abortable(\n signal,\n async () => {\n const created = await browser.newContext({\n acceptDownloads: false,\n ignoreHTTPSErrors: false,\n serviceWorkers: 'block',\n proxy: { server: proxyServer },\n viewport: input.viewport ?? { width: 1440, height: 900 },\n });\n if (signal.aborted) {\n await created.close().catch(() => undefined);\n signal.throwIfAborted();\n }\n return created;\n },\n () => undefined,\n );\n const session: LiveSession = {\n id: ulid(),\n ownerId,\n context,\n page: await context.newPage(),\n createdAt: new Date().toISOString(),\n lastUsedAt: new Date().toISOString(),\n tracing: input.trace ?? true,\n console: [],\n network: [],\n };\n this.sessions.set(session.id, session);\n this.attachEvidenceCollectors(session);\n await context.route('**/*', async (route) => {\n try {\n await assertBrowserUrlAllowed(route.request().url(), {\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n navigation: false,\n });\n await route.continue();\n } catch {\n this.pushNetwork(session, {\n method: route.request().method(),\n url: safeBrowserUrl(route.request().url()),\n failed: true,\n at: new Date().toISOString(),\n });\n await route.abort('blockedbyclient');\n }\n });\n try {\n if (session.tracing) {\n await context.tracing.start({ screenshots: true, snapshots: true, sources: false });\n }\n if (input.url) await this.navigate(session.id, ownerId, input.url, signal);\n return await this.summary(session);\n } catch (err) {\n await context.close().catch(() => undefined);\n this.sessions.delete(session.id);\n await this.closeBrowserIfIdle();\n throw err;\n }\n }\n\n async list(ownerId: string): Promise<BrowserSessionSummary[]> {\n const owned = [...this.sessions.values()].filter((session) => session.ownerId === ownerId);\n return Promise.all(owned.map((session) => this.summary(session)));\n }\n\n async navigate(\n id: string,\n ownerId: string,\n rawUrl: string,\n signal: AbortSignal,\n ): Promise<BrowserSessionSummary> {\n await assertBrowserUrlAllowed(rawUrl, {\n allowPrivateHosts: this.allowPrivateHosts,\n allowedPrivateOrigins: this.allowedPrivateOrigins,\n navigation: true,\n });\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.goto(rawUrl, {\n waitUntil: 'domcontentloaded',\n timeout: this.operationTimeoutMs,\n }),\n );\n return this.summary(session);\n }\n\n async snapshot(id: string, ownerId: string, signal: AbortSignal): Promise<BrowserSnapshot> {\n const session = this.requireOwned(id, ownerId);\n const raw = await this.runPageOperation(session, signal, async () => {\n try {\n return await session.page\n .locator('body')\n .ariaSnapshot({ timeout: this.operationTimeoutMs });\n } catch {\n return await session.page.locator('body').innerText({ timeout: this.operationTimeoutMs });\n }\n });\n const aria = redactBrowserText(raw);\n const truncated = aria.length > this.maxSnapshotChars;\n return {\n session: await this.summary(session),\n aria: truncated ? `${aria.slice(0, this.maxSnapshotChars)}\\n\u2026[snapshot truncated]` : aria,\n console: session.console.map((entry) => ({ ...entry })),\n network: session.network.map((entry) => ({ ...entry })),\n truncated,\n };\n }\n\n async screenshot(\n id: string,\n ownerId: string,\n input: { fullPage?: boolean | undefined; selector?: string | undefined },\n signal: AbortSignal,\n ): Promise<BrowserArtifact> {\n const session = this.requireOwned(id, ownerId);\n const bytes = await this.runPageOperation(session, signal, () =>\n input.selector\n ? session.page\n .locator(input.selector)\n .screenshot({ type: 'png', timeout: this.operationTimeoutMs })\n : session.page.screenshot({ type: 'png', fullPage: input.fullPage ?? false }),\n );\n signal.throwIfAborted();\n return this.artifacts.write(session.id, 'screenshot', 'png', 'image/png', bytes);\n }\n\n async click(id: string, ownerId: string, selector: string, signal: AbortSignal): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).click({ timeout: this.operationTimeoutMs }),\n );\n }\n\n async type(\n id: string,\n ownerId: string,\n selector: string,\n text: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).fill(text, { timeout: this.operationTimeoutMs }),\n );\n }\n\n async select(\n id: string,\n ownerId: string,\n selector: string,\n value: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).selectOption(value, { timeout: this.operationTimeoutMs }),\n );\n }\n\n async press(id: string, ownerId: string, key: string, signal: AbortSignal): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () => session.page.keyboard.press(key));\n }\n\n async hover(id: string, ownerId: string, selector: string, signal: AbortSignal): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).hover({ timeout: this.operationTimeoutMs }),\n );\n }\n\n async wait(\n id: string,\n ownerId: string,\n input: { selector?: string | undefined; timeoutMs?: number | undefined },\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n const timeout = Math.min(\n Math.max(input.timeoutMs ?? this.operationTimeoutMs, 0),\n this.operationTimeoutMs,\n );\n await this.runPageOperation(session, signal, () =>\n input.selector\n ? session.page.locator(input.selector).waitFor({ state: 'visible', timeout })\n : session.page.waitForTimeout(timeout),\n );\n }\n\n async drag(\n id: string,\n ownerId: string,\n from: string,\n to: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n await this.runPageOperation(session, signal, () =>\n session.page.locator(from).dragTo(session.page.locator(to), {\n timeout: this.operationTimeoutMs,\n }),\n );\n }\n\n async upload(\n id: string,\n ownerId: string,\n selector: string,\n files: string[],\n projectRoot: string,\n signal: AbortSignal,\n ): Promise<void> {\n const session = this.requireOwned(id, ownerId);\n const root = path.resolve(projectRoot);\n const realRoot = await fs.realpath(root);\n const resolved: string[] = [];\n for (const file of files) {\n const absolute = path.resolve(root, file);\n const relative = path.relative(root, absolute);\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n throw new Error('browser: upload files must stay inside the project root');\n }\n const realFile = await fs.realpath(absolute);\n const realRelative = path.relative(realRoot, realFile);\n if (realRelative.startsWith('..') || path.isAbsolute(realRelative)) {\n throw new Error('browser: upload files must not escape the project root through a symlink');\n }\n const stat = await fs.stat(realFile);\n if (!stat.isFile()) throw new Error(`browser: upload target is not a file: ${file}`);\n resolved.push(realFile);\n }\n await this.runPageOperation(session, signal, () =>\n session.page.locator(selector).setInputFiles(resolved, { timeout: this.operationTimeoutMs }),\n );\n }\n\n async evaluate(\n id: string,\n ownerId: string,\n expression: string,\n signal: AbortSignal,\n ): Promise<unknown> {\n const session = this.requireOwned(id, ownerId);\n const result = await this.runPageOperation(session, signal, () =>\n session.page.evaluate(expression),\n );\n const serialized = JSON.stringify(result);\n if (serialized && serialized.length > this.maxSnapshotChars) {\n throw new Error(`browser: evaluation result exceeds ${this.maxSnapshotChars} characters`);\n }\n return result;\n }\n\n async close(id: string, ownerId: string): Promise<{ trace?: BrowserArtifact | undefined }> {\n const session = this.requireOwned(id, ownerId);\n let trace: BrowserArtifact | undefined;\n try {\n if (session.tracing) {\n const target = this.artifacts.pathFor(session.id, 'zip');\n await fs.mkdir(path.dirname(target.path), { recursive: true });\n await session.context.tracing.stop({ path: target.path });\n trace = await this.artifacts.describe(target.id, 'trace', target.path, 'application/zip');\n }\n } finally {\n await session.context.close().catch(() => undefined);\n this.sessions.delete(id);\n await this.closeBrowserIfIdle();\n }\n return trace ? { trace } : {};\n }\n\n async closeOwner(ownerId: string): Promise<void> {\n const ids = [...this.sessions.values()]\n .filter((session) => session.ownerId === ownerId)\n .map((session) => session.id);\n for (const id of ids) await this.close(id, ownerId).catch(() => undefined);\n }\n\n /** True when the manager owns no live browser contexts. */\n isIdle(): boolean {\n return this.sessions.size === 0;\n }\n\n async dispose(): Promise<void> {\n for (const session of [...this.sessions.values()]) {\n await session.context.close().catch(() => undefined);\n }\n this.sessions.clear();\n const browser = this.browser;\n this.browser = undefined;\n this.launching = undefined;\n await browser?.close().catch(() => undefined);\n await this.networkProxy.close();\n }\n\n private async ensureBrowser(signal: AbortSignal): Promise<Browser> {\n if (this.browser?.isConnected()) return this.browser;\n if (!this.launching) {\n this.launching = this.launcher(this.headless).then((browser) => {\n this.browser = browser;\n browser.on('disconnected', () => {\n if (this.browser === browser) this.browser = undefined;\n for (const [id, session] of this.sessions) {\n if (session.context.browser() === browser) this.sessions.delete(id);\n }\n });\n return browser;\n });\n }\n try {\n return await abortable(\n signal,\n () => this.launching!,\n async () => {\n const browser = await this.launching?.catch(() => undefined);\n await browser?.close().catch(() => undefined);\n },\n );\n } finally {\n this.launching = undefined;\n }\n }\n\n private requireOwned(id: string, ownerId: string): LiveSession {\n const session = this.sessions.get(id);\n if (!session) throw new Error(`browser: unknown session \"${id}\"`);\n if (session.ownerId !== ownerId) throw new Error('browser: session belongs to another agent');\n session.lastUsedAt = new Date().toISOString();\n return session;\n }\n\n private async summary(session: LiveSession): Promise<BrowserSessionSummary> {\n return {\n id: session.id,\n ownerId: session.ownerId,\n url: safeBrowserUrl(session.page.url()),\n title: redactBrowserText(await session.page.title().catch(() => '')),\n createdAt: session.createdAt,\n lastUsedAt: session.lastUsedAt,\n tracing: session.tracing,\n };\n }\n\n private attachEvidenceCollectors(session: LiveSession): void {\n session.page.on('console', (message) => {\n pushBounded(\n session.console,\n {\n level: message.type(),\n text: redactBrowserText(message.text()).slice(0, 4_096),\n at: new Date().toISOString(),\n },\n this.maxConsoleEntries,\n );\n });\n session.page.on('response', (response) => {\n this.pushNetwork(session, {\n method: response.request().method(),\n url: safeBrowserUrl(response.url()),\n status: response.status(),\n at: new Date().toISOString(),\n });\n });\n session.page.on('requestfailed', (request) => {\n this.pushNetwork(session, {\n method: request.method(),\n url: safeBrowserUrl(request.url()),\n failed: true,\n at: new Date().toISOString(),\n });\n });\n }\n\n private pushNetwork(session: LiveSession, entry: BrowserNetworkEntry): void {\n pushBounded(session.network, entry, this.maxNetworkEntries);\n }\n\n private async runPageOperation<T>(\n session: LiveSession,\n signal: AbortSignal,\n operation: () => Promise<T>,\n ): Promise<T> {\n signal.throwIfAborted();\n session.lastUsedAt = new Date().toISOString();\n return abortable(signal, operation, async () => {\n await session.context.close().catch(() => undefined);\n this.sessions.delete(session.id);\n await this.closeBrowserIfIdle();\n });\n }\n\n private async closeBrowserIfIdle(): Promise<void> {\n if (this.sessions.size > 0 || !this.browser) return;\n const browser = this.browser;\n this.browser = undefined;\n await browser.close().catch(() => undefined);\n }\n}\n\nasync function defaultLauncher(headless: boolean): Promise<Browser> {\n try {\n const { chromium } = await import('@playwright/test');\n return await chromium.launch({ headless });\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(\n `browser: Playwright Chromium is unavailable (${detail}). Run \"pnpm exec playwright install chromium\".`,\n );\n }\n}\n\nexport async function browserInstallationDiagnostics(): Promise<{\n available: boolean;\n executablePath?: string | undefined;\n message: string;\n}> {\n try {\n const { chromium } = await import('@playwright/test');\n const executablePath = chromium.executablePath();\n await fs.access(executablePath);\n return { available: true, executablePath, message: 'Playwright Chromium is available.' };\n } catch {\n return {\n available: false,\n message: 'Playwright Chromium is unavailable. Run \"pnpm exec playwright install chromium\".',\n };\n }\n}\n\nfunction pushBounded<T>(target: T[], value: T, limit: number): void {\n target.push(value);\n if (target.length > limit) target.splice(0, target.length - limit);\n}\n\nasync function abortable<T>(\n signal: AbortSignal,\n operation: () => Promise<T>,\n onAbort: () => void | Promise<void>,\n): Promise<T> {\n signal.throwIfAborted();\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n let aborting = false;\n const finish = (fn: () => void) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener('abort', abort);\n fn();\n };\n const abort = () => {\n aborting = true;\n void Promise.resolve(onAbort()).finally(() => {\n finish(() => reject(signal.reason instanceof Error ? signal.reason : new Error('Aborted')));\n });\n };\n signal.addEventListener('abort', abort, { once: true });\n operation().then(\n (value) => {\n if (!aborting) finish(() => resolve(value));\n },\n (err) => {\n if (!aborting) finish(() => reject(err));\n },\n );\n });\n}\n", "import * as http from 'node:http';\nimport * as net from 'node:net';\nimport type { Duplex } from 'node:stream';\nimport type { BrowserDnsLookup } from './security.js';\nimport { resolvePinnedBrowserTarget } from './security.js';\n\nexport interface BrowserNetworkGuardProxyOptions {\n allowPrivateHosts?: boolean | undefined;\n allowedPrivateOrigins?: readonly string[] | undefined;\n lookup?: BrowserDnsLookup | undefined;\n connectTimeoutMs?: number | undefined;\n}\n\n/** Local HTTP proxy that pins every browser socket to its validated DNS answer. */\nexport class BrowserNetworkGuardProxy {\n private readonly server: http.Server;\n private readonly sockets = new Set<net.Socket>();\n private startPromise?: Promise<string> | undefined;\n private url?: string | undefined;\n\n constructor(private readonly options: BrowserNetworkGuardProxyOptions = {}) {\n this.server = http.createServer((request, response) => {\n void this.forwardHttp(request, response);\n });\n this.server.on('connect', (request, socket, head) => {\n void this.forwardConnect(request, socket, head);\n });\n this.server.on('upgrade', (request, socket, head) => {\n void this.forwardUpgrade(request, socket, head);\n });\n this.server.on('connection', (socket) => {\n this.sockets.add(socket);\n socket.once('close', () => this.sockets.delete(socket));\n // Browsers routinely abort speculative/idle connections. On Windows\n // that can surface as an asynchronous ECONNABORTED from a pipe write.\n // A Server's `clientError` event only covers HTTP parser failures; once\n // a socket becomes a CONNECT/WebSocket tunnel, an unhandled socket\n // `error` would otherwise terminate the entire host process.\n socket.on('error', () => {\n socket.destroy();\n });\n });\n this.server.on('clientError', (_error, socket) => {\n socket.end('HTTP/1.1 400 Bad Request\\r\\nConnection: close\\r\\n\\r\\n');\n });\n }\n\n async start(): Promise<string> {\n if (this.url) return this.url;\n if (this.startPromise) return this.startPromise;\n this.startPromise = new Promise<string>((resolve, reject) => {\n const onError = (error: Error) => {\n this.server.off('listening', onListening);\n reject(error);\n };\n const onListening = () => {\n this.server.off('error', onError);\n const address = this.server.address();\n if (!address || typeof address === 'string') {\n reject(new Error('browser: network guard proxy failed to bind'));\n return;\n }\n this.url = `http://127.0.0.1:${address.port}`;\n resolve(this.url);\n };\n this.server.once('error', onError);\n this.server.once('listening', onListening);\n this.server.listen(0, '127.0.0.1');\n }).finally(() => {\n this.startPromise = undefined;\n });\n return this.startPromise;\n }\n\n async close(): Promise<void> {\n this.url = undefined;\n for (const socket of this.sockets) socket.destroy();\n this.sockets.clear();\n if (!this.server.listening) return;\n await new Promise<void>((resolve) => this.server.close(() => resolve()));\n }\n\n private async forwardHttp(\n request: http.IncomingMessage,\n response: http.ServerResponse,\n ): Promise<void> {\n try {\n const target = await this.resolve(request.url ?? '');\n if (target.url.protocol !== 'http:') throw new Error('browser: HTTPS must use CONNECT');\n const headers = sanitizeHeaders(request.headers);\n headers.host = target.url.host;\n const upstream = http.request({\n host: target.address,\n family: target.family,\n port: Number(target.url.port || 80),\n method: request.method,\n path: `${target.url.pathname}${target.url.search}`,\n headers,\n agent: false,\n });\n upstream.setTimeout(this.options.connectTimeoutMs ?? 30_000, () => {\n upstream.destroy(new Error('browser: upstream connection timed out'));\n });\n upstream.on('response', (upstreamResponse) => {\n response.writeHead(\n upstreamResponse.statusCode ?? 502,\n sanitizeHeaders(upstreamResponse.headers),\n );\n upstreamResponse.pipe(response);\n });\n upstream.on('error', () => writeProxyError(response, 502, 'Bad Gateway'));\n request.on('aborted', () => upstream.destroy());\n request.pipe(upstream);\n } catch {\n writeProxyError(response, 403, 'Blocked by browser network policy');\n }\n }\n\n private async forwardConnect(\n request: http.IncomingMessage,\n client: Duplex,\n head: Buffer,\n ): Promise<void> {\n try {\n const authority = request.url ?? '';\n const target = await this.resolve(`https://${authority}`);\n const upstream = net.connect({\n host: target.address,\n family: target.family,\n port: Number(target.url.port || 443),\n });\n upstream.setTimeout(this.options.connectTimeoutMs ?? 30_000, () => upstream.destroy());\n const onConnectError = () => {\n client.end('HTTP/1.1 502 Bad Gateway\\r\\nConnection: close\\r\\n\\r\\n');\n };\n upstream.once('error', onConnectError);\n upstream.once('connect', () => {\n upstream.off('error', onConnectError);\n client.write('HTTP/1.1 200 Connection Established\\r\\n\\r\\n');\n if (head.length > 0) upstream.write(head);\n pipeDuplexPair(upstream, client);\n });\n client.once('close', () => upstream.destroy());\n } catch {\n client.end('HTTP/1.1 403 Forbidden\\r\\nConnection: close\\r\\n\\r\\n');\n }\n }\n\n private async forwardUpgrade(\n request: http.IncomingMessage,\n client: Duplex,\n head: Buffer,\n ): Promise<void> {\n let upstream: http.ClientRequest | undefined;\n try {\n const rawUrl = request.url ?? '';\n const websocketUrl = new URL(rawUrl);\n if (websocketUrl.protocol !== 'ws:') {\n throw new Error('browser: only plain ws upgrades are handled by the HTTP proxy');\n }\n websocketUrl.protocol = 'http:';\n const target = await this.resolve(websocketUrl.toString());\n const headers = sanitizeHeaders(request.headers, true);\n headers.host = target.url.host;\n upstream = http.request({\n host: target.address,\n family: target.family,\n port: Number(target.url.port || 80),\n method: request.method,\n path: `${target.url.pathname}${target.url.search}`,\n headers,\n agent: false,\n });\n upstream.once('upgrade', (response, upstreamSocket, upstreamHead) => {\n writeRawResponseHead(client, response);\n if (head.length > 0) upstreamSocket.write(head);\n if (upstreamHead.length > 0) client.write(upstreamHead);\n pipeDuplexPair(upstreamSocket, client);\n client.once('close', () => upstreamSocket.destroy());\n });\n upstream.once('response', (response) => {\n writeRawResponseHead(client, response);\n response.once('error', () => client.destroy());\n response.pipe(client);\n });\n upstream.once('error', () => {\n client.end('HTTP/1.1 502 Bad Gateway\\r\\nConnection: close\\r\\n\\r\\n');\n });\n client.once('close', () => upstream?.destroy());\n upstream.end();\n } catch {\n upstream?.destroy();\n client.end('HTTP/1.1 403 Forbidden\\r\\nConnection: close\\r\\n\\r\\n');\n }\n }\n\n private resolve(rawUrl: string) {\n return resolvePinnedBrowserTarget(rawUrl, {\n allowPrivateHosts: this.options.allowPrivateHosts,\n allowedPrivateOrigins: this.options.allowedPrivateOrigins,\n lookup: this.options.lookup,\n });\n }\n}\n\n/**\n * Couple both directions of a raw tunnel. `pipe()` deliberately does not\n * forward stream errors, so each destination needs its own listener before\n * either side can write. Destroying the peer also stops the opposite pipe and\n * prevents a disconnected browser socket from accumulating more writes.\n */\nfunction pipeDuplexPair(left: Duplex, right: Duplex): void {\n left.on('error', () => right.destroy());\n right.on('error', () => left.destroy());\n left.pipe(right);\n right.pipe(left);\n}\n\nfunction sanitizeHeaders(\n headers: http.IncomingHttpHeaders,\n preserveUpgrade = false,\n): http.OutgoingHttpHeaders {\n const sanitized: http.OutgoingHttpHeaders = { ...headers };\n delete sanitized['proxy-authorization'];\n delete sanitized['proxy-connection'];\n if (!preserveUpgrade) delete sanitized.connection;\n return sanitized;\n}\n\nfunction writeRawResponseHead(client: Duplex, response: http.IncomingMessage): void {\n const status = response.statusCode ?? 502;\n const statusText = response.statusMessage ?? 'Bad Gateway';\n const lines = [`HTTP/1.1 ${status} ${statusText}`];\n for (let index = 0; index < response.rawHeaders.length; index += 2) {\n lines.push(`${response.rawHeaders[index]}: ${response.rawHeaders[index + 1]}`);\n }\n client.write(`${lines.join('\\r\\n')}\\r\\n\\r\\n`);\n}\n\nfunction writeProxyError(response: http.ServerResponse, status: number, message: string): void {\n if (response.headersSent || response.destroyed) return;\n response.writeHead(status, { 'content-type': 'text/plain', connection: 'close' });\n response.end(message);\n}\n", "import * as dns from 'node:dns/promises';\nimport * as net from 'node:net';\nimport { assertNotPrivateHost, isPrivateIPv4, isPrivateIPv6 } from '@wrongstack/core/utils';\n\nconst SAFE_SUBRESOURCE_PROTOCOLS = new Set(['about:', 'blob:', 'data:']);\n\nexport async function assertBrowserUrlAllowed(\n rawUrl: string,\n opts: {\n allowPrivateHosts?: boolean | undefined;\n allowedPrivateOrigins?: readonly string[] | undefined;\n navigation?: boolean | undefined;\n },\n): Promise<URL> {\n const url = parseBrowserUrl(rawUrl, opts.navigation ?? true);\n if (!opts.navigation && SAFE_SUBRESOURCE_PROTOCOLS.has(url.protocol)) return url;\n if (!opts.allowPrivateHosts && !isAllowedPrivateOrigin(url, opts.allowedPrivateOrigins)) {\n await assertNotPrivateHost(url.hostname);\n }\n return url;\n}\n\nexport interface BrowserResolvedTarget {\n url: URL;\n address: string;\n family: 4 | 6;\n}\n\nexport type BrowserDnsLookup = (\n hostname: string,\n) => Promise<readonly { address: string; family: number }[]>;\n\n/**\n * Resolve once, validate every answer, and return the exact address a socket\n * must use. Callers must connect to `address`, never resolve `url.hostname`\n * again, otherwise DNS rebinding remains possible.\n */\nexport async function resolvePinnedBrowserTarget(\n rawUrl: string,\n opts: {\n allowPrivateHosts?: boolean | undefined;\n allowedPrivateOrigins?: readonly string[] | undefined;\n lookup?: BrowserDnsLookup | undefined;\n } = {},\n): Promise<BrowserResolvedTarget> {\n const url = parseBrowserUrl(rawUrl, true);\n const allowPrivate =\n opts.allowPrivateHosts === true || isAllowedPrivateOrigin(url, opts.allowedPrivateOrigins);\n const hostname = unbracket(url.hostname);\n const literalFamily = net.isIP(hostname);\n if (literalFamily === 4 || literalFamily === 6) {\n if (!allowPrivate && isPrivateAddress(hostname, literalFamily)) {\n throw new Error(`browser: blocked private/loopback address \"${hostname}\"`);\n }\n return { url, address: hostname, family: literalFamily };\n }\n if ((hostname === 'localhost' || hostname.endsWith('.localhost')) && !allowPrivate) {\n throw new Error('browser: blocked localhost target');\n }\n\n const lookup = opts.lookup ?? ((host) => dns.lookup(host, { all: true }));\n let records: readonly { address: string; family: number }[];\n try {\n records = await lookup(hostname);\n } catch (error) {\n throw new Error(\n `browser: DNS resolution failed for \"${hostname}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n if (records.length === 0) throw new Error(`browser: DNS returned no addresses for \"${hostname}\"`);\n\n for (const record of records) {\n if (record.family !== 4 && record.family !== 6) {\n throw new Error(`browser: DNS returned an unsupported address family for \"${hostname}\"`);\n }\n if (!allowPrivate && isPrivateAddress(record.address, record.family)) {\n throw new Error(`browser: resolved to private address ${record.address}`);\n }\n }\n const selected = records[0]!;\n return { url, address: selected.address, family: selected.family as 4 | 6 };\n}\n\nexport function parsePrivateOriginAllowlist(raw: string | undefined): string[] {\n if (!raw?.trim()) return [];\n const origins = new Set<string>();\n for (const entry of raw.split(',')) {\n const candidate = entry.trim();\n if (!candidate) continue;\n const url = parseBrowserUrl(candidate, true);\n if (url.pathname !== '/' || url.search || url.hash) {\n throw new Error(`browser: private origin allowlist entry must be an origin: \"${candidate}\"`);\n }\n origins.add(url.origin);\n }\n return [...origins];\n}\n\nfunction parseBrowserUrl(rawUrl: string, navigation: boolean): URL {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new Error('browser: url must be an absolute URL');\n }\n if (!navigation && SAFE_SUBRESOURCE_PROTOCOLS.has(url.protocol)) return url;\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error(`browser: unsupported protocol \"${url.protocol}\"`);\n }\n if (url.username || url.password) {\n throw new Error('browser: credentials in URLs are not allowed');\n }\n return url;\n}\n\nfunction isAllowedPrivateOrigin(url: URL, origins: readonly string[] | undefined): boolean {\n return origins?.includes(url.origin) ?? false;\n}\n\nfunction isPrivateAddress(address: string, family: 4 | 6): boolean {\n return family === 4 ? isPrivateIPv4(address) : isPrivateIPv6(address);\n}\n\nfunction unbracket(hostname: string): string {\n return hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n}\n\n/** Remove credentials, query strings, and fragments before persistence/output. */\nexport function safeBrowserUrl(rawUrl: string): string {\n try {\n const url = new URL(rawUrl);\n url.username = '';\n url.password = '';\n url.search = '';\n url.hash = '';\n return url.toString();\n } catch {\n return 'about:blank';\n }\n}\n\nexport function redactBrowserText(text: string): string {\n return text\n .replace(/\\bBearer\\s+[A-Za-z0-9._~+/-]+=*/gi, 'Bearer [REDACTED]')\n .replace(\n /\\b(api[-_ ]?key|access[-_ ]?token|auth[-_ ]?token|token|password|secret)\\b\\s*[:=]\\s*[^\\s,;]+/gi,\n '$1=[REDACTED]',\n );\n}\n", "import * as path from 'node:path';\nimport type { Context } from '@wrongstack/core/agent';\nimport { ToolCapabilities } from '@wrongstack/core/security';\nimport type { Tool } from '@wrongstack/core/types';\nimport { resolveWstackPaths } from '@wrongstack/core/utils';\nimport { BrowserSessionManager, browserInstallationDiagnostics } from './manager.js';\nimport { parsePrivateOriginAllowlist } from './security.js';\n\nconst managers = new Map<string, BrowserSessionManager>();\nconst cleanupSignalByContext = new WeakMap<object, AbortSignal>();\n\nfunction managerFor(ctx: Context): BrowserSessionManager {\n const root = path.resolve(ctx.projectRoot);\n let manager = managers.get(root);\n if (!manager) {\n const wpaths = resolveWstackPaths({ projectRoot: root });\n manager = new BrowserSessionManager({\n artifactRoot: path.join(wpaths.projectDir, 'browser-artifacts'),\n allowedPrivateOrigins: parsePrivateOriginAllowlist(\n process.env['WRONGSTACK_BROWSER_PRIVATE_ORIGINS'],\n ),\n });\n managers.set(root, manager);\n }\n const runSignal = ctx.signal;\n if (cleanupSignalByContext.get(ctx) !== runSignal) {\n cleanupSignalByContext.set(ctx, runSignal);\n const managerForRun = manager;\n const rootForRun = root;\n const ownerForRun = owner(ctx);\n ctx.registerAbortHook?.(async () => {\n if (cleanupSignalByContext.get(ctx) === runSignal) {\n cleanupSignalByContext.delete(ctx);\n }\n await managerForRun.closeOwner(ownerForRun);\n // Managers are keyed by project root and own a listening network proxy.\n // Drop the entry as soon as the final owner is gone so project switching\n // cannot accumulate one proxy/server handle per visited repository.\n if (managerForRun.isIdle() && managers.get(rootForRun) === managerForRun) {\n managers.delete(rootForRun);\n await managerForRun.dispose();\n }\n });\n }\n return manager;\n}\n\nfunction owner(ctx: Context): string {\n return ctx.agentId || 'leader';\n}\n\nfunction json(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nconst sessionIdSchema = {\n type: 'string',\n minLength: 1,\n description: 'Browser session id returned by browser_open.',\n} as const;\n\nexport const browserOpenTool: Tool<{\n url?: string | undefined;\n width?: number | undefined;\n height?: number | undefined;\n trace?: boolean | undefined;\n}> = {\n name: 'browser_open',\n description:\n 'Open an isolated first-party Playwright browser session, optionally navigating to a URL.',\n usageHint: 'browser_open({ url?, width?, height?, trace? })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n subjectKey: 'url',\n inputSchema: {\n type: 'object',\n properties: {\n url: { type: 'string', description: 'Optional absolute http(s) URL.' },\n width: { type: 'integer', minimum: 320, maximum: 3840 },\n height: { type: 'integer', minimum: 240, maximum: 2160 },\n trace: { type: 'boolean', description: 'Capture a Playwright trace; defaults to true.' },\n },\n },\n async execute(input, ctx, opts) {\n const viewport =\n input.width || input.height\n ? { width: input.width ?? 1440, height: input.height ?? 900 }\n : undefined;\n return json(\n await managerFor(ctx).open(\n owner(ctx),\n { url: input.url, viewport, trace: input.trace },\n opts.signal,\n ),\n );\n },\n};\n\nexport const browserListTool: Tool<Record<string, never>> = {\n name: 'browser_list',\n description:\n 'List browser sessions owned by the current agent without exposing other agents sessions.',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: { type: 'object', properties: {} },\n async execute(_input, ctx) {\n return json(await managerFor(ctx).list(owner(ctx)));\n },\n};\n\nexport const browserStatusTool: Tool<Record<string, never>> = {\n name: 'browser_status',\n description: 'Check whether first-party Playwright Chromium is installed and ready to launch.',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.TOOL_META],\n inputSchema: { type: 'object', properties: {} },\n async execute() {\n return json(await browserInstallationDiagnostics());\n },\n};\n\nexport const browserNavigateTool: Tool<{ sessionId: string; url: string }> = {\n name: 'browser_navigate',\n description: 'Navigate an owned browser session to an approved http(s) URL.',\n usageHint: 'browser_navigate({ sessionId, url })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n subjectKey: 'url',\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema, url: { type: 'string', minLength: 1 } },\n required: ['sessionId', 'url'],\n },\n async execute(input, ctx, opts) {\n return json(\n await managerFor(ctx).navigate(input.sessionId, owner(ctx), input.url, opts.signal),\n );\n },\n};\n\nexport const browserSnapshotTool: Tool<{ sessionId: string }> = {\n name: 'browser_snapshot',\n description: 'Return bounded accessibility state plus redacted console and network summaries.',\n usageHint: 'browser_snapshot({ sessionId })',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema },\n required: ['sessionId'],\n },\n async execute(input, ctx, opts) {\n return json(await managerFor(ctx).snapshot(input.sessionId, owner(ctx), opts.signal));\n },\n};\n\nexport const browserScreenshotTool: Tool<{\n sessionId: string;\n fullPage?: boolean | undefined;\n selector?: string | undefined;\n}> = {\n name: 'browser_screenshot',\n description:\n 'Capture a page or element PNG and return sensitive artifact metadata with integrity hash.',\n usageHint: 'browser_screenshot({ sessionId, fullPage?, selector? })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n fullPage: { type: 'boolean' },\n selector: { type: 'string', minLength: 1 },\n },\n required: ['sessionId'],\n },\n async execute(input, ctx, opts) {\n return json(\n await managerFor(ctx).screenshot(\n input.sessionId,\n owner(ctx),\n { fullPage: input.fullPage, selector: input.selector },\n opts.signal,\n ),\n );\n },\n};\n\ntype SelectorInput = { sessionId: string; selector: string };\n\nfunction selectorTool(\n name: string,\n description: string,\n run: (\n manager: BrowserSessionManager,\n input: SelectorInput,\n ownerId: string,\n signal: AbortSignal,\n ) => Promise<void>,\n): Tool<SelectorInput> {\n return {\n name,\n description,\n usageHint: `${name}({ sessionId, selector })`,\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema, selector: { type: 'string', minLength: 1 } },\n required: ['sessionId', 'selector'],\n },\n async execute(input, ctx, opts) {\n await run(managerFor(ctx), input, owner(ctx), opts.signal);\n return 'ok';\n },\n };\n}\n\nexport const browserClickTool = selectorTool(\n 'browser_click',\n 'Click an element in an owned browser session.',\n (manager, input, ownerId, signal) =>\n manager.click(input.sessionId, ownerId, input.selector, signal),\n);\n\nexport const browserHoverTool = selectorTool(\n 'browser_hover',\n 'Hover an element in an owned browser session.',\n (manager, input, ownerId, signal) =>\n manager.hover(input.sessionId, ownerId, input.selector, signal),\n);\n\nexport const browserTypeTool: Tool<\n SelectorInput & { text?: string | undefined; secretEnv?: string | undefined }\n> = {\n name: 'browser_type',\n description:\n 'Fill an input in an owned browser session. Use secretEnv instead of text for credentials so values stay out of tool arguments and session audit.',\n usageHint: 'browser_type({ sessionId, selector, text? | secretEnv? })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n text: { type: 'string' },\n secretEnv: {\n type: 'string',\n pattern: '^[A-Z_][A-Z0-9_]*$',\n description: 'Host environment variable resolved only at execution time.',\n },\n },\n required: ['sessionId', 'selector'],\n },\n validate(input) {\n return (input.text === undefined) === (input.secretEnv === undefined)\n ? ['exactly one of text or secretEnv is required']\n : [];\n },\n async execute(input, ctx, opts) {\n const value = input.text ?? (input.secretEnv ? process.env[input.secretEnv] : undefined);\n if (value === undefined) {\n throw new Error(`browser: secret environment variable \"${input.secretEnv ?? ''}\" is not set`);\n }\n await managerFor(ctx).type(input.sessionId, owner(ctx), input.selector, value, opts.signal);\n return 'ok';\n },\n};\n\nexport const browserSelectTool: Tool<SelectorInput & { value: string }> = {\n name: 'browser_select',\n description: 'Select an option in an owned browser session.',\n usageHint: 'browser_select({ sessionId, selector, value })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n value: { type: 'string' },\n },\n required: ['sessionId', 'selector', 'value'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).select(\n input.sessionId,\n owner(ctx),\n input.selector,\n input.value,\n opts.signal,\n );\n return 'ok';\n },\n};\n\nexport const browserPressTool: Tool<{ sessionId: string; key: string }> = {\n name: 'browser_press',\n description: 'Press a keyboard key in an owned browser session.',\n usageHint: 'browser_press({ sessionId, key })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema, key: { type: 'string', minLength: 1 } },\n required: ['sessionId', 'key'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).press(input.sessionId, owner(ctx), input.key, opts.signal);\n return 'ok';\n },\n};\n\nexport const browserDragTool: Tool<{ sessionId: string; from: string; to: string }> = {\n name: 'browser_drag',\n description: 'Drag one element to another in an owned browser session.',\n usageHint: 'browser_drag({ sessionId, from, to })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'standard',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n from: { type: 'string', minLength: 1 },\n to: { type: 'string', minLength: 1 },\n },\n required: ['sessionId', 'from', 'to'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).drag(input.sessionId, owner(ctx), input.from, input.to, opts.signal);\n return 'ok';\n },\n};\n\nexport const browserWaitTool: Tool<{\n sessionId: string;\n selector?: string | undefined;\n timeoutMs?: number | undefined;\n}> = {\n name: 'browser_wait',\n description: 'Wait for an element or a bounded duration in an owned browser session.',\n usageHint: 'browser_wait({ sessionId, selector?, timeoutMs? })',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n timeoutMs: { type: 'integer', minimum: 0, maximum: 30000 },\n },\n required: ['sessionId'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).wait(\n input.sessionId,\n owner(ctx),\n { selector: input.selector, timeoutMs: input.timeoutMs },\n opts.signal,\n );\n return 'ok';\n },\n};\n\nexport const browserEvaluateTool: Tool<{ sessionId: string; expression: string }> = {\n name: 'browser_evaluate',\n description:\n 'Evaluate bounded JavaScript in the page. Requires confirmation because page code is arbitrary.',\n usageHint: 'browser_evaluate({ sessionId, expression })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'destructive',\n capabilities: [ToolCapabilities.NET_OUTBOUND, ToolCapabilities.TOOL_MUTATE_ANY],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n expression: { type: 'string', minLength: 1, maxLength: 16384 },\n },\n required: ['sessionId', 'expression'],\n },\n async execute(input, ctx, opts) {\n return json(\n await managerFor(ctx).evaluate(input.sessionId, owner(ctx), input.expression, opts.signal),\n );\n },\n};\n\nexport const browserUploadTool: Tool<SelectorInput & { files: string[] }> = {\n name: 'browser_upload',\n description: 'Upload project-local files through a file input in an owned browser session.',\n usageHint: 'browser_upload({ sessionId, selector, files })',\n permission: 'confirm',\n mutating: true,\n riskTier: 'destructive',\n capabilities: [ToolCapabilities.NET_OUTBOUND, ToolCapabilities.FS_READ],\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: sessionIdSchema,\n selector: { type: 'string', minLength: 1 },\n files: { type: 'array', minItems: 1, maxItems: 20, items: { type: 'string', minLength: 1 } },\n },\n required: ['sessionId', 'selector', 'files'],\n },\n async execute(input, ctx, opts) {\n await managerFor(ctx).upload(\n input.sessionId,\n owner(ctx),\n input.selector,\n input.files,\n ctx.projectRoot,\n opts.signal,\n );\n return 'ok';\n },\n};\n\nexport const browserCloseTool: Tool<{ sessionId: string }> = {\n name: 'browser_close',\n description:\n 'Close an owned browser session, reclaim its context, and return sensitive trace metadata.',\n usageHint: 'browser_close({ sessionId })',\n permission: 'auto',\n mutating: false,\n riskTier: 'safe',\n capabilities: [ToolCapabilities.NET_OUTBOUND],\n inputSchema: {\n type: 'object',\n properties: { sessionId: sessionIdSchema },\n required: ['sessionId'],\n },\n async execute(input, ctx) {\n return json(await managerFor(ctx).close(input.sessionId, owner(ctx)));\n },\n};\n\nexport const browserTools: Tool[] = [\n browserOpenTool,\n browserStatusTool,\n browserListTool,\n browserNavigateTool,\n browserSnapshotTool,\n browserScreenshotTool,\n browserClickTool,\n browserTypeTool,\n browserSelectTool,\n browserPressTool,\n browserHoverTool,\n browserDragTool,\n browserWaitTool,\n browserEvaluateTool,\n browserUploadTool,\n browserCloseTool,\n];\n\nfor (const tool of browserTools) tool.icon = 'web';\nfor (const tool of browserTools) tool.timeoutMs ??= 60_000;\n\nexport async function shutdownBrowserTools(): Promise<void> {\n const active = [...managers.values()];\n managers.clear();\n await Promise.all(active.map((manager) => manager.dispose()));\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["stat", "resolve", "fs", "path", "ulid", "net", "lookup", "request", "resolve", "ulid", "relative", "stat", "request", "resolve", "path"]
7
7
  }