UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

147 lines (146 loc) 5.58 kB
import { a as resolveSandboxInputPath } from "./sandbox-paths-hdOwYXJD.js"; import { n as resolvePathFromInput, t as preserveAtPrefixedRelativePath } from "./path-policy-s_BvJZSk.js"; import path from "node:path"; //#region src/agents/apply-patch-targets.ts const ADD_FILE_MARKER = "*** Add File: "; const DELETE_FILE_MARKER = "*** Delete File: "; const UPDATE_FILE_MARKER = "*** Update File: "; const MOVE_TO_MARKER = "*** Move to: "; function readPatchText(input) { if (typeof input === "string") return input; if (input && typeof input === "object" && "input" in input) { const candidate = input.input; return typeof candidate === "string" ? candidate : void 0; } } function normalizeMarkerHeaderLine(line) { if (line === void 0) return; const startTrimmed = line.trimStart(); return startTrimmed.startsWith("***") ? startTrimmed.trimEnd() : void 0; } function readMarkerPath(line, marker) { const candidate = normalizeMarkerHeaderLine(line); return candidate?.startsWith(marker) ? candidate.slice(marker.length) : void 0; } /** Walk the executor-compatible envelope grammar without resolving its paths. */ function extractApplyPatchTargets(input) { const text = readPatchText(input); if (!text) return []; const lines = text.split(/\r?\n/); const targets = []; for (let index = 0; index < lines.length; index += 1) { const line = lines.at(index); const addPath = readMarkerPath(line, ADD_FILE_MARKER); if (addPath !== void 0) { targets.push({ kind: "add", path: addPath }); while (index + 1 < lines.length && lines.at(index + 1)?.startsWith("+")) index += 1; continue; } const deletePath = readMarkerPath(line, DELETE_FILE_MARKER); if (deletePath !== void 0) { targets.push({ kind: "delete", path: deletePath }); continue; } const updatePath = readMarkerPath(line, UPDATE_FILE_MARKER); if (updatePath === void 0) continue; targets.push({ kind: "update", path: updatePath }); let lookahead = index + 1; while (lookahead < lines.length && lines.at(lookahead)?.trim() === "") lookahead += 1; const movePath = readMarkerPath(lines.at(lookahead), MOVE_TO_MARKER); if (movePath !== void 0) { targets.push({ kind: "move", path: movePath }); lookahead += 1; } while (lookahead < lines.length) { const lookaheadLine = lines.at(lookahead); if (lookaheadLine === void 0 || lookaheadLine.startsWith("***")) break; lookahead += 1; } index = lookahead - 1; } return targets; } //#endregion //#region src/agents/apply-patch-paths.ts /** * Path extraction for the apply_patch envelope grammar. * Used by pre-execution policy hooks that only need destination paths, not the * full strict patch parser. */ /** Resolve a patch input through the same literal-@ policy used by execution. */ async function resolveApplyPatchInputPath(raw, options = {}) { const cwd = options.cwd ?? options.sandbox?.root ?? process.cwd(); const preserved = await preserveAtPrefixedRelativePath(raw, cwd, options.sandbox?.bridge, options.signal); if (!raw.startsWith("@") || preserved !== raw) return preserved; const referenced = raw.slice(1); return referenced === "~" || referenced.startsWith("~/") || referenced.startsWith("~\\") ? resolvePathFromInput(raw, cwd) : referenced; } function normalizePatchPath(raw, options = {}) { if (raw.length === 0) return; const cwd = options.cwd ?? options.sandbox?.root ?? process.cwd(); try { const filePath = preserveAtPrefixedRelativePath(raw, cwd); const resolved = options.sandbox ? options.sandbox.bridge.resolvePath({ filePath, cwd }) : void 0; const normalized = path.normalize(resolved ? resolved.hostPath ?? resolved.containerPath : resolveSandboxInputPath(filePath, cwd)); return normalized && normalized !== "." ? normalized : void 0; } catch { return; } } function pushPath(target, seen, raw, options) { const normalized = normalizePatchPath(raw, options); if (!normalized) return; if (seen.has(normalized)) return; seen.add(normalized); target.push(normalized); } /** * Walk an apply_patch envelope and return every destination path found, in * the order they appear. Duplicates are de-duplicated (the same file may be * referenced multiple times within a single envelope). Returns `[]` for any * input that is not a recognised envelope. */ function extractApplyPatchTargetPaths(input, options = {}) { const paths = []; const seen = /* @__PURE__ */ new Set(); for (const target of extractApplyPatchTargets(input)) pushPath(paths, seen, target.path, options); return paths; } /** Derive policy-visible paths using the asynchronous resolver used by execution. */ async function extractResolvedApplyPatchTargetPaths(input, options = {}) { const paths = []; const seen = /* @__PURE__ */ new Set(); const cwd = options.cwd ?? options.sandbox?.root ?? process.cwd(); for (const target of extractApplyPatchTargets(input)) try { const filePath = await resolveApplyPatchInputPath(target.path, options); const resolved = options.sandbox?.bridge.resolvePath({ filePath, cwd }); const normalized = resolved?.hostPath ? path.normalize(resolved.hostPath) : resolved ? path.posix.normalize(resolved.containerPath) : path.normalize(resolveSandboxInputPath(filePath, cwd)); if (normalized && normalized !== "." && !seen.has(normalized)) { seen.add(normalized); paths.push(normalized); } } catch { options.signal?.throwIfAborted(); } return paths; } //#endregion export { extractResolvedApplyPatchTargetPaths as n, resolveApplyPatchInputPath as r, extractApplyPatchTargetPaths as t };