switch_mode.py
Rama main · réplica de lectura del repositorio original.
"""Umschalten zwischen Dev- und Offizieller Version in Claude Desktop.
Aendert die MCP-Konfiguration in claude_desktop_config.json:
- Dev: Quellcode aus dem Projektordner, .venv-Python
- Offiziell: Installierte Version, system/venv-Python
Plattformunabhaengig: Windows, macOS und Linux.
Nutzung:
python switch_mode.py # Zeigt aktuellen Modus
python switch_mode.py dev # Wechselt auf Dev-Version
python switch_mode.py official # Wechselt auf offizielle Version
"""
import json
import os
import sys
from _setup_claude import eintrag_bauen # liegt neben diesem Skript
# ── Plattform-Pfade ────────────────────────────────────────────
def _claude_config_path():
if sys.platform == "win32":
return os.path.join(os.environ.get("APPDATA", ""), "Claude", "claude_desktop_config.json")
elif sys.platform == "darwin":
return os.path.join(os.path.expanduser("~"), "Library", "Application Support", "Claude", "claude_desktop_config.json")
else:
return os.path.join(os.path.expanduser("~"), ".config", "Claude", "claude_desktop_config.json")
def _data_dir():
if sys.platform == "win32":
return os.path.join(os.environ.get("LOCALAPPDATA", ""), "BewerbungsAssistent")
else:
return os.path.join(os.path.expanduser("~"), ".bewerbungs-assistent")
def _venv_python(base_dir):
if sys.platform == "win32":
return os.path.join(base_dir, ".venv", "Scripts", "python.exe")
else:
return os.path.join(base_dir, ".venv", "bin", "python")
def _installed_python(data_dir):
if sys.platform == "win32":
return os.path.join(data_dir, "python", "Scripts", "python.exe")
else:
return os.path.join(data_dir, "venv", "bin", "python")
# ── Pfade ──────────────────────────────────────────────────────
CONFIG_PATH = _claude_config_path()
PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
MODES = {
"dev": {
"python": _venv_python(PROJECT_DIR),
"src": os.path.join(PROJECT_DIR, "src"),
"data_dir": _data_dir(),
"label": "Dev",
},
"official": {
"python": _installed_python(_data_dir()),
"src": os.path.join(_data_dir(), "src"),
"data_dir": _data_dir(),
"label": "Offiziell",
},
}
MCP_KEY = "bewerbungs-assistent"
# ── Hilfsfunktionen ───────────────────────────────────────────
def load_config():
if not os.path.exists(CONFIG_PATH):
return {"mcpServers": {}}
with open(CONFIG_PATH, "r", encoding="utf-8-sig") as f: # BOM-fest, wie _setup_claude.lese_config
return json.load(f)
def save_config(config):
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True)
with open(CONFIG_PATH, "w", encoding="utf-8") as f:
json.dump(config, f, indent=2, ensure_ascii=False)
def detect_current_mode(config):
"""Erkennt den aktuellen Modus anhand des PYTHONPATH."""
entry = config.get("mcpServers", {}).get(MCP_KEY, {})
pythonpath = entry.get("env", {}).get("PYTHONPATH", "")
if os.path.normcase(pythonpath) == os.path.normcase(MODES["dev"]["src"]):
return "dev"
elif os.path.normcase(pythonpath) == os.path.normcase(MODES["official"]["src"]):
return "official"
return None
def get_version(src_dir):
"""Liest __version__ aus dem Quellcode."""
init = os.path.join(src_dir, "bewerbungs_assistent", "__init__.py")
if not os.path.exists(init):
return "?"
with open(init, "r", encoding="utf-8") as f:
for line in f:
if line.startswith("__version__"):
return line.split("=")[1].strip().strip('"').strip("'")
return "?"
def switch_to(mode_name):
mode = MODES[mode_name]
# Pruefen ob Python existiert
if not os.path.exists(mode["python"]):
print(f"FEHLER: Python nicht gefunden: {mode['python']}")
sys.exit(1)
# Pruefen ob Quellcode existiert
pkg_dir = os.path.join(mode["src"], "bewerbungs_assistent")
if not os.path.isdir(pkg_dir):
print(f"FEHLER: Quellcode nicht gefunden: {pkg_dir}")
sys.exit(1)
config = load_config()
# Eine Regel fuer den Eintrag (#1238): was der Mensch unter env eingetragen hat (API-Schluessel,
# verlegter Datenordner, Port), bleibt; nur PYTHONPATH folgt dem Modus.
server = config.setdefault("mcpServers", {})
server[MCP_KEY] = eintrag_bauen(mode["python"], mode["src"], mode["data_dir"], server.get(MCP_KEY))
save_config(config)
version = get_version(mode["src"])
print(f"Umgeschaltet auf: {mode['label']} (v{version})")
print(f" Python: {mode['python']}")
print(f" Quellcode: {mode['src']}")
print(f" Daten: {mode['data_dir']}")
print()
print("Claude Desktop muss neu gestartet werden, damit die Aenderung wirkt.")
def show_status():
config = load_config()
current = detect_current_mode(config)
print("=== Bewerbungs-Assistent: Modus-Status ===\n")
print(f" Plattform: {sys.platform}")
print(f" Config: {CONFIG_PATH}")
print()
if current:
mode = MODES[current]
version = get_version(mode["src"])
print(f" Aktiver Modus: {mode['label']} (v{version})")
else:
entry = config.get("mcpServers", {}).get(MCP_KEY, {})
pythonpath = entry.get("env", {}).get("PYTHONPATH", "(nicht konfiguriert)")
print(f" Aktiver Modus: Unbekannt")
print(f" PYTHONPATH: {pythonpath}")
print()
for name, mode in MODES.items():
version = get_version(mode["src"])
exists = os.path.exists(mode["python"]) and os.path.isdir(
os.path.join(mode["src"], "bewerbungs_assistent")
)
marker = " <-- aktiv" if name == current else ""
status = "OK" if exists else "FEHLT"
print(f" [{name:9s}] v{version:8s} ({status}){marker}")
print(f" Python: {mode['python']}")
print(f" Source: {mode['src']}")
print()
print("Nutzung: python switch_mode.py [dev|official]")
# ── Main ───────────────────────────────────────────────────────
if __name__ == "__main__":
if len(sys.argv) < 2:
show_status()
elif sys.argv[1] in ("dev", "official"):
switch_to(sys.argv[1])
else:
print(f"Unbekannter Modus: {sys.argv[1]}")
print("Nutzung: python switch_mode.py [dev|official]")
sys.exit(1)