feat(browser): reuse admitted browser-socket transport and allow discovery_timeout_ms (#9203)

* feat(browser): reuse admitted browser-socket transport and allow discovery_timeout_ms

* fix(browser): close unhealthy shared sockets and clamp max discovery timer

* fix(browser): retry failed shared-socket cleanup while peer leases remain active

* test(browser): race observation readiness with awaitAcknowledgement and join before mock restore

* fix(browser): isolate shared-socket discovery aborts and coalesce cold connects

* fix(browser): observe pending cold-connect cleanup failures and isolate fake CDP sessions

* refactor(browser): carry typed connect cleanup owners and gate concurrent session test

* test(browser): cover loopback socket reuse-key normalization

* test(browser): verify distinct browser socket path IDs stay separate
This commit is contained in:
Ryan S authored and GitHub committed 2026-11-08 23:06:56 +00:00
1 parent 94182f331e
commit 9d0e87f331
26 files changed
+2868 -411

No files matched your search

+6 -3
View File
@@ -4,8 +4,9 @@ import { Cli, z } from "incur";
import { browserCliError } from "./browserCliError.js";
import { createBrowserObservationProvider } from "../composition/browserObservation.js";
import {
browserScopeOptions,
passiveBrowserScopeOptions,
selectedCommandTimeout,
selectedDiscoveryTimeout,
} from "../cliObservationOptions.js";
import {
captureWebScreenshot,
@@ -66,7 +67,7 @@ const registerWebMcp = (
),
}),
options: z.object({
...browserScopeOptions,
...passiveBrowserScopeOptions,
observationMs: cliDecimalField(
discoverWebMcpToolsInputSchema.shape.observation_ms,
).describe("Observation duration in milliseconds"),
@@ -80,6 +81,7 @@ const registerWebMcp = (
allowed_origins: options.allowedOrigins,
target_id: args.targetId,
observation_ms: options.observationMs,
...selectedDiscoveryTimeout(options.discoveryTimeoutMs),
...selectedCommandTimeout(options.commandTimeoutMs),
};
const parsed = discoverWebMcpToolsInputSchema.safeParse(input);
@@ -183,7 +185,7 @@ const registerScreenshot = (
),
}),
options: z.object({
...browserScopeOptions,
...passiveBrowserScopeOptions,
}),
run: ({ args, options }) =>
withCommandCancellation((signal) =>
@@ -193,6 +195,7 @@ const registerScreenshot = (
cdp_endpoint: args.endpoint,
allowed_origins: options.allowedOrigins,
target_id: args.targetId,
...selectedDiscoveryTimeout(options.discoveryTimeoutMs),
...selectedCommandTimeout(options.commandTimeoutMs),
};
const parsed = captureWebScreenshotInputSchema.safeParse(input);
+10 -4
View File
@@ -30,9 +30,10 @@ import { cliDecimalField } from "./options.js";
import { CLI_COMMANDS } from "../cliCommandNames.js";
import {
browserPageInspectionOptions,
browserScopeOptions,
observationDuration,
passiveBrowserScopeOptions,
selectedCommandTimeout,
selectedDiscoveryTimeout,
} from "../cliObservationOptions.js";
import { withCommandCancellation } from "./commandCancellation.js";
import { finishAnalysisCommand } from "./finishAnalysisCommand.js";
@@ -61,7 +62,8 @@ const registerTargetList = (
),
}),
options: z.object({
allowedOrigins: browserScopeOptions.allowedOrigins,
allowedOrigins: passiveBrowserScopeOptions.allowedOrigins,
discoveryTimeoutMs: passiveBrowserScopeOptions.discoveryTimeoutMs,
}),
run: ({ args, options }) =>
withCommandCancellation((signal) =>
@@ -70,6 +72,7 @@ const registerTargetList = (
const input = {
cdp_endpoint: args.endpoint,
allowed_origins: options.allowedOrigins,
...selectedDiscoveryTimeout(options.discoveryTimeoutMs),
};
const parsed = listBrowserTargetsInputSchema.safeParse(input);
if (!parsed.success)
@@ -128,6 +131,7 @@ const registerPageInspection = (
include_script_sources: options.includeScriptSources,
include_storage_keys: options.includeStorageKeys,
include_storage_fingerprints: options.includeStorageFingerprints,
...selectedDiscoveryTimeout(options.discoveryTimeoutMs),
...selectedCommandTimeout(options.commandTimeoutMs),
};
const parsed = inspectWebPageInputSchema.safeParse(input);
@@ -171,7 +175,7 @@ const registerBundleAnalysis = (
),
}),
options: z.object({
...browserScopeOptions,
...passiveBrowserScopeOptions,
...webBundleDeliveryOptions,
observationMs: observationDuration(500),
fetchSourceMaps: z
@@ -220,6 +224,7 @@ const registerBundleAnalysis = (
: {
source_map_fetch_timeout_ms: options.sourceMapFetchTimeoutMs,
}),
...selectedDiscoveryTimeout(options.discoveryTimeoutMs),
...selectedCommandTimeout(options.commandTimeoutMs),
};
const parsed = analyzeWebBundleInputSchema.safeParse(input);
@@ -263,7 +268,7 @@ const registerObservationSession = (
),
}),
options: z.object({
...browserScopeOptions,
...passiveBrowserScopeOptions,
observationMs: observationDuration(10_000, 1),
}),
run: ({ args, options }) =>
@@ -275,6 +280,7 @@ const registerObservationSession = (
allowed_origins: options.allowedOrigins,
target_id: args.targetId,
observation_ms: options.observationMs,
...selectedDiscoveryTimeout(options.discoveryTimeoutMs),
...selectedCommandTimeout(options.commandTimeoutMs),
};
const parsed = observeWebSessionInputSchema.safeParse(input);