refactor: redesign finished dialogs and UI elements

This commit is contained in:
0xallam
2026-01-19 16:42:38 -08:00
committed by Ahmed Allam
parent 9f7b532056
commit a67fe4c45c
10 changed files with 154 additions and 174 deletions

View File

@@ -36,7 +36,7 @@ Screen {
}
#sidebar {
width: 25%;
width: 20%;
background: transparent;
margin-left: 1;
}
@@ -174,7 +174,7 @@ VulnerabilityDetailScreen {
}
#chat_area_container {
width: 75%;
width: 80%;
background: transparent;
}

View File

@@ -24,30 +24,26 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
console = Console()
start_text = Text()
start_text.append("🦉 ", style="bold white")
start_text.append("STRIX CYBERSECURITY AGENT", style="bold green")
start_text.append("Penetration test initiated", style="bold #22c55e")
target_text = Text()
target_text.append("Target", style="dim")
target_text.append(" ")
if len(args.targets_info) == 1:
target_text.append("🎯 Target: ", style="bold cyan")
target_text.append(args.targets_info[0]["original"], style="bold white")
else:
target_text.append("🎯 Targets: ", style="bold cyan")
target_text.append(f"{len(args.targets_info)} targets\n", style="bold white")
for i, target_info in enumerate(args.targets_info):
target_text.append("", style="dim white")
target_text.append(f"{len(args.targets_info)} targets", style="bold white")
for target_info in args.targets_info:
target_text.append("\n ")
target_text.append(target_info["original"], style="white")
if i < len(args.targets_info) - 1:
target_text.append("\n")
results_text = Text()
results_text.append("📊 Results will be saved to: ", style="bold cyan")
results_text.append(f"strix_runs/{args.run_name}", style="bold white")
results_text.append("Output", style="dim")
results_text.append(" ")
results_text.append(f"strix_runs/{args.run_name}", style="#60a5fa")
note_text = Text()
note_text.append("\n\n", style="dim")
note_text.append("⏱️ ", style="dim")
note_text.append("This may take a while depending on target complexity. ", style="dim")
note_text.append("Vulnerabilities will be displayed in real-time.", style="dim")
startup_panel = Panel(
@@ -59,9 +55,9 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
results_text,
note_text,
),
title="[bold green]🛡️ STRIX PENETRATION TEST INITIATED",
title_align="center",
border_style="green",
title="[bold white]STRIX",
title_align="left",
border_style="#22c55e",
padding=(1, 2),
)
@@ -126,8 +122,7 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
def create_live_status() -> Panel:
status_text = Text()
status_text.append("🦉 ", style="bold white")
status_text.append("Running penetration test...", style="bold #22c55e")
status_text.append("Penetration test in progress", style="bold #22c55e")
status_text.append("\n\n")
stats_text = build_live_stats_text(tracer, agent_config)
@@ -136,8 +131,8 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
return Panel(
status_text,
title="[bold #22c55e]🔍 Live Penetration Test Status",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="#22c55e",
padding=(1, 2),
)
@@ -169,7 +164,7 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
error_msg = result.get("error", "Unknown error")
error_details = result.get("details")
console.print()
console.print(f"[bold red]Penetration test failed:[/] {error_msg}")
console.print(f"[bold red]Penetration test failed:[/] {error_msg}")
if error_details:
console.print(f"[dim]{error_details}[/]")
console.print()
@@ -186,8 +181,7 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
console.print()
final_report_text = Text()
final_report_text.append("📄 ", style="bold cyan")
final_report_text.append("FINAL PENETRATION TEST REPORT", style="bold cyan")
final_report_text.append("Penetration test summary", style="bold #60a5fa")
final_report_panel = Panel(
Text.assemble(
@@ -195,9 +189,9 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
"\n\n",
tracer.final_scan_result,
),
title="[bold cyan]📊 PENETRATION TEST SUMMARY",
title_align="center",
border_style="cyan",
title="[bold white]STRIX",
title_align="left",
border_style="#60a5fa",
padding=(1, 2),
)

View File

