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
110 lines
3.8 KiB
TypeScript
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,
|
|
);
|
|
}),
|
|
),
|
|
});
|
|
};
|