dayhoff-tools 1.9.1__tar.gz → 1.9.2__tar.gz

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.
Files changed (32) hide show
  1. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/PKG-INFO +1 -1
  2. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/cli/engine_commands.py +60 -19
  3. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/pyproject.toml +1 -1
  4. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/README.md +0 -0
  5. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/__init__.py +0 -0
  6. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/chemistry/standardizer.py +0 -0
  7. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/chemistry/utils.py +0 -0
  8. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/cli/__init__.py +0 -0
  9. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/cli/cloud_commands.py +0 -0
  10. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/cli/main.py +0 -0
  11. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/cli/swarm_commands.py +0 -0
  12. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/cli/utility_commands.py +0 -0
  13. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/deployment/base.py +0 -0
  14. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/deployment/deploy_aws.py +0 -0
  15. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/deployment/deploy_gcp.py +0 -0
  16. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/deployment/deploy_utils.py +0 -0
  17. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/deployment/job_runner.py +0 -0
  18. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/deployment/processors.py +0 -0
  19. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/deployment/swarm.py +0 -0
  20. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/embedders.py +0 -0
  21. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/fasta.py +0 -0
  22. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/file_ops.py +0 -0
  23. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/h5.py +0 -0
  24. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/intake/gcp.py +0 -0
  25. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/intake/gtdb.py +0 -0
  26. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/intake/kegg.py +0 -0
  27. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/intake/mmseqs.py +0 -0
  28. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/intake/structure.py +0 -0
  29. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/intake/uniprot.py +0 -0
  30. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/logs.py +0 -0
  31. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/sqlite.py +0 -0
  32. {dayhoff_tools-1.9.1 → dayhoff_tools-1.9.2}/dayhoff_tools/warehouse.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dayhoff-tools
3
- Version: 1.9.1
3
+ Version: 1.9.2
4
4
  Summary: Common tools for all the repos at Dayhoff Labs
5
5
  Author: Daniel Martin-Alarcon
6
6
  Author-email: dma@dayhofflabs.com
