fix(error-handling): _handle_file_edit() now respects encoding parameter #8258
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user