openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
164 lines (163 loc) • 9.06 kB
JavaScript
import { F as resolveTimerTimeoutMs, S as parseStrictInteger, a as addTimerTimeoutGraceMs, n as MAX_TIMER_TIMEOUT_MS, p as clampPositiveTimerTimeoutMs } from "./number-coercion-CuVhdCBs.mjs";
import { c as isRecord } from "./record-coerce-TIsquoVR.mjs";
import "./string-coerce-runtime-50qKeWeL.mjs";
import "./number-runtime-CgyXj1A5.mjs";
import { i as DEFAULT_BROWSER_ACTION_TIMEOUT_MS } from "./constants-C-i9f6FL.mjs";
import { t as normalizeBrowserTimerDelayMs } from "./timer-delay-DhAs5gz8.mjs";
//#region extensions/browser/src/browser/act-policy.ts
/**
* Browser action limits and timeout normalization.
*
* Shared by the tool schema and runtime action handlers so model-facing limits
* and browser-control enforcement stay aligned.
*/
/** Maximum click delay accepted from model/tool input. */
const ACT_MAX_CLICK_DELAY_MS = 5e3;
/** Maximum explicit wait duration accepted from model/tool input. */
const ACT_MAX_WAIT_TIME_MS = 3e4;
/** Maximum viewport side length accepted by resize actions. */
const ACT_MAX_VIEWPORT_DIMENSION = 8192;
/** Existing-session actions whose runtime accepts a per-call timeout override. */
const EXISTING_SESSION_TIMEOUT_OVERRIDE_KINDS = /* @__PURE__ */ new Set([
"click",
"clickCoords",
"evaluate",
"wait"
]);
const ACT_MIN_TIMEOUT_MS = 500;
const ACT_MAX_INTERACTION_TIMEOUT_MS = 6e4;
const ACT_MAX_WAIT_TIMEOUT_MS = 12e4;
const ACT_DEFAULT_INTERACTION_TIMEOUT_MS = 8e3;
const ACT_DEFAULT_WAIT_TIMEOUT_MS = 2e4;
/** Grace between the runtime's action budget and an outer transport watchdog. */
const BROWSER_ACTION_TRANSPORT_SLACK_MS = 5e3;
/** Existing-session verification keeps observing after the action settles. */
const EXISTING_SESSION_NAVIGATION_RECHECK_DELAYS_MS = [
0,
250,
500
];
const EXISTING_SESSION_NAVIGATION_GRACE_MS = EXISTING_SESSION_NAVIGATION_RECHECK_DELAYS_MS.reduce((total, delay) => total + delay, 0) + (EXISTING_SESSION_NAVIGATION_RECHECK_DELAYS_MS.at(-1) ?? 0);
/** Keep navigation timeouts consistent across transports and browser backends. */
function resolveBrowserNavigationTimeoutMs(timeoutMs) {
return Math.min(12e4, resolveTimerTimeoutMs(timeoutMs, 2e4, 1e3));
}
function normalizeActBoundedNonNegativeMs(value, fieldName, maxMs) {
if (value === void 0) return;
if (!Number.isFinite(value) || value < 0) throw new Error(`${fieldName} must be >= 0`);
const normalized = Math.floor(value);
if (normalized > maxMs) throw new Error(`${fieldName} exceeds maximum of ${maxMs}ms`);
return normalized;
}
/** Clamp interaction actions to the supported browser-control timeout window. */
function resolveActInteractionTimeoutMs(timeoutMs) {
return Math.min(ACT_MAX_INTERACTION_TIMEOUT_MS, resolveTimerTimeoutMs(timeoutMs, ACT_DEFAULT_INTERACTION_TIMEOUT_MS, ACT_MIN_TIMEOUT_MS));
}
/** Clamp wait actions to their wider supported browser-control timeout window. */
function resolveActWaitTimeoutMs(timeoutMs) {
return Math.min(ACT_MAX_WAIT_TIMEOUT_MS, resolveTimerTimeoutMs(timeoutMs, ACT_DEFAULT_WAIT_TIMEOUT_MS, ACT_MIN_TIMEOUT_MS));
}
function parseTimerInteger(value) {
return typeof value === "number" && Number.isFinite(value) ? Math.floor(value) : parseStrictInteger(value);
}
function resolveNonNegativeTimerMs(value) {
const parsed = parseTimerInteger(value);
return parsed !== void 0 && parsed >= 0 ? resolveTimerTimeoutMs(parsed, 0, 0) : 0;
}
function addExecutionBudgetMs(totalMs, nextMs) {
return Math.min(MAX_TIMER_TIMEOUT_MS, totalMs + nextMs);
}
function multiplyExecutionBudgetMs(durationMs, count) {
return Math.min(MAX_TIMER_TIMEOUT_MS, durationMs * count);
}
function resolveInteractionTimeoutMs(request) {
return resolveActInteractionTimeoutMs(parseTimerInteger("timeoutMs" in request ? request.timeoutMs : void 0));
}
function addNavigationGraceMs(durationMs, count = 1) {
return addExecutionBudgetMs(durationMs, multiplyExecutionBudgetMs(250, count));
}
function resolveLeafExecutionBudgetMs(request) {
switch (request.kind) {
case "click": {
const timeoutMs = resolveInteractionTimeoutMs(request);
const delayMs = Math.min(ACT_MAX_CLICK_DELAY_MS, resolveNonNegativeTimerMs(request.delayMs));
return addNavigationGraceMs(delayMs > 0 ? addExecutionBudgetMs(timeoutMs * 2, delayMs) : timeoutMs);
}
case "clickCoords": {
const delayMs = Math.min(ACT_MAX_CLICK_DELAY_MS, resolveNonNegativeTimerMs(request.delayMs));
return addNavigationGraceMs(addExecutionBudgetMs(clampPositiveTimerTimeoutMs(parseTimerInteger(request.timeoutMs)) ?? 0, multiplyExecutionBudgetMs(delayMs, request.doubleClick ? 3 : 1)));
}
case "type": {
const phaseCount = (request.slowly ? 2 : 1) + (request.submit ? 1 : 0);
return addNavigationGraceMs(multiplyExecutionBudgetMs(resolveInteractionTimeoutMs(request), phaseCount));
}
case "press": return addNavigationGraceMs(resolveNonNegativeTimerMs(request.delayMs));
case "insertText": return addNavigationGraceMs(0);
case "fill": {
const fieldCount = (Array.isArray(request.fields) ? request.fields : []).filter((field) => Boolean(field) && typeof field === "object" && typeof field.ref === "string" && Boolean(field.ref.trim())).length;
return addNavigationGraceMs(multiplyExecutionBudgetMs(resolveInteractionTimeoutMs(request), fieldCount), fieldCount);
}
case "evaluate":
case "scrollIntoView": return addNavigationGraceMs(resolveActWaitTimeoutMs(parseTimerInteger(request.timeoutMs)));
case "hover":
case "drag":
case "select": return addNavigationGraceMs(resolveInteractionTimeoutMs(request));
case "resize":
case "close": return 0;
}
return 0;
}
function resolveExecutionBudgetMs(request) {
if (request.kind === "batch") return (Array.isArray(request.actions) ? request.actions.filter(isRecord) : []).reduce((totalMs, action) => addExecutionBudgetMs(totalMs, resolveExecutionBudgetMs(action)), 0);
if (request.kind !== "wait") return resolveLeafExecutionBudgetMs(request);
const conditionCount = [
Boolean(request.text),
Boolean(request.textGone),
typeof request.selector === "string" && Boolean(request.selector.trim()),
typeof request.url === "string" && Boolean(request.url.trim()),
Boolean(request.loadState),
typeof request.fn === "string" && Boolean(request.fn.trim())
].filter(Boolean).length;
const timeoutMs = resolveActWaitTimeoutMs(parseTimerInteger(request.timeoutMs));
return addExecutionBudgetMs(resolveNonNegativeTimerMs(request.timeMs), multiplyExecutionBudgetMs(timeoutMs, conditionCount));
}
/** Bound logical action and verification phases without renewing every MCP call's budget. */
function resolveExistingSessionActTimeouts(request) {
const requestedTimeoutMs = EXISTING_SESSION_TIMEOUT_OVERRIDE_KINDS.has(request.kind) && "timeoutMs" in request ? parseTimerInteger(request.timeoutMs) : void 0;
const timeoutMs = normalizeBrowserTimerDelayMs(requestedTimeoutMs ?? 6e4);
let actionTimeoutMs = timeoutMs;
if (request.kind === "wait") {
const timeMs = resolveNonNegativeTimerMs(request.timeMs);
actionTimeoutMs = [
request.text,
request.textGone,
request.selector,
request.url,
request.loadState,
request.fn
].some((value) => typeof value === "string" && Boolean(value.trim())) ? addExecutionBudgetMs(timeMs, Math.max(250, timeoutMs)) : Math.max(timeMs, timeoutMs);
}
const verificationTimeoutMs = request.kind === "resize" || request.kind === "close" ? 0 : addExecutionBudgetMs(timeoutMs, EXISTING_SESSION_NAVIGATION_GRACE_MS);
return {
timeoutMs,
bodyTimeoutMs: request.kind === "wait" ? void 0 : actionTimeoutMs,
verificationTimeoutMs,
requestTimeoutMs: addExecutionBudgetMs(actionTimeoutMs, verificationTimeoutMs)
};
}
/**
* Resolve the runtime budget before an outer transport watchdog is armed.
* Wait phases and batch children execute serially, so maxima would abort valid work midway.
*/
function resolveBrowserActExecutionBudgetMs(request) {
const executionBudgetMs = resolveExecutionBudgetMs(request);
if (request.kind === "wait") return executionBudgetMs;
return (request.kind === "batch" ? void 0 : clampPositiveTimerTimeoutMs(parseTimerInteger("timeoutMs" in request ? request.timeoutMs : void 0))) === void 0 ? Math.max(DEFAULT_BROWSER_ACTION_TIMEOUT_MS, executionBudgetMs) : executionBudgetMs;
}
/** Add action transport slack once after the full sequential runtime budget is known. */
function resolveBrowserActRequestTimeoutMs(request) {
const existingSessionBudgetMs = request.kind === "batch" ? 0 : resolveExistingSessionActTimeouts(request).requestTimeoutMs;
return addTimerTimeoutGraceMs(Math.max(resolveBrowserActExecutionBudgetMs(request), existingSessionBudgetMs), 5e3) ?? 1;
}
//#endregion
export { EXISTING_SESSION_NAVIGATION_RECHECK_DELAYS_MS as a, resolveActInteractionTimeoutMs as c, resolveBrowserNavigationTimeoutMs as d, resolveExistingSessionActTimeouts as f, BROWSER_ACTION_TRANSPORT_SLACK_MS as i, resolveActWaitTimeoutMs as l, ACT_MAX_VIEWPORT_DIMENSION as n, EXISTING_SESSION_TIMEOUT_OVERRIDE_KINDS as o, ACT_MAX_WAIT_TIME_MS as r, normalizeActBoundedNonNegativeMs as s, ACT_MAX_CLICK_DELAY_MS as t, resolveBrowserActRequestTimeoutMs as u };