UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

349 lines (348 loc) • 13.1 kB
import { w as resolveGlobalSingleton } from "./number-coercion-PJEgwXYS.mjs"; import { createRequire } from "node:module"; import { existsSync } from "node:fs"; import { posix } from "node:path"; import { getEnvironmentData, isMainThread, setEnvironmentData } from "node:worker_threads"; //#region node-version.mjs const NODE_RELEASE_VERSION_RE = /^v?((?:0|[1-9]\d*))\.((?:0|[1-9]\d*))\.((?:0|[1-9]\d*))(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u; const NODE_RELEASE_FLOORS = [{ major: 24, minor: 22, patch: 1 }, { major: 26, minor: 12, patch: 1 }]; NODE_RELEASE_FLOORS[NODE_RELEASE_FLOORS.length - 1]; `${NODE_RELEASE_FLOORS.map(({ major, minor, patch }, index) => `>=${major}.${minor}.${patch}${index < NODE_RELEASE_FLOORS.length - 1 ? ` <${major + 1}` : ""}`).join(" || ").replaceAll(" || ", ", ").replace(/, ([^,]+)$/, ", or $1")}`; /** Parses an anchored release SemVer, allowing a leading v and valid build metadata. */ function parseNodeReleaseVersion(value) { if (typeof value !== "string") return null; const match = NODE_RELEASE_VERSION_RE.exec(value.trim()); if (!match) return null; const version = { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) }; return Object.values(version).every(Number.isSafeInteger) ? version : null; } function isNodeVersionAtLeast(version, minimum) { if (!version) return false; if (version.major !== minimum.major) return version.major > minimum.major; if (version.minor !== minimum.minor) return version.minor > minimum.minor; return version.patch >= minimum.patch; } function renderProcessNodeVersionCheck() { return `((value) => { if (typeof value !== "string") return false; const match = new RegExp(${JSON.stringify(NODE_RELEASE_VERSION_RE.source)}, "u").exec(value.trim()); if (!match) return false; const version = { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) }; if (!Object.values(version).every(Number.isSafeInteger)) return false; const floors = ${JSON.stringify(NODE_RELEASE_FLOORS)}; const minimum = floors.find((floor) => floor.major === version.major); const atLeast = (floor) => version.major > floor.major || (version.major === floor.major && (version.minor > floor.minor || (version.minor === floor.minor && version.patch >= floor.patch))); return minimum ? atLeast(minimum) : version.major > floors[floors.length - 1].major; })(process.versions.node)`; } renderProcessNodeVersionCheck(); //#endregion //#region src/infra/diagnostic-flags-env.ts function parseDiagnosticEnvFlags(raw) { const trimmed = raw?.trim() ?? ""; const lowered = trimmed.toLowerCase(); if (!lowered) return { flags: [], disablesAll: false }; if ([ "0", "false", "off", "none" ].includes(lowered)) return { flags: [], disablesAll: true }; if ([ "1", "true", "all", "*" ].includes(lowered)) return { flags: ["*"], disablesAll: false }; return { flags: trimmed.split(/[,\s]+/), disablesAll: false }; } //#endregion //#region node-sqlite.mjs function probeSqlite(DatabaseSync) { const result = { available: false, version: null, text: false, blob: false, json: false }; let database; try { database = new DatabaseSync(":memory:"); result.available = true; const version = database.prepare("SELECT sqlite_version() AS version").get()?.version; result.version = typeof version === "string" ? version : null; const text = "a\0b\0"; const bytes = Buffer.from(text, "utf8"); const json = JSON.stringify({ value: text }); database.exec("CREATE TABLE probe (text_value TEXT, blob_value BLOB, json_value TEXT)"); database.prepare("INSERT INTO probe VALUES (?, ?, ?)").run(text, bytes, json); const row = database.prepare("SELECT text_value, blob_value, json_value FROM probe").get(); result.text = typeof row?.text_value === "string" && row.text_value.length === 4 && Buffer.from(row.text_value, "utf8").equals(bytes); result.blob = row?.blob_value instanceof Uint8Array && Buffer.from(row.blob_value).equals(bytes); result.json = row?.json_value === json && JSON.parse(row.json_value).value === text; } catch (error) { result.error = error instanceof Error ? error.message : String(error); } finally { database?.close(); } return result; } function isSqliteWalResetSafeVersion(value) { const match = /^(\d+)\.(\d+)\.(\d+)$/u.exec(value.trim()); if (!match) return false; const [major, minor, patch] = match.slice(1).map(Number); if (![ major, minor, patch ].every(Number.isSafeInteger)) return false; return major > 3 || major === 3 && (minor > 51 || minor === 51 && patch >= 3 || minor === 50 && patch >= 7 || minor === 44 && patch >= 6); } `${probeSqlite.toString()}`; //#endregion //#region src/infra/bun-sqlite-library.ts const WORKER_SELECTION_KEY = "openclaw.bunSqliteLibrarySelection"; const WORKER_CAPABILITIES_KEY = "openclaw.sqliteRuntimeCapabilities"; const SQLITE_NATIVE_RUNTIME_ADMISSION_KEY = "openclaw.sqliteNativeRuntimeAdmission"; const SQLITE_CANONICAL_DEFINITIONS_KEY = "openclaw.agentCanonicalValidationSchemaDefinitions"; const SQLITE_EXPECTED_SCHEMA_CONTRACTS_KEY = "openclaw.sqliteExpectedSchemaContracts.v1"; function createCapabilities(select) { let decision; let initialization; let earlyTopologyOwners = 0; const pending = Object.freeze({ explicitSqliteCloseReleasesNativeResources: false, decided: false, reason: "SQLite close capability has not been decided" }); function decide(value) { if (!decision) { decision = Object.freeze(value); setEnvironmentData(WORKER_CAPABILITIES_KEY, decision); if (decision.explicitSqliteCloseReleasesNativeResources && earlyTopologyOwners > 0) process.emitWarning(`SQLite close became capable after ${earlyTopologyOwners} topology owners were created; those owners remain conservative`, { code: "SQLITE_EARLY_TOPOLOGY" }); } return decision; } function conservative(reason) { return { explicitSqliteCloseReleasesNativeResources: false, decided: true, reason }; } function settled() { if (decision) return decision; if (!process.versions.bun) return decide({ explicitSqliteCloseReleasesNativeResources: true, decided: true, reason: "Node runtime" }); if (process.platform === "win32") return decide(conservative("Bun Windows native-close conformance is not qualified")); if (!isMainThread) return decide({ ...pending, reason: "Parent did not complete SQLite close admission", ...getEnvironmentData(WORKER_CAPABILITIES_KEY) }); } return { get() { return settled() ?? pending; }, capture() { const fact = settled() ?? pending; if (!fact.decided) earlyTopologyOwners += 1; return fact.explicitSqliteCloseReleasesNativeResources; }, initialize() { initialization ??= (async () => { select(); const ready = settled(); if (ready) return ready; try { if (parseDiagnosticEnvFlags(process.env.OPENCLAW_DIAGNOSTICS).flags.some((flag) => flag.toLowerCase() === "sqlite.close.conservative")) return decide(conservative("SQLite close optimization disabled by internal diagnostic flag")); const { probeSqliteNativeClose } = await import("./bun-sqlite-close-probe-BOywC01Q.mjs"); return decide({ ...await probeSqliteNativeClose(), decided: true }); } catch (error) { return decide(conservative(`SQLite close check failed: ${String(error)}`)); } })(); return initialization; } }; } function probeLibrary(path) { const { dlopen, FFIType } = createRequire(import.meta.url)("bun:ffi"); const library = dlopen(path, { sqlite3_libversion: { args: [], returns: FFIType.cstring }, sqlite3_compileoption_used: { args: [FFIType.cstring], returns: FFIType.i32 } }); try { return { version: String(library.symbols.sqlite3_libversion()), extensionLoadingSupported: library.symbols.sqlite3_compileoption_used(Buffer.from("OMIT_LOAD_EXTENSION\0")) === 0 }; } finally { library.close(); } } function selectLibrary(path) { const { Database } = createRequire(import.meta.url)("bun:sqlite"); Database.setCustomSQLite(path); } function createSelector() { let selection; let failure; return (options = {}) => { if (failure) throw failure; if (selection) return selection; const override = options.explicitPath ?? (process.env.OPENCLAW_SQLITE_LIBRARY?.trim() || void 0); if (!process.versions.bun || process.platform !== "darwin") { selection = override ? { source: "runtime", ignoredOverride: "OPENCLAW_SQLITE_LIBRARY requires Bun on macOS" } : { source: "runtime" }; return selection; } const prefix = process.env.HOMEBREW_PREFIX?.trim(); const candidates = override !== void 0 ? [override] : [.../* @__PURE__ */ new Set([ ...prefix ? [posix.join(prefix, "opt/sqlite/lib/libsqlite3.dylib")] : [], "/opt/homebrew/opt/sqlite/lib/libsqlite3.dylib", "/usr/local/opt/sqlite/lib/libsqlite3.dylib", "/opt/local/lib/libsqlite3.dylib" ])]; for (const path of candidates) { let probe; try { try { probe = probeLibrary(path); } catch (error) { throw existsSync(path) ? error : new Error("missing file", { cause: error }); } if (!isSqliteWalResetSafeVersion(probe.version)) throw new Error(`SQLite version ${probe.version} below the WAL safety floor`); if (!probe.extensionLoadingSupported) throw new Error("built with SQLITE_OMIT_LOAD_EXTENSION"); } catch (error) { if (override === void 0) continue; failure = selectionError(path, error); throw failure; } try { selectLibrary(path); } catch (error) { failure = selectionError(path, error); throw failure; } selection = { source: override === void 0 ? "discovered" : "env", path, version: probe.version, extensionLoadingSupported: true }; return selection; } selection = { source: "runtime" }; return selection; }; } function selectionError(path, error) { return new Error(`Cannot use SQLite library ${path}: ${error instanceof Error ? error.message : String(error)}. Fix or unset OPENCLAW_SQLITE_LIBRARY; install a supported library with brew install sqlite.`, { cause: error }); } function inheritedSelection() { const value = getEnvironmentData(WORKER_SELECTION_KEY); if (value === void 0) return; if (value !== null && typeof value === "object" && !Array.isArray(value)) { const source = "source" in value ? value.source : void 0; if (source === "runtime") return { source: "runtime" }; const path = "path" in value ? value.path : void 0; const version = "version" in value ? value.version : void 0; const extensionLoadingSupported = "extensionLoadingSupported" in value ? value.extensionLoadingSupported : void 0; if ((source === "env" || source === "discovered") && typeof path === "string" && typeof version === "string" && extensionLoadingSupported === true) return { source, path, version, extensionLoadingSupported: true }; } throw new Error("Invalid inherited SQLite library selection"); } function createRuntimeSelector() { const sharedLibrary = Boolean(process.versions.bun) && process.platform === "darwin"; const inherited = sharedLibrary && !isMainThread ? inheritedSelection() : void 0; const select = createSelector(); let published = false; return (options) => { const selection = inherited ?? select(options); if (sharedLibrary && isMainThread && !published) { setEnvironmentData(WORKER_SELECTION_KEY, Object.freeze({ ...selection })); published = true; } return selection; }; } function runtimeSelector() { return resolveGlobalSingleton(Symbol.for("openclaw.bunSqliteLibrarySelection"), createRuntimeSelector); } function capabilities() { const select = runtimeSelector(); return select.capabilities ??= createCapabilities(select); } function getSqliteRuntimeCapabilities() { return capabilities().get(); } /** A topology owner keeps this snapshot for placement and paired native retirement. */ function captureSqliteWorkerClosePolicy() { return capabilities().capture(); } /** Retained supervisors forward the caller's current facts when creating each descendant. */ function captureSqliteWorkerEnvironmentData() { return [ [WORKER_SELECTION_KEY, ensureSqliteLibrarySelected()], [WORKER_CAPABILITIES_KEY, getSqliteRuntimeCapabilities()], [SQLITE_NATIVE_RUNTIME_ADMISSION_KEY, getEnvironmentData(SQLITE_NATIVE_RUNTIME_ADMISSION_KEY)], [SQLITE_CANONICAL_DEFINITIONS_KEY, getEnvironmentData(SQLITE_CANONICAL_DEFINITIONS_KEY)], [SQLITE_EXPECTED_SCHEMA_CONTRACTS_KEY, getEnvironmentData(SQLITE_EXPECTED_SCHEMA_CONTRACTS_KEY)] ]; } /** Select once, before any SQLite open; shared across CLI and bundled SDK module graphs. */ function ensureSqliteLibrarySelected(options) { return runtimeSelector()(options); } //#endregion export { ensureSqliteLibrarySelected as a, isNodeVersionAtLeast as c, captureSqliteWorkerEnvironmentData as i, parseNodeReleaseVersion as l, SQLITE_NATIVE_RUNTIME_ADMISSION_KEY as n, getSqliteRuntimeCapabilities as o, captureSqliteWorkerClosePolicy as r, isSqliteWalResetSafeVersion as s, SQLITE_EXPECTED_SCHEMA_CONTRACTS_KEY as t };