oclaw/runtime/tools/public/apply_patch_tool.py
oliver 420abac9f1 refactor: root-package imports (svc/runtime/interfaces) and fix PYTHONPATH
- Rename platform/ to svc/ to avoid shadowing stdlib platform.
- Replace from oclaw.* with from svc/runtime/interfaces; update -m CLI paths.
- tests/conftest: prepend repo root to sys.path (no parent-folder package name).
- CI: paths and offline_eval script under repo root.
- Ops scripts: PYTHONPATH must be repo root for python -m runtime.* (fixes gateway/WhatsApp sidecar startup).
- Fix default oclaw.json path in tabular/file attachment limits; stabilize attachment test config.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-13 14:51:17 +08:00

54 lines
2 KiB
Python

from __future__ import annotations
import hashlib
from typing import Any
from runtime.tools.base import ToolSpec
from runtime.tools.path_guard import resolve_workspace_path
def apply_patch_tool() -> ToolSpec:
def handler(args: dict[str, Any]) -> dict[str, Any]:
path = str(args.get("path") or "").strip()
new_content = str(args.get("new_content") or "")
expected_sha256 = str(args.get("expected_sha256") or "").strip()
p = resolve_workspace_path(path)
if p.exists() and p.is_file() and expected_sha256:
cur = hashlib.sha256(p.read_bytes()).hexdigest()
if cur != expected_sha256:
return {
"ok": False,
"error": "sha_mismatch",
"path": str(p),
"expected_sha256": expected_sha256,
"current_sha256": cur,
}
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(new_content, encoding="utf-8")
sha = hashlib.sha256(p.read_bytes()).hexdigest()
return {"ok": True, "path": str(p), "sha256": sha, "bytes": p.stat().st_size}
return ToolSpec(
name="apply_patch",
description="Overwrite a file with new content (optional sha256 precondition).",
parameters={
"type": "object",
"properties": {
"path": {"type": "string", "description": "File path, relative to workspace root."},
"new_content": {"type": "string", "description": "New full file content."},
"expected_sha256": {
"type": "string",
"description": "If provided, the current file sha256 must match.",
},
},
"required": ["path", "new_content"],
"additionalProperties": False,
},
handler=handler,
tags=frozenset({"public", "write"}),
risk_level="high",
read_only=False,
)
__all__ = ["apply_patch_tool"]