dayhoff-tools 1.9.1__py3-none-any.whl → 1.9.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dayhoff_tools/cli/engine_commands.py +82 -35
- {dayhoff_tools-1.9.1.dist-info → dayhoff_tools-1.9.3.dist-info}/METADATA +1 -1
- {dayhoff_tools-1.9.1.dist-info → dayhoff_tools-1.9.3.dist-info}/RECORD +5 -5
- {dayhoff_tools-1.9.1.dist-info → dayhoff_tools-1.9.3.dist-info}/WHEEL +0 -0
- {dayhoff_tools-1.9.1.dist-info → dayhoff_tools-1.9.3.dist-info}/entry_points.txt +0 -0
@@ -319,9 +319,6 @@ def format_status(state: str, ready: Optional[bool]) -> str:
|
|
319
319
|
return state
|
320
320
|
|
321
321
|
|
322
|
-
|
323
|
-
|
324
|
-
|
325
322
|
def resolve_engine(name_or_id: str, engines: List[Dict]) -> Dict:
|
326
323
|
"""Resolve engine by name or ID with interactive selection."""
|
327
324
|
# Exact ID match
|
@@ -776,23 +773,22 @@ def engine_status(
|
|
776
773
|
run_disp = engine["state"].capitalize()
|
777
774
|
|
778
775
|
# Compose Active/Idle header with extra detail when idle
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
# show Idle <elapsed>/<threshold> if available; else just N/A for stopped states
|
776
|
+
def _compute_active_disp(idle_info: Dict[str, Any]) -> str:
|
777
|
+
if idle_info.get("status") == "active":
|
778
|
+
return "[green]Active[/green]"
|
783
779
|
if running_state in ("stopped", "stopping"):
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
780
|
+
return "[dim]N/A[/dim]"
|
781
|
+
idle_seconds_v = idle_info.get("idle_seconds")
|
782
|
+
thresh_v = idle_info.get("idle_threshold")
|
783
|
+
if isinstance(idle_seconds_v, (int, float)) and isinstance(
|
784
|
+
thresh_v, (int, float)
|
785
|
+
):
|
786
|
+
return (
|
787
|
+
f"[yellow]Idle {int(idle_seconds_v)//60}m/{int(thresh_v)//60}m[/yellow]"
|
788
|
+
)
|
789
|
+
return "[yellow]Idle[/yellow]"
|
790
|
+
|
791
|
+
active_disp = _compute_active_disp(idle_detector)
|
796
792
|
|
797
793
|
top_lines = [
|
798
794
|
f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n",
|
@@ -927,23 +923,55 @@ def engine_status(
|
|
927
923
|
if not content:
|
928
924
|
return None
|
929
925
|
data = json.loads(content)
|
930
|
-
# Convert last_state schema to idle_detector schema used by CLI output
|
926
|
+
# Convert last_state schema (new or old) to idle_detector schema used by CLI output
|
931
927
|
idle_info: Dict[str, Any] = {"available": True}
|
932
|
-
|
933
|
-
#
|
928
|
+
|
929
|
+
# Active/idle
|
930
|
+
idle_flag = bool(data.get("idle", False))
|
931
|
+
idle_info["status"] = "idle" if idle_flag else "active"
|
932
|
+
|
933
|
+
# Threshold and elapsed
|
934
934
|
if isinstance(data.get("timeout_sec"), (int, float)):
|
935
935
|
idle_info["idle_threshold"] = int(data["timeout_sec"]) # seconds
|
936
|
-
|
936
|
+
if isinstance(data.get("idle_seconds"), (int, float)):
|
937
|
+
idle_info["idle_seconds"] = int(data["idle_seconds"])
|
938
|
+
|
939
|
+
# Keep raw reasons for sensor display when available (new schema)
|
937
940
|
if isinstance(data.get("reasons"), list):
|
938
941
|
idle_info["_reasons_raw"] = data["reasons"]
|
939
|
-
|
940
|
-
|
942
|
+
else:
|
943
|
+
# Fallback: synthesize reasons from the old forensics layout
|
944
|
+
f_all = data.get("forensics", {}) or {}
|
945
|
+
synthesized = []
|
946
|
+
|
947
|
+
def _mk(sensor_name: str, key: str):
|
948
|
+
entry = f_all.get(key, {}) or {}
|
949
|
+
synthesized.append(
|
950
|
+
{
|
951
|
+
"sensor": sensor_name,
|
952
|
+
"active": bool(entry.get("active", False)),
|
953
|
+
"reason": entry.get("reason", ""),
|
954
|
+
"forensic": entry.get("forensic", {}),
|
955
|
+
}
|
956
|
+
)
|
957
|
+
|
958
|
+
_mk("CoffeeLockSensor", "coffee")
|
959
|
+
_mk("ActiveLoginSensor", "ssh")
|
960
|
+
_mk("IDEConnectionSensor", "ide")
|
961
|
+
_mk("DockerWorkloadSensor", "docker")
|
962
|
+
idle_info["_reasons_raw"] = synthesized
|
963
|
+
|
964
|
+
# Derive details from sensors
|
965
|
+
for r in idle_info.get("_reasons_raw", []):
|
941
966
|
if not r.get("active"):
|
942
967
|
continue
|
943
968
|
sensor = (r.get("sensor") or "").lower()
|
944
969
|
forensic = r.get("forensic") or {}
|
945
970
|
if sensor == "ideconnectionsensor":
|
946
|
-
|
971
|
+
# Prefer unique_pid_count written by new detector
|
972
|
+
cnt = forensic.get("unique_pid_count")
|
973
|
+
if not isinstance(cnt, int):
|
974
|
+
cnt = forensic.get("matches")
|
947
975
|
if isinstance(cnt, int):
|
948
976
|
idle_info["ide_connections"] = {"connection_count": cnt}
|
949
977
|
else:
|
@@ -955,12 +983,11 @@ def engine_status(
|
|
955
983
|
timedelta(seconds=int(rem))
|
956
984
|
)
|
957
985
|
elif sensor == "activeloginsensor":
|
958
|
-
# Provide a single summarized SSH session if available
|
959
986
|
sess = {
|
960
|
-
"tty":
|
961
|
-
"pid":
|
962
|
-
"idle_time":
|
963
|
-
"from_ip":
|
987
|
+
"tty": forensic.get("tty", "pts/?"),
|
988
|
+
"pid": forensic.get("pid", "?"),
|
989
|
+
"idle_time": forensic.get("idle_sec", 0),
|
990
|
+
"from_ip": forensic.get("remote_addr", "unknown"),
|
964
991
|
}
|
965
992
|
idle_info.setdefault("ssh_sessions", []).append(sess)
|
966
993
|
return idle_info
|
@@ -977,6 +1004,13 @@ def engine_status(
|
|
977
1004
|
for k, v in overlay.items():
|
978
1005
|
idle_detector.setdefault(k, v)
|
979
1006
|
|
1007
|
+
# Recompute header display using enriched overlay values
|
1008
|
+
try:
|
1009
|
+
active_disp = _compute_active_disp(idle_detector)
|
1010
|
+
top_lines[0] = f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n"
|
1011
|
+
except Exception:
|
1012
|
+
pass
|
1013
|
+
|
980
1014
|
# Activity Sensors (show all with YES/no)
|
981
1015
|
if idle_detector.get("available"):
|
982
1016
|
status_lines.append("")
|
@@ -1002,7 +1036,23 @@ def engine_status(
|
|
1002
1036
|
status_lines.append(_sensor_line(" IDE ", "IDEConnectionSensor", "🖥"))
|
1003
1037
|
status_lines.append(_sensor_line("Docker", "DockerWorkloadSensor", "🐳"))
|
1004
1038
|
|
1005
|
-
|
1039
|
+
# If we have elapsed idle seconds and threshold, reflect that in the header
|
1040
|
+
try:
|
1041
|
+
if idle_detector.get("status") == "idle":
|
1042
|
+
idle_secs = int(idle_detector.get("idle_seconds", 0))
|
1043
|
+
thresh_secs = int(idle_detector.get("idle_threshold", 0))
|
1044
|
+
if thresh_secs > 0:
|
1045
|
+
active_disp = (
|
1046
|
+
f"[yellow]Idle {idle_secs//60}m/{thresh_secs//60}m[/yellow]"
|
1047
|
+
)
|
1048
|
+
# Rewrite top header line (index 0) to include updated display
|
1049
|
+
all_header = top_lines[0]
|
1050
|
+
# Replace the portion after two spaces (name and running state fixed)
|
1051
|
+
top_lines[0] = (
|
1052
|
+
f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n"
|
1053
|
+
)
|
1054
|
+
except Exception:
|
1055
|
+
pass
|
1006
1056
|
|
1007
1057
|
# Combine top summary and details
|
1008
1058
|
all_lines = top_lines + status_lines
|
@@ -1041,9 +1091,6 @@ def engine_status(
|
|
1041
1091
|
console.print(f"[red]❌ Error fetching log: {e}[/red]")
|
1042
1092
|
|
1043
1093
|
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
1094
|
@engine_app.command("stop")
|
1048
1095
|
def stop_engine(
|
1049
1096
|
name_or_id: str = typer.Argument(help="Engine name or instance ID"),
|
@@ -3,7 +3,7 @@ dayhoff_tools/chemistry/standardizer.py,sha256=uMn7VwHnx02nc404eO6fRuS4rsl4dvSPf
|
|
3
3
|
dayhoff_tools/chemistry/utils.py,sha256=jt-7JgF-GeeVC421acX-bobKbLU_X94KNOW24p_P-_M,2257
|
4
4
|
dayhoff_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
dayhoff_tools/cli/cloud_commands.py,sha256=33qcWLmq-FwEXMdL3F0OHm-5Stlh2r65CldyEZgQ1no,40904
|
6
|
-
dayhoff_tools/cli/engine_commands.py,sha256=
|
6
|
+
dayhoff_tools/cli/engine_commands.py,sha256=uq09BZJ4XEV6lOay2Zz2rylTU8AAAIzxeTDbKzNX-r4,107098
|
7
7
|
dayhoff_tools/cli/main.py,sha256=LoFs3SI4fdCjP4pdxEAhri-_q0dmNYupmBCRE4KbBac,5933
|
8
8
|
dayhoff_tools/cli/swarm_commands.py,sha256=5EyKj8yietvT5lfoz8Zx0iQvVaNgc3SJX1z2zQR6o6M,5614
|
9
9
|
dayhoff_tools/cli/utility_commands.py,sha256=WQTHOh1MttuxaJjl2c6zMa4x7_JuaKMQgcyotYrU3GA,25883
|
@@ -27,7 +27,7 @@ dayhoff_tools/intake/uniprot.py,sha256=BZYJQF63OtPcBBnQ7_P9gulxzJtqyorgyuDiPeOJq
|
|
27
27
|
dayhoff_tools/logs.py,sha256=DKdeP0k0kliRcilwvX0mUB2eipO5BdWUeHwh-VnsICs,838
|
28
28
|
dayhoff_tools/sqlite.py,sha256=jV55ikF8VpTfeQqqlHSbY8OgfyfHj8zgHNpZjBLos_E,18672
|
29
29
|
dayhoff_tools/warehouse.py,sha256=UETBtZD3r7WgvURqfGbyHlT7cxoiVq8isjzMuerKw8I,24475
|
30
|
-
dayhoff_tools-1.9.
|
31
|
-
dayhoff_tools-1.9.
|
32
|
-
dayhoff_tools-1.9.
|
33
|
-
dayhoff_tools-1.9.
|
30
|
+
dayhoff_tools-1.9.3.dist-info/METADATA,sha256=cGFFtcWLIkHTYq9PFUgZkddSxAKoSOQTuS0Ix2eYfDs,2914
|
31
|
+
dayhoff_tools-1.9.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
32
|
+
dayhoff_tools-1.9.3.dist-info/entry_points.txt,sha256=iAf4jteNqW3cJm6CO6czLxjW3vxYKsyGLZ8WGmxamSc,49
|
33
|
+
dayhoff_tools-1.9.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|