Files
deepagent/deepagents_sourcecode/libs/deepagents-cli/deepagents_cli/ui.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

246 lines
9.2 KiB
Python

"""CLI UI 렌더링/표시 관련 유틸리티입니다.
UI rendering and display utilities for the CLI.
"""
import json
from contextlib import suppress
from pathlib import Path
from .config import COLORS, DEEP_AGENTS_ASCII, MAX_ARG_LENGTH, console
def truncate_value(value: str, max_length: int = MAX_ARG_LENGTH) -> str:
"""Truncate a string value if it exceeds max_length."""
if len(value) > max_length:
return value[:max_length] + "..."
return value
def format_tool_display(tool_name: str, tool_args: dict) -> str: # noqa: PLR0911, PLR0912, PLR0915
"""Format tool calls for display with tool-specific smart formatting.
Shows the most relevant information for each tool type rather than all arguments.
Args:
tool_name: Name of the tool being called
tool_args: Dictionary of tool arguments
Returns:
Formatted string for display (e.g., "read_file(config.py)")
Examples:
read_file(path="/long/path/file.py") → "read_file(file.py)"
web_search(query="how to code", max_results=5) → 'web_search("how to code")'
shell(command="pip install foo") → 'shell("pip install foo")'
"""
def abbreviate_path(path_str: str, max_length: int = 60) -> str:
"""Abbreviate a file path intelligently - show basename or relative path."""
path = Path(path_str)
# If it's just a filename (no directory parts), return as-is
if len(path.parts) == 1:
return path_str
# Try to get relative path from current working directory
try:
cwd = Path.cwd()
except OSError:
cwd = None
if cwd is not None:
with suppress(ValueError):
rel_path = path.relative_to(cwd)
rel_str = str(rel_path)
# Use relative if it's shorter and not too long
if len(rel_str) < len(path_str) and len(rel_str) <= max_length:
return rel_str
# If absolute path is reasonable length, use it
if len(path_str) <= max_length:
return path_str
# Otherwise, just show basename (filename only)
return path.name
# Tool-specific formatting - show the most important argument(s)
if tool_name in ("read_file", "write_file", "edit_file"):
# File operations: show the primary file path argument (file_path or path)
path_value = tool_args.get("file_path")
if path_value is None:
path_value = tool_args.get("path")
if path_value is not None:
path = abbreviate_path(str(path_value))
return f"{tool_name}({path})"
elif tool_name == "web_search":
# Web search: show the query string
if "query" in tool_args:
query = str(tool_args["query"])
query = truncate_value(query, 100)
return f'{tool_name}("{query}")'
elif tool_name == "grep":
# Grep: show the search pattern
if "pattern" in tool_args:
pattern = str(tool_args["pattern"])
pattern = truncate_value(pattern, 70)
return f'{tool_name}("{pattern}")'
elif tool_name == "shell":
# Shell: show the command being executed
if "command" in tool_args:
command = str(tool_args["command"])
command = truncate_value(command, 120)
return f'{tool_name}("{command}")'
elif tool_name == "ls":
# ls: show directory, or empty if current directory
if tool_args.get("path"):
path = abbreviate_path(str(tool_args["path"]))
return f"{tool_name}({path})"
return f"{tool_name}()"
elif tool_name == "glob":
# Glob: show the pattern
if "pattern" in tool_args:
pattern = str(tool_args["pattern"])
pattern = truncate_value(pattern, 80)
return f'{tool_name}("{pattern}")'
elif tool_name == "http_request":
# HTTP: show method and URL
parts = []
if "method" in tool_args:
parts.append(str(tool_args["method"]).upper())
if "url" in tool_args:
url = str(tool_args["url"])
url = truncate_value(url, 80)
parts.append(url)
if parts:
return f"{tool_name}({' '.join(parts)})"
elif tool_name == "fetch_url":
# Fetch URL: show the URL being fetched
if "url" in tool_args:
url = str(tool_args["url"])
url = truncate_value(url, 80)
return f'{tool_name}("{url}")'
elif tool_name == "task":
# Task: show the task description
if "description" in tool_args:
desc = str(tool_args["description"])
desc = truncate_value(desc, 100)
return f'{tool_name}("{desc}")'
elif tool_name == "write_todos":
# Todos: show count of items
if "todos" in tool_args and isinstance(tool_args["todos"], list):
count = len(tool_args["todos"])
return f"{tool_name}({count} items)"
# Fallback: generic formatting for unknown tools
# Show all arguments in key=value format
args_str = ", ".join(f"{k}={truncate_value(str(v), 50)}" for k, v in tool_args.items())
return f"{tool_name}({args_str})"
def format_tool_message_content(content: object) -> str:
"""Convert ToolMessage content into a printable string."""
if content is None:
return ""
if isinstance(content, list):
parts = []
for item in content:
if isinstance(item, str):
parts.append(item)
else:
try:
parts.append(json.dumps(item))
except (TypeError, ValueError):
parts.append(str(item))
return "\n".join(parts)
return str(content)
def show_help() -> None:
"""Show help information."""
console.print()
console.print(DEEP_AGENTS_ASCII, style=f"bold {COLORS['primary']}")
console.print()
console.print("[bold]Usage:[/bold]", style=COLORS["primary"])
console.print(" deepagents [OPTIONS] Start interactive session")
console.print(" deepagents list List all available agents")
console.print(" deepagents reset --agent AGENT Reset agent to default prompt")
console.print(
" deepagents reset --agent AGENT --target SOURCE Reset agent to copy of another agent"
)
console.print(" deepagents help Show this help message")
console.print()
console.print("[bold]Options:[/bold]", style=COLORS["primary"])
console.print(" --agent NAME Agent identifier (default: agent)")
console.print(
" --model MODEL Model to use (e.g., claude-sonnet-4-5-20250929, gpt-4o)"
)
console.print(" --auto-approve Auto-approve tool usage without prompting")
console.print(
" --sandbox TYPE Remote sandbox for execution (modal, runloop, daytona)"
)
console.print(" --sandbox-id ID Reuse existing sandbox (skips creation/cleanup)")
console.print(
" -r, --resume [ID] Resume thread: -r for most recent, -r <ID> for specific"
)
console.print()
console.print("[bold]Examples:[/bold]", style=COLORS["primary"])
console.print(
" deepagents # Start with default agent", style=COLORS["dim"]
)
console.print(
" deepagents --agent mybot # Start with agent named 'mybot'",
style=COLORS["dim"],
)
console.print(
" deepagents --model gpt-4o # Use specific model (auto-detects provider)",
style=COLORS["dim"],
)
console.print(
" deepagents -r # Resume most recent session",
style=COLORS["dim"],
)
console.print(
" deepagents -r abc123 # Resume specific thread",
style=COLORS["dim"],
)
console.print(
" deepagents --auto-approve # Start with auto-approve enabled",
style=COLORS["dim"],
)
console.print(
" deepagents --sandbox runloop # Execute code in Runloop sandbox",
style=COLORS["dim"],
)
console.print()
console.print("[bold]Thread Management:[/bold]", style=COLORS["primary"])
console.print(
" deepagents threads list # List all sessions", style=COLORS["dim"]
)
console.print(
" deepagents threads delete <ID> # Delete a session", style=COLORS["dim"]
)
console.print()
console.print("[bold]Interactive Features:[/bold]", style=COLORS["primary"])
console.print(" Enter Submit your message", style=COLORS["dim"])
console.print(" Ctrl+J Insert newline", style=COLORS["dim"])
console.print(" Shift+Tab Toggle auto-approve mode", style=COLORS["dim"])
console.print(" @filename Auto-complete files and inject content", style=COLORS["dim"])
console.print(" /command Slash commands (/help, /clear, /quit)", style=COLORS["dim"])
console.print(" !command Run bash commands directly", style=COLORS["dim"])
console.print()