UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

233 lines (232 loc) • 7.78 kB
import { F as resolveTimerTimeoutMs } from "./number-coercion-Dq1l5muL.mjs"; import { t as expandHomePrefix } from "./home-dir-CjKH62jd.mjs"; import { c as resolveExecApprovalsDisplayPath, o as normalizeExecApprovalsInternal, u as resolveExecApprovalsSocketPath } from "./exec-approvals-config-BF54IW19.mjs"; import { _ as resolveExecApprovalsFromFilePrepared, n as applyRecordedAllowlistUse, o as buildAllowlistEntryMatchKey, r as assertCurrentUsageAuthorization, s as createExecApprovalPolicySnapshot } from "./exec-approvals-authorization.kernel-BwTTU2c4.mjs"; import { h as updateExecApprovalsSync, i as loadExecApprovals, l as replaceExecApprovalsSnapshot, n as ensureExecApprovals, r as ensureExecApprovalsSnapshot, t as commitExecAuthorizations } from "./exec-approvals-store-B3Dzx_vP.mjs"; import "./exec-approvals-analysis-DRan0KvC.mjs"; import "./exec-approvals-allowlist-4YPZdW-H.mjs"; import "./exec-approvals-generated-migration-CwfGvxfI.mjs"; import "./exec-approvals-policy-CMlDajgd.mjs"; import net from "node:net"; import { addAbortListener } from "node:events"; import { clearTimeout, setTimeout } from "node:timers"; //#region src/infra/exec-approvals-authorization.ts function recordAllowlistUse(approvals, agentId, entry, command, resolvedPath) { recordAllowlistMatchesUse({ approvals, agentId, matches: [entry], command, resolvedPath }); } function recordAllowlistMatchesUse(params) { if (params.matches.length === 0 && !params.authorization) return; const snapshot = updateExecApprovalsSync({ update: (file) => applyRecordedAllowlistUse({ ...params, file }) }); if (snapshot) replaceExecApprovalsSnapshot(params.approvals, snapshot.file); } async function commitExecAuthorizationLocked(input) { const params = structuredClone(input); const { snapshot, readCurrent } = await commitExecAuthorizations(params); const matchKeys = new Set(params.matches.filter((entry) => entry.pattern).map(buildAllowlistEntryMatchKey)); const authorization = { ...params.authorization, policySnapshot: createExecApprovalPolicySnapshot({ file: snapshot.file, agentId: params.agentId }) }; return () => assertCurrentUsageAuthorization({ file: readCurrent(), agentId: params.agentId, command: params.command, matchKeys, authorization }); } //#endregion //#region src/infra/jsonl-socket.ts const JSONL_SOCKET_MAX_LINE_BYTES = 16777216; /** * Sends one JSONL request line, half-closes the write side, and waits for an accepted response line. */ async function requestJsonlSocket(params) { const { socketPath, requestLine, accept, signal } = params; const timeoutMs = resolveTimerTimeoutMs(params.timeoutMs, 1); return await new Promise((resolve) => { const client = new net.Socket(); let settled = false; const lineChunks = []; let lineBytes = 0; const finish = (value) => { if (settled) return; settled = true; clearTimeout(timer); abortListener?.[Symbol.dispose](); client.destroy(); resolve(value); }; const appendLineChunk = (chunk) => { if (lineBytes + chunk.byteLength > JSONL_SOCKET_MAX_LINE_BYTES) { finish(null); return false; } if (chunk.byteLength > 0) { lineChunks.push(chunk); lineBytes += chunk.byteLength; } return true; }; const timer = setTimeout(() => finish(null), timeoutMs); const abortListener = signal ? addAbortListener(signal, () => finish(null)) : void 0; if (signal?.aborted) { finish(null); return; } client.on("error", () => finish(null)); client.on("end", () => finish(null)); client.on("close", () => finish(null)); client.connect(socketPath, () => { if (!settled) client.end(`${requestLine}\n`); }); client.on("data", (data) => { let offset = 0; while (offset < data.byteLength) { const newlineIndex = data.indexOf(10, offset); if (newlineIndex === -1) { appendLineChunk(data.subarray(offset)); return; } if (!appendLineChunk(data.subarray(offset, newlineIndex))) return; const line = (lineChunks.length > 1 ? Buffer.concat(lineChunks, lineBytes) : lineChunks[0])?.toString("utf8").trim() ?? ""; lineChunks.length = 0; lineBytes = 0; offset = newlineIndex + 1; if (!line) continue; try { const msg = JSON.parse(line); const result = accept(msg); if (result === void 0) continue; finish(result); return; } catch {} } }); }); } //#endregion //#region src/infra/exec-approvals-socket.ts async function requestExecApprovalViaSocket(params) { const { socketPath, token, request } = params; if (!socketPath || !token) return null; const timeoutMs = params.timeoutMs ?? 15e3; return await requestJsonlSocket({ socketPath, requestLine: JSON.stringify({ type: "request", token, id: crypto.randomUUID(), request }), timeoutMs, accept: (value) => { const msg = value; if (msg?.type === "decision" && msg.decision) return msg.decision; } }); } //#endregion //#region src/infra/exec-approvals.ts function redactExecApprovals(snapshot) { const { raw: _raw, ...rest } = snapshot; const socketPath = snapshot.file.socket?.path?.trim(); return { ...rest, file: { ...snapshot.file, socket: socketPath ? { path: socketPath } : void 0 } }; } function normalizeExecApprovals(file) { const socketPath = file.socket?.path?.trim(); const token = file.socket?.token?.trim(); return normalizeExecApprovalsInternal({ ...file, socket: { path: socketPath, token } }); } function shapeResolvedExecApprovals(params) { const defaultSocketPath = resolveExecApprovalsSocketPath(); return resolveExecApprovalsFromFile({ file: params.file, agentId: params.agentId, overrides: params.overrides, path: params.filePath, socketPath: params.socket === "persisted" ? expandHomePrefix(params.file.socket?.path ?? defaultSocketPath) : defaultSocketPath, token: params.socket === "persisted" ? params.file.socket?.token ?? "" : "" }); } function resolveExecApprovalsWithoutSocket(params) { const resolved = shapeResolvedExecApprovals({ ...params, socket: "none" }); return (resolved.agent.security === "full" || resolved.agent.security === "deny") && resolved.agent.ask === "off" && !params.file.socket?.token?.trim() ? resolved : null; } function resolveExecApprovals(agentId, overrides) { const filePath = resolveExecApprovalsDisplayPath(); if (!overrides?.requireSocket) { const resolved = resolveExecApprovalsWithoutSocket({ file: loadExecApprovals(), filePath, agentId, overrides }); if (resolved) return resolved; } return shapeResolvedExecApprovals({ file: ensureExecApprovals(), filePath, agentId, overrides, socket: "persisted" }); } async function resolveExecApprovalsLocked(agentId, overrides) { const filePath = resolveExecApprovalsDisplayPath(); if (!overrides?.requireSocket) { const resolved = resolveExecApprovalsWithoutSocket({ file: loadExecApprovals(), filePath, agentId, overrides }); if (resolved) return resolved; } return shapeResolvedExecApprovals({ file: (await ensureExecApprovalsSnapshot()).file, filePath: resolveExecApprovalsDisplayPath(), agentId, overrides, socket: "persisted" }); } function resolveExecApprovalsFromFile(params) { const rawFile = params.file; const file = normalizeExecApprovals(params.file); return resolveExecApprovalsFromFilePrepared({ ...params, rawFile, file, token: params.token ?? file.socket?.token ?? "" }); } //#endregion export { resolveExecApprovalsLocked as a, commitExecAuthorizationLocked as c, resolveExecApprovalsFromFile as i, recordAllowlistMatchesUse as l, redactExecApprovals as n, requestExecApprovalViaSocket as o, resolveExecApprovals as r, requestJsonlSocket as s, normalizeExecApprovals as t, recordAllowlistUse as u };