File_System tool is easier for smaller models to understand and 1-shot
Browse files- Modules/File_System.py +25 -16
Modules/File_System.py
CHANGED
|
@@ -18,17 +18,18 @@ TOOL_SUMMARY = (
|
|
| 18 |
"Browse, search, and manage files within a safe root. "
|
| 19 |
"Actions: list, read, write, append, mkdir, move, copy, delete, info, search, help. "
|
| 20 |
"Fill other fields as needed. "
|
| 21 |
-
"Use paths like
|
| 22 |
"Use 'help' to see action-specific required fields and examples."
|
| 23 |
)
|
| 24 |
|
| 25 |
HELP_TEXT = (
|
| 26 |
"File System — actions and usage\n\n"
|
| 27 |
"Root: paths resolve under Nymbo-Tools/Filesystem by default (or NYMBO_TOOLS_ROOT if set). "
|
|
|
|
| 28 |
"Absolute paths are disabled unless UNSAFE_ALLOW_ABS_PATHS=1.\n\n"
|
| 29 |
"Actions and fields:\n"
|
| 30 |
-
"- list: path='
|
| 31 |
-
"- read: path, offset=0, max_chars=4000 (shows next_cursor when truncated)\n"
|
| 32 |
"- write: path, content (UTF-8), create_dirs=true\n"
|
| 33 |
"- append: path, content (UTF-8), create_dirs=true\n"
|
| 34 |
"- mkdir: path (directory), exist_ok=true\n"
|
|
@@ -40,13 +41,13 @@ HELP_TEXT = (
|
|
| 40 |
"- help: show this guide\n\n"
|
| 41 |
"Errors are returned as JSON with fields: {status:'error', code, message, path?, hint?, data?}.\n\n"
|
| 42 |
"Examples:\n"
|
| 43 |
-
"- list current: action=list, path='
|
| 44 |
-
"- make folder: action=mkdir, path='notes'\n"
|
| 45 |
-
"- write file: action=write, path='notes/todo.txt', content='hello'\n"
|
| 46 |
-
"- read file: action=read, path='notes/todo.txt', max_chars=200\n"
|
| 47 |
-
"- move file: action=move, path='notes/todo.txt', dest_path='notes/todo-old.txt', overwrite=true\n"
|
| 48 |
-
"- delete dir: action=delete, path='notes', recursive=true\n"
|
| 49 |
-
"- search text: action=search, path='notes', content='TODO', recursive=true, max_entries=50\n"
|
| 50 |
"- page search results: action=search, content='TODO', offset=10\n"
|
| 51 |
"- case-sensitive search: action=search, content='TODO', case_sensitive=true\n"
|
| 52 |
)
|
|
@@ -119,16 +120,24 @@ def _resolve_path(path: str) -> tuple[str, str]:
|
|
| 119 |
(unless UNSAFE_ALLOW_ABS_PATHS=1). Returns (abs_path, error_message). error_message is empty when ok.
|
| 120 |
"""
|
| 121 |
try:
|
| 122 |
-
user_input = (path or "
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
if not ALLOW_ABS:
|
| 126 |
# Absolute paths are not allowed in safe mode
|
| 127 |
return "", _err(
|
| 128 |
"absolute_path_disabled",
|
| 129 |
"Absolute paths are disabled in safe mode.",
|
| 130 |
path=raw.replace("\\", "/"),
|
| 131 |
-
hint="Use a path relative to / (e.g., notes/todo.txt)."
|
| 132 |
)
|
| 133 |
abs_path = os.path.abspath(raw)
|
| 134 |
else:
|
|
@@ -499,7 +508,7 @@ def _info(abs_path: str) -> str:
|
|
| 499 |
@autodoc(summary=TOOL_SUMMARY)
|
| 500 |
def File_System(
|
| 501 |
action: Annotated[str, "Operation to perform: 'list', 'read', 'write', 'append', 'mkdir', 'move', 'copy', 'delete', 'info', 'search'."],
|
| 502 |
-
path: Annotated[str, "Target path, relative to root unless UNSAFE_ALLOW_ABS_PATHS=1."] = "
|
| 503 |
content: Annotated[Optional[str], "Content for write/append actions or search query (UTF-8)."] = None,
|
| 504 |
dest_path: Annotated[Optional[str], "Destination for move/copy (relative to root unless unsafe absolute allowed)."] = None,
|
| 505 |
recursive: Annotated[bool, "For list/search (recurse into subfolders) and delete (required for directories)."] = False,
|
|
@@ -610,7 +619,7 @@ def build_interface() -> gr.Interface:
|
|
| 610 |
choices=["list", "read", "write", "append", "mkdir", "move", "copy", "delete", "info", "search", "help"],
|
| 611 |
value="help",
|
| 612 |
),
|
| 613 |
-
gr.Textbox(label="Path", placeholder="
|
| 614 |
gr.Textbox(label="Content (write/append/search)", lines=6, placeholder="Text to write or search for..."),
|
| 615 |
gr.Textbox(label="Destination (for move/copy)", max_lines=1),
|
| 616 |
gr.Checkbox(label="Recursive (list/delete/search)", value=False),
|
|
|
|
| 18 |
"Browse, search, and manage files within a safe root. "
|
| 19 |
"Actions: list, read, write, append, mkdir, move, copy, delete, info, search, help. "
|
| 20 |
"Fill other fields as needed. "
|
| 21 |
+
"Use paths like `/` or `/notes/todo.txt` because all paths are relative to the root (`/`). "
|
| 22 |
"Use 'help' to see action-specific required fields and examples."
|
| 23 |
)
|
| 24 |
|
| 25 |
HELP_TEXT = (
|
| 26 |
"File System — actions and usage\n\n"
|
| 27 |
"Root: paths resolve under Nymbo-Tools/Filesystem by default (or NYMBO_TOOLS_ROOT if set). "
|
| 28 |
+
"Start paths with '/' to refer to the tool root (e.g., /notes). "
|
| 29 |
"Absolute paths are disabled unless UNSAFE_ALLOW_ABS_PATHS=1.\n\n"
|
| 30 |
"Actions and fields:\n"
|
| 31 |
+
"- list: path='/' (default), recursive=false, show_hidden=false, max_entries=20\n"
|
| 32 |
+
"- read: path (e.g., /notes/todo.txt), offset=0, max_chars=4000 (shows next_cursor when truncated)\n"
|
| 33 |
"- write: path, content (UTF-8), create_dirs=true\n"
|
| 34 |
"- append: path, content (UTF-8), create_dirs=true\n"
|
| 35 |
"- mkdir: path (directory), exist_ok=true\n"
|
|
|
|
| 41 |
"- help: show this guide\n\n"
|
| 42 |
"Errors are returned as JSON with fields: {status:'error', code, message, path?, hint?, data?}.\n\n"
|
| 43 |
"Examples:\n"
|
| 44 |
+
"- list current: action=list, path='/'\n"
|
| 45 |
+
"- make folder: action=mkdir, path='/notes'\n"
|
| 46 |
+
"- write file: action=write, path='/notes/todo.txt', content='hello'\n"
|
| 47 |
+
"- read file: action=read, path='/notes/todo.txt', max_chars=200\n"
|
| 48 |
+
"- move file: action=move, path='/notes/todo.txt', dest_path='/notes/todo-old.txt', overwrite=true\n"
|
| 49 |
+
"- delete dir: action=delete, path='/notes', recursive=true\n"
|
| 50 |
+
"- search text: action=search, path='/notes', content='TODO', recursive=true, max_entries=50\n"
|
| 51 |
"- page search results: action=search, content='TODO', offset=10\n"
|
| 52 |
"- case-sensitive search: action=search, content='TODO', case_sensitive=true\n"
|
| 53 |
)
|
|
|
|
| 120 |
(unless UNSAFE_ALLOW_ABS_PATHS=1). Returns (abs_path, error_message). error_message is empty when ok.
|
| 121 |
"""
|
| 122 |
try:
|
| 123 |
+
user_input = (path or "/").strip() or "/"
|
| 124 |
+
if user_input.startswith("/"):
|
| 125 |
+
# Treat leading '/' as the virtual root for the tool.
|
| 126 |
+
rel_part = user_input.lstrip("/") or "."
|
| 127 |
+
raw = os.path.expanduser(rel_part)
|
| 128 |
+
treat_as_relative = True
|
| 129 |
+
else:
|
| 130 |
+
raw = os.path.expanduser(user_input)
|
| 131 |
+
treat_as_relative = False
|
| 132 |
+
|
| 133 |
+
if not treat_as_relative and os.path.isabs(raw):
|
| 134 |
if not ALLOW_ABS:
|
| 135 |
# Absolute paths are not allowed in safe mode
|
| 136 |
return "", _err(
|
| 137 |
"absolute_path_disabled",
|
| 138 |
"Absolute paths are disabled in safe mode.",
|
| 139 |
path=raw.replace("\\", "/"),
|
| 140 |
+
hint="Use a path relative to / (e.g., /notes/todo.txt)."
|
| 141 |
)
|
| 142 |
abs_path = os.path.abspath(raw)
|
| 143 |
else:
|
|
|
|
| 508 |
@autodoc(summary=TOOL_SUMMARY)
|
| 509 |
def File_System(
|
| 510 |
action: Annotated[str, "Operation to perform: 'list', 'read', 'write', 'append', 'mkdir', 'move', 'copy', 'delete', 'info', 'search'."],
|
| 511 |
+
path: Annotated[str, "Target path, relative to root unless UNSAFE_ALLOW_ABS_PATHS=1."] = "/",
|
| 512 |
content: Annotated[Optional[str], "Content for write/append actions or search query (UTF-8)."] = None,
|
| 513 |
dest_path: Annotated[Optional[str], "Destination for move/copy (relative to root unless unsafe absolute allowed)."] = None,
|
| 514 |
recursive: Annotated[bool, "For list/search (recurse into subfolders) and delete (required for directories)."] = False,
|
|
|
|
| 619 |
choices=["list", "read", "write", "append", "mkdir", "move", "copy", "delete", "info", "search", "help"],
|
| 620 |
value="help",
|
| 621 |
),
|
| 622 |
+
gr.Textbox(label="Path", placeholder="/ or /src/file.txt", max_lines=1, value="/"),
|
| 623 |
gr.Textbox(label="Content (write/append/search)", lines=6, placeholder="Text to write or search for..."),
|
| 624 |
gr.Textbox(label="Destination (for move/copy)", max_lines=1),
|
| 625 |
gr.Checkbox(label="Recursive (list/delete/search)", value=False),
|