@@ -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
@@ -927,23 +924,55 @@ def engine_status(
927
924
  if not content:
928
925
  return None
929
926
  data = json.loads(content)
930
- # Convert last_state schema to idle_detector schema used by CLI output
927
+ # Convert last_state schema (new or old) to idle_detector schema used by CLI output
931
928
  idle_info: Dict[str, Any] = {"available": True}
932
- idle_info["status"] = "active" if not data.get("idle", True) else "idle"
933
- # thresholds if present
929
+
930
+ # Active/idle
931
+ idle_flag = bool(data.get("idle", False))
932
+ idle_info["status"] = "idle" if idle_flag else "active"
933
+
934
+ # Threshold and elapsed
934
935
  if isinstance(data.get("timeout_sec"), (int, float)):
935
936
  idle_info["idle_threshold"] = int(data["timeout_sec"]) # seconds
936
- # keep raw reasons for sensor display
937
+ if isinstance(data.get("idle_seconds"), (int, float)):
938
+ idle_info["idle_seconds"] = int(data["idle_seconds"])
939
+
940
+ # Keep raw reasons for sensor display when available (new schema)
937
941
  if isinstance(data.get("reasons"), list):
938
942
  idle_info["_reasons_raw"] = data["reasons"]
939
- # derive details from sensors
940
- for r in data.get("reasons", []):
943
+ else:
944
+ # Fallback: synthesize reasons from the old forensics layout
945
+ f_all = data.get("forensics", {}) or {}
946
+ synthesized = []
947
+
948
+ def _mk(sensor_name: str, key: str):
949
+ entry = f_all.get(key, {}) or {}
950
+ synthesized.append(
951
+ {
952
+ "sensor": sensor_name,
953
+ "active": bool(entry.get("active", False)),
954
+ "reason": entry.get("reason", ""),
955
+ "forensic": entry.get("forensic", {}),
956
+ }
957
+ )
958
+
959
+ _mk("CoffeeLockSensor", "coffee")
960
+ _mk("ActiveLoginSensor", "ssh")
961
+ _mk("IDEConnectionSensor", "ide")
962
+ _mk("DockerWorkloadSensor", "docker")
963
+ idle_info["_reasons_raw"] = synthesized
964
+
965
+ # Derive details from sensors
966
+ for r in idle_info.get("_reasons_raw", []):
941
967
  if not r.get("active"):
942
968
  continue
943
969
  sensor = (r.get("sensor") or "").lower()
944
970
  forensic = r.get("forensic") or {}
945
971
  if sensor == "ideconnectionsensor":
946
- cnt = forensic.get("matches")
972
+ # Prefer unique_pid_count written by new detector
973
+ cnt = forensic.get("unique_pid_count")
974
+ if not isinstance(cnt, int):
975
+ cnt = forensic.get("matches")
947
976
  if isinstance(cnt, int):
948
977
  idle_info["ide_connections"] = {"connection_count": cnt}
949
978
  else:
@@ -955,12 +984,11 @@ def engine_status(
955
984
  timedelta(seconds=int(rem))
956
985
  )
957
986
  elif sensor == "activeloginsensor":
958
- # Provide a single summarized SSH session if available
959
987
  sess = {
960
- "tty": r.get("forensic", {}).get("tty", "pts/?"),
961
- "pid": r.get("forensic", {}).get("pid", "?"),
962
- "idle_time": r.get("forensic", {}).get("idle_sec", 0),
963
- "from_ip": r.get("forensic", {}).get("remote_addr", "unknown"),
988
+ "tty": forensic.get("tty", "pts/?"),
989
+ "pid": forensic.get("pid", "?"),
990
+ "idle_time": forensic.get("idle_sec", 0),
991
+ "from_ip": forensic.get("remote_addr", "unknown"),
964
992
  }
965
993
  idle_info.setdefault("ssh_sessions", []).append(sess)
966
994
  return idle_info
@@ -1002,7 +1030,23 @@ def engine_status(
1002
1030
  status_lines.append(_sensor_line(" IDE ", "IDEConnectionSensor", "🖥"))
1003
1031
  status_lines.append(_sensor_line("Docker", "DockerWorkloadSensor", "🐳"))
1004
1032
 
1005
-
1033
+ # If we have elapsed idle seconds and threshold, reflect that in the header
1034
+ try:
1035
+ if idle_detector.get("status") == "idle":
1036
+ idle_secs = int(idle_detector.get("idle_seconds", 0))
1037
+ thresh_secs = int(idle_detector.get("idle_threshold", 0))
1038
+ if thresh_secs > 0:
1039
+ active_disp = (
1040
+ f"[yellow]Idle {idle_secs//60}m/{thresh_secs//60}m[/yellow]"
1041
+ )
1042
+ # Rewrite top header line (index 0) to include updated display
1043
+ all_header = top_lines[0]
1044
+ # Replace the portion after two spaces (name and running state fixed)
1045
+ top_lines[0] = (
1046
+ f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n"
1047
+ )
1048
+ except Exception:
1049
+ pass
1006
1050
 
1007
1051
  # Combine top summary and details
1008
1052
  all_lines = top_lines + status_lines
@@ -1041,9 +1085,6 @@ def engine_status(
1041
1085
  console.print(f"[red]❌ Error fetching log: {e}[/red]")
1042
1086
 
1043
1087
 
1044
-
1045
-
1046
-
1047
1088
  @engine_app.command("stop")
1048
1089
  def stop_engine(
1049
1090
  name_or_id: str = typer.Argument(help="Engine name or instance ID"),
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
5
5
 
6
6
  [project]
7
7
  name = "dayhoff-tools"
8
- version = "1.9.1"
8
+ version = "1.9.2"
9
9
  description = "Common tools for all the repos at Dayhoff Labs"
10
10
  authors = [
11
11
  {name = "Daniel Martin-Alarcon", email = "dma@dayhofflabs.com"}
File without changes