UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

100 lines (99 loc) 3.86 kB
import { o as asDateTimestampMs } from "./number-coercion-CJQ8TR--.js"; import "./number-coercion-Z7n6tXLk.js"; import { n as defaultRuntime } from "./runtime-B4lgFmsS.js"; import { i as getRuntimeConfig } from "./io-Gi7-pyU-.js"; import "./config-C9RxTsn1.js"; import { A as removeBrowserRegistryEntry, O as readBrowserRegistry, j as removeRegistryEntry, k as readRegistry } from "./docker-Z5I59fn0.js"; import { a as getSandboxBackendManager, k as dockerSandboxBackendManager, r as stopBrowserBridgeServer, t as BROWSER_BRIDGES } from "./browser-bridges-CXnrIxHc.js"; //#region src/agents/sandbox/prune.ts /** * Sandbox registry pruning. * * Removes stale runtime containers and browser bridges on a best-effort schedule. */ let lastPruneAtMs = 0; function shouldPruneSandboxEntry(cfg, now, entry) { const idleHours = cfg.prune.idleHours; const maxAgeDays = cfg.prune.maxAgeDays; if (idleHours === 0 && maxAgeDays === 0) return false; const nowMs = asDateTimestampMs(now) ?? 0; const lastUsedAtMs = asDateTimestampMs(entry.lastUsedAtMs) ?? 0; const createdAtMs = asDateTimestampMs(entry.createdAtMs) ?? 0; const idleMs = nowMs - lastUsedAtMs; const ageMs = nowMs - createdAtMs; return idleHours > 0 && idleMs > idleHours * 60 * 60 * 1e3 || maxAgeDays > 0 && ageMs > maxAgeDays * 24 * 60 * 60 * 1e3; } /** Removes expired registry entries and their backing runtime resources. */ async function pruneSandboxRegistryEntries(params) { const now = Date.now(); if (params.cfg.prune.idleHours === 0 && params.cfg.prune.maxAgeDays === 0) return; const registry = await params.read(); for (const entry of registry.entries) { if (!shouldPruneSandboxEntry(params.cfg, now, entry)) continue; try { await params.removeRuntime(entry); await params.remove(entry.containerName); await params.onRemoved?.(entry); } catch (error) { const message = error instanceof Error ? error.message : typeof error === "string" ? error : JSON.stringify(error); defaultRuntime.error?.(`Sandbox prune failed to remove ${entry.containerName}: ${message ?? "unknown error"}`); } } } /** Prunes ordinary sandbox runtime containers from the configured backend manager. */ async function pruneSandboxContainers(cfg) { const config = getRuntimeConfig(); await pruneSandboxRegistryEntries({ cfg, read: readRegistry, remove: removeRegistryEntry, removeRuntime: async (entry) => { await getSandboxBackendManager(entry.backendId ?? "docker")?.removeRuntime({ entry, config }); } }); } /** Prunes browser bridge containers and closes matching in-process bridge servers. */ async function pruneSandboxBrowsers(cfg) { const config = getRuntimeConfig(); await pruneSandboxRegistryEntries({ cfg, read: readBrowserRegistry, remove: removeBrowserRegistryEntry, removeRuntime: async (entry) => { await dockerSandboxBackendManager.removeRuntime({ entry: { ...entry, backendId: "docker", runtimeLabel: entry.containerName, configLabelKind: "Image" }, config }); }, onRemoved: async (entry) => { const bridge = BROWSER_BRIDGES.get(entry.sessionKey); if (bridge?.containerName === entry.containerName) { await stopBrowserBridgeServer(bridge.bridge.server).catch(() => void 0); BROWSER_BRIDGES.delete(entry.sessionKey); } } }); } /** Runs sandbox pruning at most once per throttle window. */ async function maybePruneSandboxes(cfg) { const now = Date.now(); if (now - lastPruneAtMs < 300 * 1e3) return; lastPruneAtMs = now; try { await pruneSandboxContainers(cfg); await pruneSandboxBrowsers(cfg); } catch (error) { const message = error instanceof Error ? error.message : typeof error === "string" ? error : JSON.stringify(error); defaultRuntime.error?.(`Sandbox prune failed: ${message ?? "unknown error"}`); } } //#endregion export { maybePruneSandboxes };