fix(error-handling): _handle_file_edit() now respects encoding parameter #8258

Merged
HAL9000 merged 3 commits from fix/7559-file-edit-encoding into master 2026-04-21 09:05:40 +00:00
5 changed files with 59 additions and 2 deletions
+9
View File
@@ -223,6 +223,15 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
prefix check using OS path separators. Added regression test tagged
`@tdd_issue_7558`.
- **File Edit Encoding Parameter** (#7559): `_handle_file_edit()` now correctly
respects the `encoding` parameter when reading and writing files. Previously the
function ignored the caller-supplied encoding and fell back to the platform default,
causing data corruption with non-UTF-8 files. The fix extracts `encoding` from the
tool inputs (defaulting to `"utf-8"`) and passes it to both `path.read_text()` and
`path.write_text()`. The `FILE_EDIT_SPEC` input schema was updated to declare the
`encoding` field. BDD scenarios were added to cover explicit encoding and the
UTF-8 default.
- **Validation Gate Empty-Run Guard** (#7508): Fixed `ApplyValidationSummary.all_required_passed`
returning `True` when zero validations were run, silently bypassing the apply gate. The property
now returns `False` when the validation result set is empty (`is_empty` is `True`), ensuring
+1
View File
@@ -19,3 +19,4 @@ Below are some of the specific details of various contributions.
* HAL 9000 has contributed the plan concurrency race-condition fix (#7989): wired `LockService` into the plan lifecycle, guarding `execute_plan()` and `apply_plan()` with plan-level advisory locks and unique per-invocation owner identities to prevent silent concurrent state corruption.
* This project was made possible thanks to considerable donation of time, money, and resources by CleverThis, Inc.
* HAL 9000 has contributed automated bug fixes, CLI output formatting improvements, and ongoing maintenance as part of the CleverAgents automation system.
* HAL 9000 has contributed the file edit encoding parameter fix (PR #8258 / issue #7559).
+27
View File
@@ -62,6 +62,15 @@ def step_given_file_with_content(context: Any, name: str, content: str) -> None:
path.write_text(content)
@given('an encoded file "{name}" with encoding "{encoding}" and content "{content}"')
def step_given_file_with_content_encoding(
context: Any, name: str, encoding: str, content: str
) -> None:
path = Path(context.sandbox_dir) / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding=encoding)
@given('a file "{name}" with lines "{csv_lines}"')
def step_given_file_with_lines(context: Any, name: str, csv_lines: str) -> None:
lines = csv_lines.split(",")
@@ -149,6 +158,24 @@ def step_when_file_edit(context: Any, old: str, new: str) -> None:
)
@when(
'I edit file "edit-enc.txt" replacing "{old}" with "{new}" specifying encoding "{encoding}"'
)
def step_when_file_edit_with_encoding(
context: Any, old: str, new: str, encoding: str
) -> None:
_run_tool(
context,
"builtin/file-edit",
{
"path": "edit-enc.txt",
"old_text": old,
"new_text": new,
"encoding": encoding,
},
)
@when('I execute the "builtin/file-edit" tool replacing all "{old}" with "{new}"')
def step_when_file_edit_all(context: Any, old: str, new: str) -> None:
_run_tool(
+14
View File
@@ -69,6 +69,20 @@ Feature: Built-in File Tools
Then the tool result should not be successful
And the tool result error should mention "not found"
Scenario: Edit file uses explicit encoding parameter
Given a temporary sandbox directory
And an encoded file "edit-enc.txt" with encoding "latin-1" and content "café"
When I edit file "edit-enc.txt" replacing "café" with "naïve" specifying encoding "latin-1"
Then the tool result should be successful
And the output "replacements" should equal 1
Scenario: Edit file defaults to utf-8 encoding when not specified
Given a temporary sandbox directory
And a file "edit.txt" with content "default encoding test"
When I execute the "builtin/file-edit" tool replacing "default" with "explicit"
Then the tool result should be successful
And the output "replacements" should equal 1
# ---- File Delete ----
Scenario: Delete an existing file
+8 -2
View File
@@ -144,8 +144,9 @@ def _handle_file_edit(inputs: dict[str, Any]) -> dict[str, Any]:
old_text: str = inputs["old_text"]
new_text: str = inputs["new_text"]
replace_all: bool = inputs.get("replace_all", False)
encoding: str = inputs.get("encoding", "utf-8")
content = path.read_text()
content = path.read_text(encoding=encoding)
count = content.count(old_text)
if count == 0:
@@ -157,7 +158,7 @@ def _handle_file_edit(inputs: dict[str, Any]) -> dict[str, Any]:
content = content.replace(old_text, new_text, 1)
count = 1
path.write_text(content)
path.write_text(content, encoding=encoding)
return {
"path": str(path),
@@ -330,6 +331,11 @@ FILE_EDIT_SPEC = ToolSpec(
"default": False,
"description": "Replace all occurrences",
},
"encoding": {
"type": "string",
"default": "utf-8",
"description": "File encoding",
},
},
"required": ["path", "old_text", "new_text"],
},