Files
deepagent/deepagents_sourcecode/libs/deepagents-cli/deepagents_cli/widgets/tool_renderers.py
HyunjunJeon af5fbfabec 문서 추가: Context Engineering 문서 추가 및 deepagents_sourcecode 한국어 번역
- Context_Engineering.md: 에이전트 컨텍스트 엔지니어링 개념 정리 문서 추가
- Context_Engineering_Research.ipynb: 연구 노트북 업데이트
- deepagents_sourcecode/: docstring과 주석을 한국어로 번역
2026-01-11 17:55:52 +09:00

141 lines
4.3 KiB
Python

"""승인(approval) 위젯용 tool renderer들(레지스트리 패턴)입니다."""
from __future__ import annotations
import difflib
from typing import TYPE_CHECKING, Any
from deepagents_cli.widgets.tool_widgets import (
BashApprovalWidget,
EditFileApprovalWidget,
GenericApprovalWidget,
WriteFileApprovalWidget,
)
if TYPE_CHECKING:
from deepagents_cli.widgets.tool_widgets import ToolApprovalWidget
DIFF_HEADER_LINES = 2
class ToolRenderer:
"""tool 승인 위젯 렌더러의 베이스 클래스입니다."""
def get_approval_widget(
self, tool_args: dict[str, Any]
) -> tuple[type[ToolApprovalWidget], dict[str, Any]]:
"""이 tool에 대한 승인 위젯 클래스와 데이터를 반환합니다.
Args:
tool_args: The tool arguments from action_request
Returns:
Tuple of (widget_class, data_dict)
"""
return GenericApprovalWidget, tool_args
class WriteFileRenderer(ToolRenderer):
"""`write_file` tool 렌더러(전체 파일 내용을 표시)."""
def get_approval_widget(
self, tool_args: dict[str, Any]
) -> tuple[type[ToolApprovalWidget], dict[str, Any]]:
"""`write_file` 요청을 표시할 승인 위젯과 데이터를 구성합니다."""
# 문법 하이라이팅을 위해 확장자를 추출
file_path = tool_args.get("file_path", "")
content = tool_args.get("content", "")
# 파일 확장자
file_extension = "text"
if "." in file_path:
file_extension = file_path.rsplit(".", 1)[-1]
data = {
"file_path": file_path,
"content": content,
"file_extension": file_extension,
}
return WriteFileApprovalWidget, data
class EditFileRenderer(ToolRenderer):
"""`edit_file` tool 렌더러(unified diff 표시)."""
def get_approval_widget(
self, tool_args: dict[str, Any]
) -> tuple[type[ToolApprovalWidget], dict[str, Any]]:
"""`edit_file` 요청을 unified diff 형태로 표시할 승인 위젯/데이터를 구성합니다."""
file_path = tool_args.get("file_path", "")
old_string = tool_args.get("old_string", "")
new_string = tool_args.get("new_string", "")
# unified diff 생성
diff_lines = self._generate_diff(old_string, new_string)
data = {
"file_path": file_path,
"diff_lines": diff_lines,
"old_string": old_string,
"new_string": new_string,
}
return EditFileApprovalWidget, data
def _generate_diff(self, old_string: str, new_string: str) -> list[str]:
"""old/new 문자열로부터 unified diff 라인을 생성합니다."""
if not old_string and not new_string:
return []
old_lines = old_string.split("\n") if old_string else []
new_lines = new_string.split("\n") if new_string else []
# unified diff 생성
diff = difflib.unified_diff(
old_lines,
new_lines,
fromfile="before",
tofile="after",
lineterm="",
n=3, # Context lines
)
# 헤더 라인(---, +++)은 제외
diff_list = list(diff)
return diff_list[DIFF_HEADER_LINES:] if len(diff_list) > DIFF_HEADER_LINES else diff_list
class BashRenderer(ToolRenderer):
"""`bash`/`shell` tool 렌더러(커맨드 표시)."""
def get_approval_widget(
self, tool_args: dict[str, Any]
) -> tuple[type[ToolApprovalWidget], dict[str, Any]]:
"""`bash`/`shell` 요청을 표시할 승인 위젯/데이터를 구성합니다."""
data = {
"command": tool_args.get("command", ""),
"description": tool_args.get("description", ""),
}
return BashApprovalWidget, data
# tool 이름 → renderer 매핑 레지스트리
_RENDERER_REGISTRY: dict[str, type[ToolRenderer]] = {
"write_file": WriteFileRenderer,
"edit_file": EditFileRenderer,
"bash": BashRenderer,
"shell": BashRenderer,
}
def get_renderer(tool_name: str) -> ToolRenderer:
"""도구 이름에 맞는 renderer를 반환합니다.
Args:
tool_name: The name of the tool
Returns:
The appropriate ToolRenderer instance
"""
renderer_class = _RENDERER_REGISTRY.get(tool_name, ToolRenderer)
return renderer_class()