@@ -76,7 +76,6 @@ def validate_environment() -> None: # noqa: PLR0912, PLR0915
if missing_required_vars:
error_text = Text()
error_text.append("", style="bold red")
error_text.append("MISSING REQUIRED ENVIRONMENT VARIABLES", style="bold red")
error_text.append("\n\n", style="white")
@@ -163,8 +162,8 @@ def validate_environment() -> None: # noqa: PLR0912, PLR0915
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX CONFIGURATION ERROR",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)
@@ -179,7 +178,6 @@ def check_docker_installed() -> None:
if shutil.which("docker") is None:
console = Console()
error_text = Text()
error_text.append("", style="bold red")
error_text.append("DOCKER NOT INSTALLED", style="bold red")
error_text.append("\n\n", style="white")
error_text.append("The 'docker' CLI was not found in your PATH.\n", style="white")
@@ -189,8 +187,8 @@ def check_docker_installed() -> None:
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX STARTUP ERROR",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)
@@ -234,7 +232,6 @@ async def warm_up_llm() -> None:
except Exception as e: # noqa: BLE001
error_text = Text()
error_text.append("", style="bold red")
error_text.append("LLM CONNECTION FAILED", style="bold red")
error_text.append("\n\n", style="white")
error_text.append("Could not establish connection to the language model.\n", style="white")
@@ -243,8 +240,8 @@ async def warm_up_llm() -> None:
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX STARTUP ERROR",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)
@@ -410,30 +407,22 @@ def display_completion_message(args: argparse.Namespace, results_path: Path) ->
completion_text = Text()
if scan_completed:
completion_text.append("🦉 ", style="bold white")
completion_text.append("AGENT FINISHED", style="bold green")
completion_text.append("", style="dim white")
completion_text.append("Penetration test completed", style="white")
completion_text.append("Penetration test completed", style="bold #22c55e")
else:
completion_text.append("🦉 ", style="bold white")
completion_text.append("SESSION ENDED", style="bold yellow")
completion_text.append("", style="dim white")
completion_text.append("Penetration test interrupted by user", style="white")
stats_text = build_final_stats_text(tracer)
completion_text.append("SESSION ENDED", style="bold #eab308")
target_text = Text()
target_text.append("Target", style="dim")
target_text.append(" ")
if len(args.targets_info) == 1:
target_text.append("🎯 Target: ", style="bold cyan")
target_text.append(args.targets_info[0]["original"], style="bold white")
else:
target_text.append("🎯 Targets: ", style="bold cyan")
target_text.append(f"{len(args.targets_info)} targets\n", style="bold white")
for i, target_info in enumerate(args.targets_info):
target_text.append("", style="dim white")
target_text.append(f"{len(args.targets_info)} targets", style="bold white")
for target_info in args.targets_info:
target_text.append("\n ")
target_text.append(target_info["original"], style="white")
if i < len(args.targets_info) - 1:
target_text.append("\n")
stats_text = build_final_stats_text(tracer)
panel_parts = [completion_text, "\n\n", target_text]
@@ -442,18 +431,20 @@ def display_completion_message(args: argparse.Namespace, results_path: Path) ->
if scan_completed or has_vulnerabilities:
results_text = Text()
results_text.append("📊 Results Saved To: ", style="bold cyan")
results_text.append(str(results_path), style="bold yellow")
panel_parts.extend(["\n\n", results_text])
results_text.append("\n")
results_text.append("Output", style="dim")
results_text.append(" ")
results_text.append(str(results_path), style="#60a5fa")
panel_parts.extend(["\n", results_text])
panel_content = Text.assemble(*panel_parts)
border_style = "green" if scan_completed else "yellow"
border_style = "#22c55e" if scan_completed else "#eab308"
panel = Panel(
panel_content,
title="[bold green]🛡️ STRIX CYBERSECURITY AGENT",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style=border_style,
padding=(1, 2),
)
@@ -461,8 +452,7 @@ def display_completion_message(args: argparse.Namespace, results_path: Path) ->
console.print("\n")
console.print(panel)
console.print()
console.print("[dim]🌐 Website:[/] [cyan]https://strix.ai[/]")
console.print("[dim]💬 Discord:[/] [cyan]https://discord.gg/YjKFvEZSdZ[/]")
console.print("[#60a5fa]strix.ai[/] [dim]·[/] [#60a5fa]discord.gg/YjKFvEZSdZ[/]")
console.print()
@@ -474,7 +464,7 @@ def pull_docker_image() -> None:
return
console.print()
console.print(f"[bold cyan]🐳 Pulling Docker image:[/] {Config.get('strix_image')}")
console.print(f"[dim]Pulling image[/] {Config.get('strix_image')}")
console.print("[dim yellow]This only happens on first run and may take a few minutes...[/]")
console.print()
@@ -489,7 +479,6 @@ def pull_docker_image() -> None:
except DockerException as e:
console.print()
error_text = Text()
error_text.append("", style="bold red")
error_text.append("FAILED TO PULL IMAGE", style="bold red")
error_text.append("\n\n", style="white")
error_text.append(f"Could not download: {Config.get('strix_image')}\n", style="white")
@@ -497,8 +486,8 @@ def pull_docker_image() -> None:
panel = Panel(
error_text,
title="[bold red]🛡️ DOCKER PULL ERROR",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)
@@ -506,8 +495,7 @@ def pull_docker_image() -> None:
sys.exit(1)
success_text = Text()
success_text.append("", style="bold green")
success_text.append("Successfully pulled Docker image", style="green")
success_text.append("Docker image ready", style="#22c55e")
console.print(success_text)
console.print()

