feat: Refactor agent-reach doctor UI with Rich markup for better visualization (#170)
* feat: use rich text formatting for doctor UI * fix: remove unrelated cli formatting changes * fix: keep cli diff focused on doctor rich output --------- Co-authored-by: Yuki9814 <Yuki9814@users.noreply.github.com>
This commit is contained in:
+5
-1
@@ -1293,9 +1293,13 @@ def _cmd_uninstall(args):
|
|||||||
def _cmd_doctor():
|
def _cmd_doctor():
|
||||||
from agent_reach.config import Config
|
from agent_reach.config import Config
|
||||||
from agent_reach.doctor import check_all, format_report
|
from agent_reach.doctor import check_all, format_report
|
||||||
|
try:
|
||||||
|
from rich import print as rprint
|
||||||
|
except ImportError:
|
||||||
|
rprint = print
|
||||||
config = Config()
|
config = Config()
|
||||||
results = check_all(config)
|
results = check_all(config)
|
||||||
print(format_report(results))
|
rprint(format_report(results))
|
||||||
|
|
||||||
|
|
||||||
def _cmd_setup():
|
def _cmd_setup():
|
||||||
|
|||||||
+29
-17
@@ -25,66 +25,78 @@ def check_all(config: Config) -> Dict[str, dict]:
|
|||||||
|
|
||||||
|
|
||||||
def format_report(results: Dict[str, dict]) -> str:
|
def format_report(results: Dict[str, dict]) -> str:
|
||||||
"""Format results as a readable text report."""
|
"""Format results as a readable text report (with Rich markup)."""
|
||||||
|
try:
|
||||||
|
from rich.markup import escape
|
||||||
|
except ImportError:
|
||||||
|
escape = lambda x: x
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
lines.append("Agent Reach 状态")
|
lines.append("[bold cyan]Agent Reach 状态[/bold cyan]")
|
||||||
lines.append("=" * 40)
|
lines.append("[cyan]" + "=" * 40 + "[/cyan]")
|
||||||
|
|
||||||
ok_count = sum(1 for r in results.values() if r["status"] == "ok")
|
ok_count = sum(1 for r in results.values() if r["status"] == "ok")
|
||||||
total = len(results)
|
total = len(results)
|
||||||
|
|
||||||
# Tier 0 — zero config
|
# Tier 0 — zero config
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("✅ 装好即用:")
|
lines.append("[bold]✅ 装好即用:[/bold]")
|
||||||
for key, r in results.items():
|
for key, r in results.items():
|
||||||
if r["tier"] == 0:
|
if r["tier"] == 0:
|
||||||
|
name_msg = f"[bold]{escape(r['name'])}[/bold] — {escape(r['message'])}"
|
||||||
if r["status"] == "ok":
|
if r["status"] == "ok":
|
||||||
lines.append(f" ✅ {r['name']} — {r['message']}")
|
lines.append(f" [green]✅[/green] {name_msg}")
|
||||||
elif r["status"] == "warn":
|
elif r["status"] == "warn":
|
||||||
lines.append(f" [!] {r['name']} — {r['message']}")
|
lines.append(f" [yellow][!][/yellow] {name_msg}")
|
||||||
elif r["status"] in ("off", "error"):
|
elif r["status"] in ("off", "error"):
|
||||||
lines.append(f" [X] {r['name']} — {r['message']}")
|
lines.append(f" [red][X][/red] {name_msg}")
|
||||||
|
|
||||||
# Tier 1 — needs free key
|
# Tier 1 — needs free key
|
||||||
tier1 = {k: r for k, r in results.items() if r["tier"] == 1}
|
tier1 = {k: r for k, r in results.items() if r["tier"] == 1}
|
||||||
if tier1:
|
if tier1:
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("搜索(mcporter 即可解锁):")
|
lines.append("[bold]搜索(mcporter 即可解锁):[/bold]")
|
||||||
for key, r in tier1.items():
|
for key, r in tier1.items():
|
||||||
|
name_msg = f"[bold]{escape(r['name'])}[/bold] — {escape(r['message'])}"
|
||||||
if r["status"] == "ok":
|
if r["status"] == "ok":
|
||||||
lines.append(f" ✅ {r['name']} — {r['message']}")
|
lines.append(f" [green]✅[/green] {name_msg}")
|
||||||
else:
|
else:
|
||||||
lines.append(f" -- {r['name']} — {r['message']}")
|
lines.append(f" [dim]--[/dim] {name_msg}")
|
||||||
|
|
||||||
# Tier 2 — optional setup
|
# Tier 2 — optional setup
|
||||||
tier2 = {k: r for k, r in results.items() if r["tier"] == 2}
|
tier2 = {k: r for k, r in results.items() if r["tier"] == 2}
|
||||||
if tier2:
|
if tier2:
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("配置后可用:")
|
lines.append("[bold]配置后可用:[/bold]")
|
||||||
for key, r in tier2.items():
|
for key, r in tier2.items():
|
||||||
|
name_msg = f"[bold]{escape(r['name'])}[/bold] — {escape(r['message'])}"
|
||||||
if r["status"] == "ok":
|
if r["status"] == "ok":
|
||||||
lines.append(f" ✅ {r['name']} — {r['message']}")
|
lines.append(f" [green]✅[/green] {name_msg}")
|
||||||
elif r["status"] == "warn":
|
elif r["status"] == "warn":
|
||||||
lines.append(f" [!] {r['name']} — {r['message']}")
|
lines.append(f" [yellow][!][/yellow] {name_msg}")
|
||||||
else:
|
else:
|
||||||
lines.append(f" -- {r['name']} — {r['message']}")
|
lines.append(f" [dim]--[/dim] {name_msg}")
|
||||||
|
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append(f"状态:{ok_count}/{total} 个渠道可用")
|
status_color = "green" if ok_count == total else ("yellow" if ok_count > 0 else "red")
|
||||||
|
lines.append(f"状态:[{status_color}]{ok_count}/{total}[/{status_color}] 个渠道可用")
|
||||||
if ok_count < total:
|
if ok_count < total:
|
||||||
lines.append("运行 `agent-reach setup` 解锁更多渠道")
|
lines.append("运行 [cyan]`agent-reach setup`[/cyan] 解锁更多渠道")
|
||||||
|
|
||||||
# Security check: config file permissions (Unix only)
|
# Security check: config file permissions (Unix only)
|
||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
config_path = Config.CONFIG_DIR / "config.yaml"
|
config_path = Config.CONFIG_DIR / "config.yaml"
|
||||||
if config_path.exists() and sys.platform != "win32":
|
if config_path.exists() and sys.platform != "win32":
|
||||||
try:
|
try:
|
||||||
mode = config_path.stat().st_mode
|
mode = config_path.stat().st_mode
|
||||||
if mode & (stat.S_IRGRP | stat.S_IROTH):
|
if mode & (stat.S_IRGRP | stat.S_IROTH):
|
||||||
lines.append("")
|
lines.append("")
|
||||||
lines.append("[!] 安全提示:config.yaml 权限过宽(其他用户可读)")
|
lines.append(
|
||||||
|
"[bold red][!] 安全提示:config.yaml 权限过宽(其他用户可读)[/bold red]"
|
||||||
|
)
|
||||||
lines.append(" 修复:chmod 600 ~/.agent-reach/config.yaml")
|
lines.append(" 修复:chmod 600 ~/.agent-reach/config.yaml")
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user