Files
rea/src/cli/webRuntimeCommands.ts
T
morluto 93c620c3e7 fix(browser): own transport cleanup through finalization
Own CDP transports from admission through observed close, retain failed
owners for retry, and keep active peers separate from pending cleanup.
Preserve primary errors and completed facts through final cancellation.
Forward passive Electron CLI cancellation and dispose browser, runtime and
scenario owners from CLI and MCP shutdown.

Refs #4255, #4256, #4257
2026-10-16 06:46:26 +08:00

110 lines
3.8 KiB
TypeScript

import { Cli, z } from "incur";
import { createWebRuntimeService } from "../composition/webRuntime.js";
import { browserCliError } from "../cliBrowserContext.js";
import {
browserScopeOptions,
observationDuration,
} from "../cliObservationOptions.js";
import { logCliCommand } from "../cliLogging.js";
import { CLI_COMMANDS } from "../cliCommandNames.js";
import type { Logger } from "pino";
import type { ProgressReporter } from "../application/ProgressReporter.js";
import { withCommandCancellation } from "./commandCancellation.js";
import { finishAnalysisCommand } from "./finishAnalysisCommand.js";
/** CLI progress exposes the actual armed point on stderr without corrupting JSON results. */
const runtimeProgress: ProgressReporter = {
report: async (update) => {
process.stderr.write(`${JSON.stringify({ rea_progress: update })}\n`);
},
};
/** Register public equivalents of the two modular website runtime tools. */
export const registerWebRuntimeCommands = (
cli: ReturnType<typeof Cli.create>,
logger: Logger,
): void => {
cli.command(CLI_COMMANDS.observeWebExecution, {
description:
"Observe precise page execution; resets counters and temporarily disables optimization",
args: z.object({
endpoint: z.string().describe("Existing loopback browser CDP endpoint"),
targetId: z
.string()
.describe("Selected page target ID from list-browser-targets"),
}),
options: z.object({
...browserScopeOptions,
observationMs: observationDuration(10_000, 1),
}),
run: ({ args, options }) =>
withCommandCancellation((signal) =>
logCliCommand(logger, "observe-web-execution", async () => {
const service = createWebRuntimeService();
return await finishAnalysisCommand(
() =>
service.observe(
{
cdp_endpoint: args.endpoint,
target_id: args.targetId,
allowed_origins: options.allowedOrigins,
observation_ms: options.observationMs,
},
{ progress: runtimeProgress, signal },
),
{
close: async () => {
await service.provider.close?.();
},
},
service.provider.identity().id,
"observe_web_execution",
undefined,
signal,
);
}),
),
});
cli.command(CLI_COMMANDS.inspectWebEventListeners, {
description:
"Inspect native listener source locations on the first main-document CSS match",
args: z.object({
endpoint: z.string().describe("Existing loopback browser CDP endpoint"),
targetId: z
.string()
.describe("Selected page target ID from list-browser-targets"),
selector: z
.string()
.describe("Native CSS selector; inspect the first main-document match"),
}),
options: z.object({ ...browserScopeOptions }),
run: ({ args, options }) =>
withCommandCancellation((signal) =>
logCliCommand(logger, "inspect-web-event-listeners", async () => {
const service = createWebRuntimeService();
return await finishAnalysisCommand(
() =>
service.inspect(
{
cdp_endpoint: args.endpoint,
target_id: args.targetId,
selector: args.selector,
allowed_origins: options.allowedOrigins,
},
{ signal },
),
{
close: async () => {
await service.provider.close?.();
},
},
service.provider.identity().id,
"inspect_web_event_listeners",
undefined,
signal,
);
}),
),
});
};