//#region extensions/browser/src/browser/errors.ts
/**
* Browser domain errors.
*
* Provides HTTP-mappable error classes and stable blocked-policy messages used
* by route handlers, clients, and Gateway proxy code.
*/
/** Stable message for blocked CDP endpoint configuration. */
const BROWSER_ENDPOINT_BLOCKED_MESSAGE = "browser endpoint blocked by policy";
/** Stable message for blocked page navigation targets. */
const BROWSER_NAVIGATION_BLOCKED_MESSAGE = "browser navigation blocked by policy";
/** Stable machine-readable browser error reasons. */
const BROWSER_ERROR_REASONS = {
	noDisplayForHeadedProfile: "no_display_for_headed_profile",
	navigationBlocked: "navigation_blocked"
};
/** Stable machine-readable codes returned by browser action routes. */
const BROWSER_ACT_ERROR_CODES = {
	kindRequired: "ACT_KIND_REQUIRED",
	invalidRequest: "ACT_INVALID_REQUEST",
	selectorUnsupported: "ACT_SELECTOR_UNSUPPORTED",
	evaluateDisabled: "ACT_EVALUATE_DISABLED",
	unsupportedForExistingSession: "ACT_EXISTING_SESSION_UNSUPPORTED",
	targetIdMismatch: "ACT_TARGET_ID_MISMATCH"
};
const BROWSER_ACT_ERROR_CODE_VALUES = new Set(Object.values(BROWSER_ACT_ERROR_CODES));
function isBrowserActErrorCode(value) {
	return typeof value === "string" && BROWSER_ACT_ERROR_CODE_VALUES.has(value);
}
const NO_DISPLAY_HEADLESS_SOURCES = [
	"request",
	"env",
	"profile",
	"config",
	"default"
];
/** Base browser error carrying an HTTP status code. */
var BrowserError = class extends Error {
	constructor(message, status = 500, options) {
		super(message, options);
		this.name = new.target.name;
		this.status = status;
	}
};
/**
* Raised when a browser CDP endpoint (the cdpUrl itself) fails the
* configured SSRF policy. Distinct from a blocked navigation target so
* callers see "fix your browser endpoint config" rather than "fix your
* navigation URL".
*/
var BrowserCdpEndpointBlockedError = class extends BrowserError {
	constructor(options) {
		super(BROWSER_ENDPOINT_BLOCKED_MESSAGE, 400, options);
	}
};
/** Validation failure for browser route or config input. */
var BrowserValidationError = class extends BrowserError {
	constructor(message, options) {
		super(message, 400, options);
	}
};
/** Raised when one tab reference matches multiple tabs. */
var BrowserTargetAmbiguousError = class extends BrowserError {
	constructor(message = "ambiguous browser tab reference", options) {
		super(message, 409, options);
	}
};
/** Raised when a requested browser tab cannot be resolved. */
var BrowserTabNotFoundError = class extends BrowserError {
	constructor(inputOrMessage, options) {
		const input = typeof inputOrMessage === "object" ? inputOrMessage.input?.trim() : inputOrMessage?.trim();
		const message = input ? /^\d+$/.test(input) ? `tab not found: browser tab "${input}" not found. Numeric values are not tab targets; use a stable tab id like "t1", a label, or a raw targetId. For positional selection, use "openclaw browser tab select ${input}".` : `tab not found: browser tab "${input}" not found. Use action=tabs and pass suggestedTargetId, tabId, label, or raw targetId.` : "tab not found";
		super(message, 404, options);
	}
};
/** Raised when a requested browser profile does not exist. */
var BrowserProfileNotFoundError = class extends BrowserError {
	constructor(message, options) {
		super(message, 404, options);
	}
};
/** Raised when a browser config mutation conflicts with existing state. */
var BrowserConflictError = class extends BrowserError {
	constructor(message, options) {
		super(message, 409, options);
	}
};
/** Raised when a browser profile cannot be reset by the current driver. */
var BrowserResetUnsupportedError = class extends BrowserError {
	constructor(message, options) {
		super(message, 400, options);
	}
};
/** Raised when a profile is configured but not currently reachable. */
var BrowserProfileUnavailableError = class extends BrowserError {
	constructor(message, options) {
		super(message, 409, options);
		this.metadata = options?.metadata;
	}
};
/** Raised when browser resource allocation, such as CDP ports, is exhausted. */
var BrowserResourceExhaustedError = class extends BrowserError {
	constructor(message, options) {
		super(message, 507, options);
	}
};
/** Map browser-domain errors to HTTP response details. */
function toBrowserErrorResponse(err) {
	if (err instanceof BrowserProfileUnavailableError && err.metadata) return {
		status: err.status,
		message: err.message,
		...err.metadata
	};
	if (err instanceof BrowserError) return {
		status: err.status,
		message: err.message
	};
	if (err instanceof Error && err.name === "BlockedBrowserTargetError") return {
		status: 409,
		message: err.message,
		reason: BROWSER_ERROR_REASONS.navigationBlocked
	};
	if (err instanceof Error && err.name === "SsrFBlockedError") return {
		status: 400,
		message: BROWSER_NAVIGATION_BLOCKED_MESSAGE,
		reason: BROWSER_ERROR_REASONS.navigationBlocked
	};
	if (err instanceof Error && err.name === "InvalidBrowserNavigationUrlError") return {
		status: 400,
		message: err.message,
		reason: BROWSER_ERROR_REASONS.navigationBlocked
	};
	return null;
}
function parseNoDisplayDetails(value) {
	if (!value || typeof value !== "object" || Array.isArray(value)) return null;
	const details = value;
	if (typeof details.profile !== "string" || details.profile.length === 0 || details.requestedHeadless !== false || !NO_DISPLAY_HEADLESS_SOURCES.includes(details.headlessSource) || details.displayPresent !== false) return null;
	return {
		profile: details.profile,
		requestedHeadless: false,
		headlessSource: details.headlessSource,
		displayPresent: false
	};
}
/** Parse only the closed browser error metadata contract from a route payload. */
function parseBrowserErrorPayload(value) {
	if (!value || typeof value !== "object" || Array.isArray(value)) return null;
	const body = value;
	if (typeof body.error !== "string" || body.error.length === 0) return null;
	const code = isBrowserActErrorCode(body.code) ? body.code : void 0;
	const unrecognizedCode = body.unrecognizedCode === true || body.code !== void 0 && !code ? true : void 0;
	const actionCode = code ? { code } : unrecognizedCode ? { unrecognizedCode: true } : {};
	if (body.reason === BROWSER_ERROR_REASONS.navigationBlocked) return {
		error: body.error,
		...actionCode,
		reason: body.reason
	};
	if (body.reason === BROWSER_ERROR_REASONS.noDisplayForHeadedProfile) {
		const details = parseNoDisplayDetails(body.details);
		if (details) return {
			error: body.error,
			...actionCode,
			reason: body.reason,
			details
		};
	}
	return {
		error: body.error,
		...actionCode
	};
}
//#endregion
export { BrowserError as a, BrowserResetUnsupportedError as c, BrowserTargetAmbiguousError as d, BrowserValidationError as f, BrowserConflictError as i, BrowserResourceExhaustedError as l, toBrowserErrorResponse as m, BROWSER_ERROR_REASONS as n, BrowserProfileNotFoundError as o, parseBrowserErrorPayload as p, BrowserCdpEndpointBlockedError as r, BrowserProfileUnavailableError as s, BROWSER_ACT_ERROR_CODES as t, BrowserTabNotFoundError as u };
