mirror of
https://github.com/hansjone/oclaw.git
synced 2026-10-09 05:50:44 +08:00
- 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>
60 lines
2.1 KiB
Python
60 lines
2.1 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 read_file_tool() -> ToolSpec:
|
|
def _handler(args: dict[str, Any]) -> dict[str, Any]:
|
|
path = str(args.get("path") or "").strip()
|
|
offset = int(args.get("offset") or 1)
|
|
limit = int(args.get("limit") or 400)
|
|
if offset == 0:
|
|
offset = 1
|
|
if limit <= 0:
|
|
limit = 1
|
|
p = resolve_workspace_path(path)
|
|
if not p.exists() or not p.is_file():
|
|
return {"ok": False, "error": "file_not_found", "path": str(p)}
|
|
text = p.read_text(encoding="utf-8", errors="replace").splitlines()
|
|
if offset < 0:
|
|
start = max(0, len(text) + offset)
|
|
else:
|
|
start = max(0, offset - 1)
|
|
end = min(len(text), start + min(limit, 2000))
|
|
out_lines = [f"{i + 1}|{text[i]}" for i in range(start, end)]
|
|
sha = hashlib.sha256(p.read_bytes()).hexdigest()
|
|
return {
|
|
"ok": True,
|
|
"path": str(p),
|
|
"start_line": start + 1,
|
|
"end_line": end,
|
|
"total_lines": len(text),
|
|
"sha256": sha,
|
|
"content": "\n".join(out_lines),
|
|
}
|
|
|
|
return ToolSpec(
|
|
name="read_file",
|
|
description="Read a text file from the workspace with line numbers.",
|
|
parameters={
|
|
"type": "object",
|
|
"properties": {
|
|
"path": {"type": "string", "description": "File path, relative to workspace root."},
|
|
"offset": {"type": "integer", "description": "1-indexed start line; negative counts from end.", "default": 1},
|
|
"limit": {"type": "integer", "description": "Max lines to return (capped).", "default": 400},
|
|
},
|
|
"required": ["path"],
|
|
"additionalProperties": False,
|
|
},
|
|
handler=_handler,
|
|
tags=frozenset({"public", "workspace"}),
|
|
read_only=True,
|
|
risk_level="low",
|
|
)
|
|
|
|
|
|
__all__ = ["read_file_tool"]
|