63 lines
2.1 KiB
Python
63 lines
2.1 KiB
Python
# SPDX-FileCopyrightText: 2026 Art Sea LLC
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
|
|
|
if TYPE_CHECKING:
|
|
from band_aider.judgement.edit_request import AiderEditRequest
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class EditorRecord:
|
|
"""Keep one applied block verbatim; ``record.render()`` presents neutral history."""
|
|
|
|
summary: str
|
|
search: str
|
|
replace: str
|
|
|
|
def render(self) -> str:
|
|
"""Quote historical text without emitting executable editor control markers."""
|
|
|
|
tokens = ("<<<<<<< SEARCH", "=======", ">>>>>>> REPLACE", "FILE:",
|
|
"SUMMARY:", "NO_PATCH:", "[CODE_EDIT_OR_LEAVE_IT:LEAVE_IT]", "== BEGIN ", "== END ")
|
|
sections: list[str] = []
|
|
# Keep the stored payload exact while making protocol-shaped history inert in prompts.
|
|
for label, content in (("Summary", self.summary), ("Before", self.search), ("After", self.replace)):
|
|
# Escape the first character so even markers embedded in source cannot become control.
|
|
for token in tokens:
|
|
content = content.replace(token, f"\\u{ord(token[0]):04x}" + token[1:])
|
|
sections.append(f"{label}:\n{content}")
|
|
return "\n\n".join(sections)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class CodeEditorResult:
|
|
"""Return edit effects and retained history; callers read ``result.records``."""
|
|
|
|
changed_paths: list[Path]
|
|
summary: str
|
|
records: list[EditorRecord]
|
|
|
|
|
|
@runtime_checkable
|
|
class CodeEditor(Protocol):
|
|
"""Apply a bounded request; ``editor.edit(request)`` returns its effects and history."""
|
|
|
|
@property
|
|
def inner(self) -> "CodeEditor | None":
|
|
"""Return the wrapped editor for decorators, or None for concrete editors."""
|
|
|
|
def edit(
|
|
self,
|
|
request: AiderEditRequest,
|
|
logger: logging.Logger | None = None,
|
|
) -> CodeEditorResult:
|
|
"""Apply one edit request and return changed paths, summary, and retained records."""
|
|
|
|
...
|