-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtui_launcher.py
More file actions
103 lines (85 loc) · 3.1 KB
/
Copy pathtui_launcher.py
File metadata and controls
103 lines (85 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""Launch the optional Bubble Tea client without breaking the Rich recovery CLI."""
from __future__ import annotations
import os
import shutil
import subprocess
import sys
from pathlib import Path
TUI_RESTART_EXIT_CODE = 75
def _legacy() -> None:
import main
main.main()
def _is_terminal() -> bool:
return bool(getattr(sys.stdin, "isatty", lambda: False)() and
getattr(sys.stdout, "isatty", lambda: False)())
def _tui_binary() -> str | None:
explicit = os.environ.get("KYROZEN_TUI_BINARY", "").strip()
state_bin = Path.home() / ".kyrozen" / "bin"
for name in ("openkyrozen-tui", "openkyrozen-tui.exe"):
target = state_bin / name
pending = target.with_name(target.name + ".next")
if pending.is_file():
try:
os.replace(pending, target)
except OSError:
pass
candidates = [Path(explicit)] if explicit else []
candidates.extend([
state_bin / "openkyrozen-tui",
state_bin / "openkyrozen-tui.exe",
Path(__file__).resolve().parent / "tui" / "openkyrozen-tui",
])
for candidate in candidates:
if candidate.is_file() and os.access(candidate, os.X_OK):
return str(candidate)
return shutil.which("openkyrozen-tui")
def _backend_command() -> tuple[str | None, str | None]:
command = shutil.which("kyrozen-backend")
if command:
return command, None
return None, sys.executable
def main() -> None:
argv = sys.argv[1:]
# These paths are intentionally handled by the legacy entry point: they
# are one-shot commands, not interactive terminal sessions.
if (not _is_terminal() or os.environ.get("KYROZEN_DISABLE_TUI") == "1" or
any(flag in argv for flag in ("--help", "--version", "--init")) or
argv[:1] in (["migrate"], ["learning"])):
_legacy()
return
binary = _tui_binary()
if not binary:
print(
"OpenKyrozen TUI is unavailable; continuing with the Rich recovery interface.",
file=sys.stderr,
)
_legacy()
return
backend, python = _backend_command()
env = os.environ.copy()
env["KYROZEN_EXECUTION_SURFACE"] = "tui"
env.setdefault("KYROZEN_TUI_CAPABILITIES", "full")
if backend:
env["KYROZEN_BACKEND_COMMAND"] = backend
else:
env["KYROZEN_BACKEND_PYTHON"] = python or sys.executable
env["KYROZEN_BACKEND_MODULE"] = "tui_backend"
while True:
try:
completed = subprocess.run([binary, *argv], env=env, check=False)
except OSError as exc:
print(f"OpenKyrozen TUI could not start ({exc}); using Rich fallback.", file=sys.stderr)
_legacy()
return
if completed.returncode == TUI_RESTART_EXIT_CODE:
binary = _tui_binary() or binary
continue
if completed.returncode:
print(
f"OpenKyrozen TUI exited with status {completed.returncode}; using Rich fallback.",
file=sys.stderr,
)
_legacy()
return
if __name__ == "__main__":
main()