From 4ab3c3b00a9404178a2dbb5a4648fbef096d6ef8 Mon Sep 17 00:00:00 2001 From: the_og Date: Tue, 7 Jul 2026 20:51:26 -0400 Subject: [PATCH] Fix: rebuild from clean main (previous push included unrelated contaminated content) --- bcc_core.py | 152 ++-------------------------------------------------- 1 file changed, 5 insertions(+), 147 deletions(-) diff --git a/bcc_core.py b/bcc_core.py index fb2410d..909df23 100644 --- a/bcc_core.py +++ b/bcc_core.py @@ -29,7 +29,6 @@ import threading import time from dataclasses import dataclass from pathlib import Path -from typing import NamedTuple from urllib.parse import urlparse CONFIG_FILENAME = "claude_desktop_config.json" @@ -135,16 +134,6 @@ def profile_from_path(path: str | os.PathLike) -> Profile: label = p.parent.name or p.name return Profile(label=label, path=p, config_exists=p.is_file()) -def profile_targets_claude_desktop(profile: Profile) -> bool: - """ - True when `profile` points at a Claude Desktop config - (claude_desktop_config.json), as opposed to Claude Code (~/.claude.json - or the legacy ~/.claude/settings.json). Used to gate Desktop-only actions - like "Restart Claude Desktop" so they never show up for a Claude Code - profile — restarting the CLI makes no sense. - """ - return Path(profile.path).name == CONFIG_FILENAME - # --------------------------------------------------------------------------- # # Load / extract / apply @@ -410,30 +399,6 @@ def config_mtime(path: Path | str) -> float | None: return None -class ConfigStat(NamedTuple): - """A snapshot of a config file's mtime + size. - - Pairing size with mtime hardens stale-file detection beyond bare mtime - equality: a concurrent external write can land within the filesystem's - mtime resolution (e.g. same-second writes on ext4/HFS+) or have its mtime - restored by the writing process, in which case mtime alone would miss the - change. Comparing both fields catches those cases without the cost of a - full content hash. - """ - - mtime: float - size: int - - -def config_fingerprint(path: Path | str) -> ConfigStat | None: - """Return the file's (mtime, size) snapshot, or None if it does not exist.""" - try: - st = Path(path).stat() - except OSError: - return None - return ConfigStat(st.st_mtime, st.st_size) - - def external_change_summary(original_cfg: dict, path: Path | str) -> tuple[list[str], str]: """ Compare original_cfg (what BCC loaded) with the current on-disk state. @@ -500,13 +465,13 @@ def suggest_name(data: dict) -> str: # Word-processor / web artifacts mapped back to ASCII. _QUOTE_MAP = { - "“": '"', - "”": '"', + """: '"', + """: '"', "„": '"', "«": '"', "»": '"', - "‘": "'", - "’": "'", + "'": "'", + "'": "'", "‚": "'", } _JUNK_CHARS = "​‌‍" # zero-width chars / BOM @@ -528,7 +493,7 @@ def _normalize_unicode(text: str, notes: list[str]) -> str: out = text for junk in _JUNK_CHARS: out = out.replace(junk, "") - out = out.replace(" ", " ") # non-breaking space + out = out.replace(" ", " ") # non-breaking space for smart, ascii_q in _QUOTE_MAP.items(): out = out.replace(smart, ascii_q) if out != text: @@ -1324,25 +1289,6 @@ def diagnostics_text(name: str, data: dict) -> str: return "\n".join(L) -def server_log_path(name: str) -> Path | None: - """ - The platform-specific Claude Desktop MCP server log file for `name`, or - None if it doesn't exist yet (nothing has been logged for this server). - - macOS : ~/Library/Logs/Claude/mcp-server-.log (one file per server) - Windows: %APPDATA%\\Claude\\logs\\mcp.log (one shared file) - Other platforms: Claude Desktop doesn't ship a log in a known location -> None. - """ - if sys.platform == "darwin": - p = Path.home() / "Library" / "Logs" / "Claude" / f"mcp-server-{name}.log" - elif os.name == "nt": - appdata = Path(os.environ.get("APPDATA", Path.home() / "AppData" / "Roaming")) - p = appdata / "Claude" / "logs" / "mcp.log" - else: - return None - return p if p.is_file() else None - - _STDERR_CAP = 4096 # bytes @@ -1532,91 +1478,3 @@ def pin_command_path(data: dict, path: str | None = None) -> tuple[dict, str | N out["args"] = args return out, f"'{c}' → {resolved}" return data, None - - -# --------------------------------------------------------------------------- # -# Restart Claude Desktop (issue #9) -# -# Scoped strictly to Claude DESKTOP, the GUI app -- never Claude Code (the -# CLI), which has no long-running process to bounce. Callers should gate this -# behind profile_targets_claude_desktop() before offering it in the UI. -# --------------------------------------------------------------------------- # -class RestartResult(NamedTuple): - """Outcome of a restart_claude_desktop() attempt.""" - - success: bool - detail: str - - -def _run_quiet(cmd: list[str]) -> None: - """Best-effort fire-and-forget command. Never raises: a nonzero exit (e.g. - pkill finding nothing to kill) is expected and not an error.""" - with contextlib.suppress(OSError): - subprocess.run(cmd, capture_output=True) - - -def _restart_claude_desktop_macos() -> RestartResult: - _run_quiet(["pkill", "-x", "Claude"]) - try: - result = subprocess.run(["open", "-a", "Claude"], capture_output=True, text=True) - except OSError as e: - return RestartResult(False, f"Couldn't launch Claude Desktop: {e}") - if result.returncode != 0: - detail = (result.stderr or result.stdout or "").strip() or "'open -a Claude' failed" - return RestartResult(False, detail) - return RestartResult(True, "Claude Desktop restarted.") - - -def _claude_windows_start_menu_shortcut() -> Path: - appdata = os.environ.get("APPDATA", str(Path.home())) - return Path(appdata) / "Microsoft" / "Windows" / "Start Menu" / "Programs" / "Claude.lnk" - - -def _restart_claude_desktop_windows() -> RestartResult: - _run_quiet(["taskkill", "/IM", "Claude.exe", "/F"]) - shortcut = _claude_windows_start_menu_shortcut() - try: - # `cmd /c start "" ` launches detached, the same as double-clicking - # the Start-menu shortcut, and returns immediately. - result = subprocess.run( - ["cmd", "/c", "start", "", str(shortcut)], capture_output=True, text=True - ) - except OSError as e: - return RestartResult(False, f"Couldn't launch Claude Desktop: {e}") - if result.returncode != 0: - detail = ( - result.stderr or result.stdout or "" - ).strip() or "failed to relaunch Claude Desktop" - return RestartResult(False, detail) - return RestartResult(True, "Claude Desktop restarted.") - - -def _restart_claude_desktop_linux() -> RestartResult: - _run_quiet(["pkill", "claude"]) - try: - # The Linux launcher is the app itself (no "open"-style helper), so it - # has to be started detached rather than waited on. - subprocess.Popen( - ["claude"], - stdin=subprocess.DEVNULL, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - start_new_session=True, - ) - except OSError as e: - return RestartResult(False, f"Couldn't launch Claude Desktop: {e}") - return RestartResult(True, "Claude Desktop restarted.") - - -def restart_claude_desktop() -> RestartResult: - """ - Kill and relaunch the Claude Desktop app so a freshly saved config takes - effect. The app not currently running is NOT a failure -- pkill/taskkill - exiting non-zero just means "nothing to kill", and we go straight to - relaunching. Only a failed relaunch is reported as success=False. - """ - if sys.platform == "darwin": - return _restart_claude_desktop_macos() - if sys.platform.startswith("win"): - return _restart_claude_desktop_windows() - return _restart_claude_desktop_linux()