mirror of
https://github.com/morluto/rea.git
synced 2026-11-07 07:16:13 +00:00
109 lines
4.9 KiB
TypeScript
109 lines
4.9 KiB
TypeScript
import type {
|
|
BrowserObservationFailureReason,
|
|
BrowserObservationOperation,
|
|
} from "./browserObservationErrors.js";
|
|
import {
|
|
AnalysisError,
|
|
type AnalysisCleanupObservation,
|
|
type AnalysisErrorOptions,
|
|
} from "./analysisErrorBase.js";
|
|
import { AnalysisCancelledError } from "./analysisErrorCore.js";
|
|
|
|
/** Describe browser cleanup failure without discarding its resource evidence. */
|
|
export const browserCleanupObservation = (
|
|
cause: unknown,
|
|
): AnalysisCleanupObservation =>
|
|
cause instanceof AnalysisError && cause.cleanup !== undefined
|
|
? cause.cleanup
|
|
: {
|
|
reason: cause instanceof Error ? cause.message : String(cause),
|
|
resources:
|
|
cause instanceof AnalysisError && cause.cleanupResources.length > 0
|
|
? cause.cleanupResources
|
|
: ["browser_transport"],
|
|
};
|
|
|
|
/** A bounded passive browser observation failed at its CDP boundary. */
|
|
export class BrowserObservationError extends AnalysisError {
|
|
readonly _tag = "BrowserObservationError";
|
|
override cleanupIncomplete: boolean;
|
|
override readonly userCategory: "cancelled" | undefined;
|
|
override readonly userMessage: string | undefined;
|
|
/** Producer-supplied explanation; undefined selects the operation default. */
|
|
readonly detail: string | undefined;
|
|
readonly remediationAction: string | undefined;
|
|
|
|
constructor(
|
|
readonly operation: BrowserObservationOperation,
|
|
readonly reason: BrowserObservationFailureReason,
|
|
options?: AnalysisErrorOptions & {
|
|
readonly detail?: string;
|
|
readonly remediationAction?: string;
|
|
},
|
|
) {
|
|
super(`Browser observation ${operation} failed: ${reason}`, options);
|
|
this.detail = options?.detail;
|
|
this.userMessage =
|
|
options?.detail ?? observationFailureMessage(operation, reason);
|
|
this.remediationAction = options?.remediationAction;
|
|
this.cleanupIncomplete =
|
|
this.cleanup !== undefined || reason === "cleanup_failed";
|
|
this.setCleanupResources(
|
|
this.cleanup?.resources ??
|
|
(reason === "cleanup_failed" ? ["browser_transport"] : []),
|
|
);
|
|
this.userCategory =
|
|
reason === "cancelled" ||
|
|
options?.cause instanceof AnalysisCancelledError ||
|
|
(options?.cause instanceof AnalysisError &&
|
|
options.cause.userCategory === "cancelled")
|
|
? "cancelled"
|
|
: undefined;
|
|
}
|
|
|
|
/**
|
|
* Attribute this failure to the caller's operation without discarding
|
|
* producer facts; the original cause keeps the primary failure chain intact.
|
|
*/
|
|
forOperation(
|
|
operation: BrowserObservationOperation,
|
|
): BrowserObservationError {
|
|
if (operation === this.operation) return this;
|
|
return new BrowserObservationError(operation, this.reason, {
|
|
cause: this.cause,
|
|
...(this.detail === undefined ? {} : { detail: this.detail }),
|
|
...(this.remediationAction === undefined
|
|
? {}
|
|
: { remediationAction: this.remediationAction }),
|
|
cleanupPrimary: this.cleanupPrimary,
|
|
diagnostics: this.diagnostics,
|
|
capturedOutput: this.capturedOutput,
|
|
cleanup: this.cleanup,
|
|
partialObservation: this.partialObservation,
|
|
});
|
|
}
|
|
}
|
|
|
|
const observationFailureMessage = (
|
|
operation: BrowserObservationOperation,
|
|
reason: BrowserObservationFailureReason,
|
|
): string | undefined => {
|
|
if (reason === "cancelled")
|
|
return `${operation} was cancelled. Collected observations and cleanup status are reported when available.`;
|
|
if (reason === "timeout")
|
|
return `${operation} exceeded its execution deadline. Review the target's responsiveness and retained observations before retrying.`;
|
|
if (reason === "endpoint_unreachable")
|
|
return `${operation} could not reach the selected loopback debugging endpoint. Verify that the target process is running with debugging enabled and that the endpoint's port matches it, then retry.`;
|
|
if (reason === "target_not_found")
|
|
return `${operation} could not find the selected target at the debugging endpoint. Refresh target discovery for that endpoint and retry with a returned target ID.`;
|
|
if (reason === "target_session_detached")
|
|
return `${operation} lost its debugging session while the target may still exist. Refresh target discovery and attach to the selected target again.`;
|
|
if (reason === "target_changed")
|
|
return `${operation} could not retain a stable document because the target changed during observation. Retry after navigation settles; refresh target discovery if the selected page was replaced.`;
|
|
if (reason === "service_worker_blocked")
|
|
return `${operation} refused the selected page because it is controlled by or has a registered service worker while the service-worker policy is block. Set environment.service_workers to allow to permit observation, or remove the service worker registration through the browser.`;
|
|
if (reason === "disconnected")
|
|
return `${operation} lost its debugging connection. Verify that the target process is still running, refresh target discovery, and retry the observation.`;
|
|
return undefined;
|
|
};
|