mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 15:37:55 +08:00
core/tools+config: refuse write_file overwrite unless overwrite=true
This commit is contained in:
@@ -46,6 +46,8 @@ DEFAULT_TOOL_DIRECTIVES = """\
|
||||
### Files
|
||||
- Prefer file tools over shell. `edit_replace` fails usually means a bad match — \
|
||||
fix `old_string` or `max_replaces`; shell workarounds rarely help.
|
||||
- `write_file` refuses to replace an existing file (read it, or change it with \
|
||||
`edit_replace` / `edit_lineno`); a full replacement needs `overwrite=true`, which asks the human.
|
||||
- `edit_replace` defaults to the first match; if remaining matches are reported, \
|
||||
raise `max_replaces` or narrow `old_string`.
|
||||
- `edit_lineno` edits only lines you read via `read_file(path, with_lineno=true)`; \
|
||||
|
||||
@@ -87,7 +87,13 @@ def _command_reason(argv: Sequence[str], *, via: str) -> str | None:
|
||||
|
||||
|
||||
def _write_file_reason(args: Mapping[str, object]) -> str | None:
|
||||
"""Confirm only when write_file would replace an existing file."""
|
||||
"""Confirm only when write_file was asked to replace an existing file.
|
||||
|
||||
An unset/``false`` ``overwrite`` never reaches this prompt: the tool itself
|
||||
refuses an existing file, so there is nothing to ask about.
|
||||
"""
|
||||
if not bool(args.get("overwrite", False)):
|
||||
return None
|
||||
path = args.get("path")
|
||||
if not isinstance(path, str) or not path:
|
||||
return None
|
||||
|
||||
@@ -5,9 +5,15 @@ from plyngent.tools.workspace import AccessMode, resolve_path
|
||||
|
||||
|
||||
@tool(tags=ToolTag.LOCAL | ToolTag.INSTANCE_STATE | ToolTag.YOLO)
|
||||
async def write_file(path: str, content: str) -> str:
|
||||
"""Write text content to a file under the workspace (creates parents)."""
|
||||
async def write_file(path: str, content: str, *, overwrite: bool = False) -> str:
|
||||
"""Write text content to a file under the workspace (creates parents).
|
||||
|
||||
Refuses to replace an existing file: pass ``overwrite=true`` to replace it
|
||||
(the replacement is then confirmed by the human).
|
||||
"""
|
||||
target = resolve_path(path, required=AccessMode.WRITE)
|
||||
if target.is_file() and not overwrite:
|
||||
return f"error: file exists: {path} (set overwrite=true to replace it)"
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
_ = target.write_text(content, encoding="utf-8")
|
||||
# The write changes the file's mtime, so edit_lineno's freshness check
|
||||
|
||||
Reference in New Issue
Block a user