View File

@@ -92,12 +92,13 @@ class AgentFinishRenderer(BaseToolRenderer):
success = args.get("success", True)
text = Text()
text.append("🏁 ")
if success:
text.append("Agent completed", style="bold #fbbf24")
text.append("", style="#22c55e")
text.append("Agent completed", style="bold #22c55e")
else:
text.append("Agent failed", style="bold #fbbf24")
text.append("", style="#ef4444")
text.append("Agent failed", style="bold #ef4444")
if result_summary:
text.append("\n ")

View File

@@ -65,16 +65,16 @@ class StrReplaceEditorRenderer(BaseToolRenderer):
text = Text()
icons_and_labels = {
"view": ("📖 ", "Reading file", "#10b981"),
"str_replace": ("✏️ ", "Editing file", "#10b981"),
"create": ("📝 ", "Creating file", "#10b981"),
"insert": ("✏️ ", "Inserting text", "#10b981"),
"undo_edit": ("↩️ ", "Undoing edit", "#10b981"),
"view": (" ", "read", "#10b981"),
"str_replace": (" ", "edit", "#10b981"),
"create": (" ", "create", "#10b981"),
"insert": (" ", "insert", "#10b981"),
"undo_edit": (" ", "undo", "#10b981"),
}
icon, label, color = icons_and_labels.get(command, ("📄 ", "File operation", "#10b981"))
text.append(icon)
text.append(label, style=f"bold {color}")
icon, label, color = icons_and_labels.get(command, (" ", "file", "#10b981"))
text.append(icon, style=color)
text.append(label, style="dim")
if path:
path_display = path[-60:] if len(path) > 60 else path
@@ -158,23 +158,20 @@ class SearchFilesRenderer(BaseToolRenderer):
regex = args.get("regex", "")
text = Text()
text.append("🔍 ")
text.append("Searching files", style="bold purple")
text.append(" ")
text.append("", style="#a855f7")
text.append("search", style="dim")
text.append(" ")
if path and regex:
text.append(path, style="dim")
text.append(" for '", style="dim")
text.append(regex, style="dim")
text.append("'", style="dim")
text.append(" ", style="dim")
text.append(regex, style="#a855f7")
elif path:
text.append(path, style="dim")
elif regex:
text.append("'", style="dim")
text.append(regex, style="dim")
text.append("'", style="dim")
text.append(regex, style="#a855f7")
else:
text.append("Searching...", style="dim")
text.append("...", style="dim")
css_classes = cls.get_css_classes("completed")
return Static(text, classes=css_classes)

View File

@@ -27,8 +27,8 @@ class FinishScanRenderer(BaseToolRenderer):
recommendations = args.get("recommendations", "")
text = Text()
text.append("🏁 ")
text.append("Finishing Scan", style="bold #dc2626")
text.append("", style="#22c55e")
text.append("Penetration test completed", style="bold #22c55e")
if executive_summary:
text.append("\n\n")

View File

@@ -21,8 +21,8 @@ class CreateNoteRenderer(BaseToolRenderer):
category = args.get("category", "general")
text = Text()
text.append("📝 ")
text.append("Note", style="bold #fbbf24")
text.append("", style="#fbbf24")
text.append("note", style="dim")
text.append(" ")
text.append(f"({category})", style="dim")
@@ -50,8 +50,8 @@ class DeleteNoteRenderer(BaseToolRenderer):
@classmethod
def render(cls, tool_data: dict[str, Any]) -> Static: # noqa: ARG003
text = Text()
text.append("📝 ")
text.append("Note Removed", style="bold #94a3b8")
text.append("", style="#fbbf24")
text.append("note removed", style="dim")
css_classes = cls.get_css_classes("completed")
return Static(text, classes=css_classes)
@@ -70,8 +70,8 @@ class UpdateNoteRenderer(BaseToolRenderer):
content = args.get("content")
text = Text()
text.append("📝 ")
text.append("Note Updated", style="bold #fbbf24")
text.append("", style="#fbbf24")
text.append("note updated", style="dim")
if title:
text.append("\n ")
@@ -99,8 +99,8 @@ class ListNotesRenderer(BaseToolRenderer):
result = tool_data.get("result")
text = Text()
text.append("📝 ")
text.append("Notes", style="bold #fbbf24")
text.append("", style="#fbbf24")
text.append("notes", style="dim")
if isinstance(result, str) and result.strip():
text.append("\n ")

