From 8ba30d4b3dac19bde49f339b93bfa4ca5eeb4db3 Mon Sep 17 00:00:00 2001 From: aimidi Date: Sun, 19 Apr 2026 01:10:19 +0800 Subject: [PATCH] fix: align lldb docs and repl skin --- README.md | 6 +- .../cli_anything/lldb/utils/repl_skin.py | 120 +++++++++--------- 2 files changed, 61 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 0cf444a50..3d19bd474 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ CLI-Anything: Bridging the Gap Between AI Agents and the World's SoftwareQuick Start CLI Hub Demos - Tests + Tests License

@@ -587,7 +587,7 @@ AI agents are great at reasoning but terrible at using real professional softwar | 💸 "UI automation breaks constantly" | No screenshots, no clicking, no RPA fragility. Pure command-line reliability with structured interfaces | | 📊 "Agents need structured data" | Built-in JSON output for seamless agent consumption + human-readable formats for debugging | | 🔧 "Custom integrations are expensive" | One Claude plugin auto-generates CLIs for ANY codebase through proven 7-phase pipeline | -| ⚡ "Prototype vs Production gap" | 2,159+ tests with real software validation. Battle-tested across 31 major applications | +| ⚡ "Prototype vs Production gap" | 2,173+ tests with real software validation. Battle-tested across 31 major applications | --- @@ -1339,7 +1339,7 @@ MIT License — free to use, modify, and distribute. **CLI-Anything** — *Make any software with a codebase Agent-native.* -A methodology for the age of AI agents | 31 professional software demos | 2,159 passing tests +A methodology for the age of AI agents | 31 professional software demos | 2,173 passing tests
diff --git a/lldb/agent-harness/cli_anything/lldb/utils/repl_skin.py b/lldb/agent-harness/cli_anything/lldb/utils/repl_skin.py index 201ff6414..c7312348a 100644 --- a/lldb/agent-harness/cli_anything/lldb/utils/repl_skin.py +++ b/lldb/agent-harness/cli_anything/lldb/utils/repl_skin.py @@ -30,7 +30,7 @@ _ITALIC = "\033[3m" _UNDERLINE = "\033[4m" # Brand colors -_CYAN = "\033[38;5;80m" # cli-anything brand cyan +_CYAN = "\033[38;5;80m" # cli-anything brand cyan _CYAN_BG = "\033[48;5;80m" _WHITE = "\033[97m" _GRAY = "\033[38;5;245m" @@ -39,16 +39,16 @@ _LIGHT_GRAY = "\033[38;5;250m" # Software accent colors — each software gets a unique accent _ACCENT_COLORS = { - "gimp": "\033[38;5;214m", # warm orange - "blender": "\033[38;5;208m", # deep orange - "inkscape": "\033[38;5;39m", # bright blue - "audacity": "\033[38;5;33m", # navy blue - "libreoffice": "\033[38;5;40m", # green - "obs_studio": "\033[38;5;55m", # purple - "kdenlive": "\033[38;5;69m", # slate blue - "shotcut": "\033[38;5;35m", # teal green + "gimp": "\033[38;5;214m", # warm orange + "blender": "\033[38;5;208m", # deep orange + "inkscape": "\033[38;5;39m", # bright blue + "audacity": "\033[38;5;33m", # navy blue + "libreoffice": "\033[38;5;40m", # green + "obs_studio": "\033[38;5;55m", # purple + "kdenlive": "\033[38;5;69m", # slate blue + "shotcut": "\033[38;5;35m", # teal green } -_DEFAULT_ACCENT = "\033[38;5;75m" # default sky blue +_DEFAULT_ACCENT = "\033[38;5;75m" # default sky blue # Status colors _GREEN = "\033[38;5;78m" @@ -81,7 +81,6 @@ _CROSS = "┼" def _strip_ansi(text: str) -> str: """Remove ANSI escape codes for length calculation.""" import re - return re.sub(r"\033\[[^m]*m", "", text) @@ -97,7 +96,8 @@ class ReplSkin: across all CLI harnesses built with the cli-anything methodology. """ - def __init__(self, software: str, version: str = "1.0.0", history_file: str | None = None, skill_path: str | None = None): + def __init__(self, software: str, version: str = "1.0.0", + history_file: str | None = None, skill_path: str | None = None): """Initialize the REPL skin. Args: @@ -118,7 +118,6 @@ class ReplSkin: # cli_anything//skills/SKILL.md (target) if skill_path is None: from pathlib import Path - _auto = Path(__file__).resolve().parent.parent / "skills" / "SKILL.md" if _auto.is_file(): skill_path = str(_auto) @@ -128,7 +127,6 @@ class ReplSkin: # History file if history_file is None: from pathlib import Path - hist_dir = Path.home() / f".cli-anything-{self.software}" hist_dir.mkdir(parents=True, exist_ok=True) self.history_file = str(hist_dir / "history") @@ -200,7 +198,8 @@ class ReplSkin: # ── Prompt ──────────────────────────────────────────────────────── - def prompt(self, project_name: str = "", modified: bool = False, context: str = "") -> str: + def prompt(self, project_name: str = "", modified: bool = False, + context: str = "") -> str: """Build a styled prompt string for prompt_toolkit or input(). Args: @@ -234,7 +233,8 @@ class ReplSkin: return "".join(parts) - def prompt_tokens(self, project_name: str = "", modified: bool = False, context: str = ""): + def prompt_tokens(self, project_name: str = "", modified: bool = False, + context: str = ""): """Build prompt_toolkit formatted text tokens for the prompt. Use with prompt_toolkit's FormattedText for proper ANSI handling. @@ -272,25 +272,23 @@ class ReplSkin: accent_hex = _ANSI_256_TO_HEX.get(self.accent, "#5fafff") - return Style.from_dict( - { - "icon": "#5fdfdf bold", # cyan brand color - "software": f"{accent_hex} bold", - "bracket": "#585858", - "context": "#bcbcbc", - "arrow": "#808080", - # Completion menu - "completion-menu.completion": "bg:#303030 #bcbcbc", - "completion-menu.completion.current": f"bg:{accent_hex} #000000", - "completion-menu.meta.completion": "bg:#303030 #808080", - "completion-menu.meta.completion.current": f"bg:{accent_hex} #000000", - # Auto-suggest - "auto-suggest": "#585858", - # Bottom toolbar - "bottom-toolbar": "bg:#1c1c1c #808080", - "bottom-toolbar.text": "#808080", - } - ) + return Style.from_dict({ + "icon": "#5fdfdf bold", # cyan brand color + "software": f"{accent_hex} bold", + "bracket": "#585858", + "context": "#bcbcbc", + "arrow": "#808080", + # Completion menu + "completion-menu.completion": "bg:#303030 #bcbcbc", + "completion-menu.completion.current": f"bg:{accent_hex} #000000", + "completion-menu.meta.completion": "bg:#303030 #808080", + "completion-menu.meta.completion.current": f"bg:{accent_hex} #000000", + # Auto-suggest + "auto-suggest": "#585858", + # Bottom toolbar + "bottom-toolbar": "bg:#1c1c1c #808080", + "bottom-toolbar.text": "#808080", + }) # ── Messages ────────────────────────────────────────────────────── @@ -367,7 +365,8 @@ class ReplSkin: # ── Table display ───────────────────────────────────────────────── - def table(self, headers: list[str], rows: list[list[str]], max_col_width: int = 40): + def table(self, headers: list[str], rows: list[list[str]], + max_col_width: int = 40): """Print a formatted table with box-drawing characters. Args: @@ -383,19 +382,25 @@ class ReplSkin: for row in rows: for i, cell in enumerate(row): if i < len(col_widths): - col_widths[i] = min(max(col_widths[i], len(str(cell))), max_col_width) + col_widths[i] = min( + max(col_widths[i], len(str(cell))), max_col_width + ) def pad(text: str, width: int) -> str: t = str(text)[:width] return t + " " * (width - len(t)) # Header - header_cells = [self._c(_CYAN + _BOLD, pad(h, col_widths[i])) for i, h in enumerate(headers)] + header_cells = [ + self._c(_CYAN + _BOLD, pad(h, col_widths[i])) + for i, h in enumerate(headers) + ] sep = self._c(_DARK_GRAY, f" {_V_LINE} ") header_line = f" {sep.join(header_cells)}" print(header_line) # Separator + sep_parts = [self._c(_DARK_GRAY, _H_LINE * w) for w in col_widths] sep_line = self._c(_DARK_GRAY, f" {'───'.join([_H_LINE * w for w in col_widths])}") print(sep_line) @@ -438,18 +443,11 @@ class ReplSkin: Returns: A configured PromptSession, or None if prompt_toolkit unavailable. """ - # prompt_toolkit's Windows console backend requires a real TTY/console - # handle. When the CLI is driven by subprocess pipes for tests or agent - # automation, fall back to plain input() instead of crashing. - if not getattr(sys.stdin, "isatty", lambda: False)(): - return None - if not getattr(sys.stdout, "isatty", lambda: False)(): - return None - try: from prompt_toolkit import PromptSession - from prompt_toolkit.auto_suggest import AutoSuggestFromHistory from prompt_toolkit.history import FileHistory + from prompt_toolkit.auto_suggest import AutoSuggestFromHistory + from prompt_toolkit.formatted_text import FormattedText style = self.get_prompt_style() @@ -463,7 +461,8 @@ class ReplSkin: except ImportError: return None - def get_input(self, pt_session, project_name: str = "", modified: bool = False, context: str = "") -> str: + def get_input(self, pt_session, project_name: str = "", + modified: bool = False, context: str = "") -> str: """Get input from user using prompt_toolkit or fallback. Args: @@ -477,11 +476,11 @@ class ReplSkin: """ if pt_session is not None: from prompt_toolkit.formatted_text import FormattedText - tokens = self.prompt_tokens(project_name, modified, context) return pt_session.prompt(FormattedText(tokens)).strip() - raw_prompt = self.prompt(project_name, modified, context) - return input(raw_prompt).strip() + else: + raw_prompt = self.prompt(project_name, modified, context) + return input(raw_prompt).strip() # ── Toolbar builder ─────────────────────────────────────────────── @@ -494,10 +493,8 @@ class ReplSkin: Returns: A callable that returns FormattedText for the toolbar. """ - def toolbar(): from prompt_toolkit.formatted_text import FormattedText - parts = [] for i, (k, v) in enumerate(items.items()): if i > 0: @@ -505,21 +502,20 @@ class ReplSkin: parts.append(("class:bottom-toolbar.text", f" {k}: ")) parts.append(("class:bottom-toolbar", v)) return FormattedText(parts) - return toolbar # ── ANSI 256-color to hex mapping (for prompt_toolkit styles) ───────── _ANSI_256_TO_HEX = { - "\033[38;5;33m": "#0087ff", # audacity navy blue - "\033[38;5;35m": "#00af5f", # shotcut teal - "\033[38;5;39m": "#00afff", # inkscape bright blue - "\033[38;5;40m": "#00d700", # libreoffice green - "\033[38;5;55m": "#5f00af", # obs purple - "\033[38;5;69m": "#5f87ff", # kdenlive slate blue - "\033[38;5;75m": "#5fafff", # default sky blue - "\033[38;5;80m": "#5fd7d7", # brand cyan + "\033[38;5;33m": "#0087ff", # audacity navy blue + "\033[38;5;35m": "#00af5f", # shotcut teal + "\033[38;5;39m": "#00afff", # inkscape bright blue + "\033[38;5;40m": "#00d700", # libreoffice green + "\033[38;5;55m": "#5f00af", # obs purple + "\033[38;5;69m": "#5f87ff", # kdenlive slate blue + "\033[38;5;75m": "#5fafff", # default sky blue + "\033[38;5;80m": "#5fd7d7", # brand cyan "\033[38;5;208m": "#ff8700", # blender deep orange "\033[38;5;214m": "#ffaf00", # gimp warm orange }