View File

@@ -19,7 +19,8 @@ class ScanStartInfoRenderer(BaseToolRenderer):
targets = args.get("targets", [])
text = Text()
text.append("🚀 Starting penetration test")
text.append("", style="#22c55e")
text.append("Starting penetration test")
if len(targets) == 1:
text.append(" on ")

View File

@@ -192,7 +192,7 @@ class SplashScreen(Static): # type: ignore[misc]
class HelpScreen(ModalScreen): # type: ignore[misc]
def compose(self) -> ComposeResult:
yield Grid(
Label("🦉 Strix Help", id="help_title"),
Label("Strix Help", id="help_title"),
Label(
"F1 Help\nCtrl+Q/C Quit\nESC Stop Agent\n"
"Enter Send message to agent\nTab Switch panels\n↑/↓ Navigate tree",
@@ -668,7 +668,7 @@ class QuitScreen(ModalScreen): # type: ignore[misc]
class StrixTUIApp(App): # type: ignore[misc]
CSS_PATH = "assets/tui_styles.tcss"
SIDEBAR_MIN_WIDTH = 100
SIDEBAR_MIN_WIDTH = 140
selected_agent_id: reactive[str | None] = reactive(default=None)
show_splash: reactive[bool] = reactive(default=True)
@@ -795,7 +795,7 @@ class StrixTUIApp(App): # type: ignore[misc]
chat_input.set_app_reference(self)
chat_input_container = Horizontal(chat_prompt, chat_input, id="chat_input_container")
agents_tree = Tree("🤖 Active Agents", id="agents_tree")
agents_tree = Tree("Agents", id="agents_tree")
agents_tree.root.expand()
agents_tree.show_root = False
@@ -911,16 +911,16 @@ class StrixTUIApp(App): # type: ignore[misc]
status = agent_data.get("status", "running")
status_indicators = {
"running": "🟢",
"waiting": "⏸️",
"completed": "",
"failed": "",
"stopped": "⏹️",
"stopping": "⏸️",
"llm_failed": "🔴",
"running": "",
"waiting": "",
"completed": "",
"failed": "",
"stopped": "",
"stopping": "",
"llm_failed": "",
}
status_icon = status_indicators.get(status, "🔵")
status_icon = status_indicators.get(status, "")
vuln_count = self._agent_vulnerability_count(agent_id)
vuln_indicator = f" ({vuln_count})" if vuln_count > 0 else ""
agent_name = f"{status_icon} {agent_name_raw}{vuln_indicator}"
@@ -1466,15 +1466,15 @@ class StrixTUIApp(App): # type: ignore[misc]
agent_name_raw = agent_data.get("name", "Agent")
status_indicators = {
"running": "🟢",
"waiting": "🟡",
"completed": "",
"failed": "",
"stopped": "⏹️",
"stopping": "⏸️",
"running": "",
"waiting": "",
"completed": "",
"failed": "",
"stopped": "",
"stopping": "",
}
status_icon = status_indicators.get(status, "🔵")
status_icon = status_indicators.get(status, "")
vuln_count = self._agent_vulnerability_count(agent_id)
vuln_indicator = f" ({vuln_count})" if vuln_count > 0 else ""
agent_name = f"{status_icon} {agent_name_raw}{vuln_indicator}"
@@ -1540,15 +1540,15 @@ class StrixTUIApp(App): # type: ignore[misc]
status = agent_data.get("status", "running")
status_indicators = {
"running": "🟢",
"waiting": "🟡",
"completed": "",
"failed": "",
"stopped": "⏹️",
"stopping": "⏸️",
"running": "",
"waiting": "",
"completed": "",
"failed": "",
"stopped": "",
"stopping": "",
}
status_icon = status_indicators.get(status, "🔵")
status_icon = status_indicators.get(status, "")
vuln_count = self._agent_vulnerability_count(agent_id)
vuln_indicator = f" ({vuln_count})" if vuln_count > 0 else ""
agent_name = f"{status_icon} {agent_name_raw}{vuln_indicator}"

View File

@@ -208,7 +208,7 @@ def _build_vulnerability_stats(stats_text: Text, tracer: Any) -> None:
if severity in severity_counts:
severity_counts[severity] += 1
stats_text.append("🔍 Vulnerabilities Found: ", style="bold red")
stats_text.append("Vulnerabilities ", style="bold red")
severity_parts = []
for severity in ["critical", "high", "medium", "low", "info"]:
@@ -230,7 +230,7 @@ def _build_vulnerability_stats(stats_text: Text, tracer: Any) -> None:
stats_text.append(")", style="dim white")
stats_text.append("\n")
else:
stats_text.append("🔍 Vulnerabilities Found: ", style="bold green")
stats_text.append("Vulnerabilities ", style="bold #22c55e")
stats_text.append("0", style="bold white")
stats_text.append(" (No exploitable vulnerabilities detected)", style="dim green")
stats_text.append("\n")
@@ -240,29 +240,29 @@ def _build_llm_stats(stats_text: Text, total_stats: dict[str, Any]) -> None:
"""Build LLM usage section of stats text."""
if total_stats["requests"] > 0:
stats_text.append("\n")
stats_text.append("📥 Input Tokens: ", style="bold cyan")
stats_text.append(format_token_count(total_stats["input_tokens"]), style="bold white")
stats_text.append("Input Tokens ", style="dim")
stats_text.append(format_token_count(total_stats["input_tokens"]), style="white")
if total_stats["cached_tokens"] > 0:
stats_text.append(" ", style="dim white")
stats_text.append("Cached Tokens: ", style="bold green")
stats_text.append(format_token_count(total_stats["cached_tokens"]), style="bold white")
stats_text.append(" · ", style="dim white")
stats_text.append("Cached Tokens ", style="dim")
stats_text.append(format_token_count(total_stats["cached_tokens"]), style="#22c55e")
stats_text.append(" ", style="dim white")
stats_text.append("📤 Output Tokens: ", style="bold cyan")
stats_text.append(format_token_count(total_stats["output_tokens"]), style="bold white")
stats_text.append(" · ", style="dim white")
stats_text.append("Output Tokens ", style="dim")
stats_text.append(format_token_count(total_stats["output_tokens"]), style="white")
if total_stats["cost"] > 0:
stats_text.append(" ", style="dim white")
stats_text.append("💰 Total Cost: ", style="bold cyan")
stats_text.append(f"${total_stats['cost']:.4f}", style="bold yellow")
stats_text.append(" · ", style="dim white")
stats_text.append("Cost ", style="dim")
stats_text.append(f"${total_stats['cost']:.4f}", style="bold #fbbf24")
else:
stats_text.append("\n")
stats_text.append("💰 Total Cost: ", style="bold cyan")
stats_text.append("$0.0000 ", style="bold yellow")
stats_text.append(" ", style="bold white")
stats_text.append("📊 Tokens: ", style="bold cyan")
stats_text.append("0", style="bold white")
stats_text.append("Cost ", style="dim")
stats_text.append("$0.0000 ", style="#fbbf24")
stats_text.append("· ", style="dim white")
stats_text.append("Tokens ", style="dim")
stats_text.append("0", style="white")
def build_final_stats_text(tracer: Any) -> Text:
@@ -276,10 +276,12 @@ def build_final_stats_text(tracer: Any) -> Text:
tool_count = tracer.get_real_tool_count()
agent_count = len(tracer.agents)
stats_text.append("🤖 Agents Used: ", style="bold cyan")
stats_text.append("Agents", style="dim")
stats_text.append(" ")
stats_text.append(str(agent_count), style="bold white")
stats_text.append(" ", style="dim white")
stats_text.append("🛠️ Tools Called: ", style="bold cyan")
stats_text.append(" · ", style="dim white")
stats_text.append("Tools", style="dim")
stats_text.append(" ")
stats_text.append(str(tool_count), style="bold white")
llm_stats = tracer.get_total_llm_stats()
@@ -296,15 +298,16 @@ def build_live_stats_text(tracer: Any, agent_config: dict[str, Any] | None = Non
if agent_config:
llm_config = agent_config["llm_config"]
model = getattr(llm_config, "model_name", "Unknown")
stats_text.append(f"🧠 Model: {model}")
stats_text.append("Model ", style="dim")
stats_text.append(model, style="white")
stats_text.append("\n")
vuln_count = len(tracer.vulnerability_reports)
tool_count = tracer.get_real_tool_count()
agent_count = len(tracer.agents)
stats_text.append("🔍 Vulnerabilities: ", style="bold white")
stats_text.append(f"{vuln_count}", style="dim white")
stats_text.append("Vulnerabilities ", style="dim")
stats_text.append(f"{vuln_count}", style="white")
stats_text.append("\n")
if vuln_count > 0:
severity_counts = {"critical": 0, "high": 0, "medium": 0, "low": 0, "info": 0}
@@ -330,33 +333,32 @@ def build_live_stats_text(tracer: Any, agent_config: dict[str, Any] | None = Non
stats_text.append("\n")
stats_text.append("🤖 Agents: ", style="bold white")
stats_text.append(str(agent_count), style="dim white")
stats_text.append(" ", style="dim white")
stats_text.append("🛠️ Tools: ", style="bold white")
stats_text.append(str(tool_count), style="dim white")
stats_text.append("Agents ", style="dim")
stats_text.append(str(agent_count), style="white")
stats_text.append(" · ", style="dim white")
stats_text.append("Tools ", style="dim")
stats_text.append(str(tool_count), style="white")
llm_stats = tracer.get_total_llm_stats()
total_stats = llm_stats["total"]
stats_text.append("\n")
stats_text.append("📥 Input: ", style="bold white")
stats_text.append(format_token_count(total_stats["input_tokens"]), style="dim white")
stats_text.append("Input Tokens ", style="dim")
stats_text.append(format_token_count(total_stats["input_tokens"]), style="white")
stats_text.append(" ", style="dim white")
stats_text.append(" ", style="bold white")
stats_text.append("Cached: ", style="bold white")
stats_text.append(format_token_count(total_stats["cached_tokens"]), style="dim white")
stats_text.append(" · ", style="dim white")
stats_text.append("Cached Tokens ", style="dim")
stats_text.append(format_token_count(total_stats["cached_tokens"]), style="#22c55e")
stats_text.append("\n")
stats_text.append("📤 Output: ", style="bold white")
stats_text.append(format_token_count(total_stats["output_tokens"]), style="dim white")
stats_text.append("Output Tokens ", style="dim")
stats_text.append(format_token_count(total_stats["output_tokens"]), style="white")
stats_text.append(" ", style="dim white")
stats_text.append("💰 Cost: ", style="bold white")
stats_text.append(f"${total_stats['cost']:.4f}", style="dim white")
stats_text.append(" · ", style="dim white")
stats_text.append("Cost ", style="dim")
stats_text.append(f"${total_stats['cost']:.4f}", style="#fbbf24")
return stats_text
@@ -668,7 +670,6 @@ def clone_repository(repo_url: str, run_name: str, dest_name: str | None = None)
except subprocess.CalledProcessError as e:
error_text = Text()
error_text.append("", style="bold red")
error_text.append("REPOSITORY CLONE FAILED", style="bold red")
error_text.append("\n\n", style="white")
error_text.append(f"Could not clone repository: {repo_url}\n", style="white")
@@ -678,8 +679,8 @@ def clone_repository(repo_url: str, run_name: str, dest_name: str | None = None)
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX CLONE ERROR",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)
@@ -689,7 +690,6 @@ def clone_repository(repo_url: str, run_name: str, dest_name: str | None = None)
sys.exit(1)
except FileNotFoundError:
error_text = Text()
error_text.append("", style="bold red")
error_text.append("GIT NOT FOUND", style="bold red")
error_text.append("\n\n", style="white")
error_text.append("Git is not installed or not available in PATH.\n", style="white")
@@ -697,8 +697,8 @@ def clone_repository(repo_url: str, run_name: str, dest_name: str | None = None)
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX CLONE ERROR",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)
@@ -715,7 +715,6 @@ def check_docker_connection() -> Any:
except DockerException:
console = Console()
error_text = Text()
error_text.append("", style="bold red")
error_text.append("DOCKER NOT AVAILABLE", style="bold red")
error_text.append("\n\n", style="white")
error_text.append("Cannot connect to Docker daemon.\n", style="white")
@@ -726,8 +725,8 @@ def check_docker_connection() -> Any:
panel = Panel(
error_text,
title="[bold red]🛡️ STRIX STARTUP ERROR",
title_align="center",
title="[bold white]STRIX",
title_align="left",
border_style="red",
padding=(1, 2),
)