dayhoff-tools 1.8.6__py3-none-any.whl → 1.8.8__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.
@@ -847,16 +847,31 @@ def engine_status(
847
847
  run_disp = "[green]Running[/green]"
848
848
  elif running_state == "pending":
849
849
  run_disp = "[yellow]Starting...[/yellow]"
850
+ elif running_state == "stopping":
851
+ run_disp = "[yellow]Stopping...[/yellow]"
850
852
  elif running_state == "stopped":
851
853
  run_disp = "[dim]Stopped[/dim]"
852
854
  else:
853
- run_disp = engine["state"]
855
+ run_disp = engine["state"].capitalize()
854
856
 
855
- active_disp = (
856
- "[green]Active[/green]"
857
- if idle_detector.get("status") == "active"
858
- else "[yellow]Idle[/yellow]"
859
- )
857
+ # Compose Active/Idle header with extra detail when idle
858
+ if idle_detector.get("status") == "active":
859
+ active_disp = "[green]Active[/green]"
860
+ else:
861
+ # show Idle <elapsed>/<threshold> if available; else just N/A for stopped states
862
+ if running_state in ("stopped", "stopping"):
863
+ active_disp = "[dim]N/A[/dim]"
864
+ else:
865
+ idle_seconds = idle_detector.get("idle_seconds")
866
+ thresh = idle_detector.get("idle_threshold")
867
+ if isinstance(idle_seconds, (int, float)) and isinstance(
868
+ thresh, (int, float)
869
+ ):
870
+ active_disp = (
871
+ f"[yellow]Idle {int(idle_seconds)//60}m/{int(thresh)//60}m[/yellow]"
872
+ )
873
+ else:
874
+ active_disp = "[yellow]Idle[/yellow]"
860
875
 
861
876
  top_lines = [
862
877
  f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n",
@@ -892,6 +907,48 @@ def engine_status(
892
907
  disk_usage = get_disk_usage_via_ssm(engine["instance_id"]) or "-"
893
908
  status_lines.append(f"Disk: {disk_usage}")
894
909
 
910
+ # Idle timeout (show even when not idle)
911
+ idle_threshold_secs: Optional[int] = None
912
+ # Prefer value from idle detector overlay if present
913
+ try:
914
+ if isinstance(idle_detector.get("idle_threshold"), (int, float)):
915
+ idle_threshold_secs = int(idle_detector["idle_threshold"])
916
+ except Exception:
917
+ idle_threshold_secs = None
918
+
919
+ if idle_threshold_secs is None and engine["state"].lower() == "running":
920
+ # Fallback: read /etc/engine.env via SSM
921
+ try:
922
+ ssm = boto3.client("ssm", region_name="us-east-1")
923
+ resp = ssm.send_command(
924
+ InstanceIds=[engine["instance_id"]],
925
+ DocumentName="AWS-RunShellScript",
926
+ Parameters={
927
+ "commands": [
928
+ "grep -E '^IDLE_TIMEOUT_SECONDS=' /etc/engine.env | cut -d'=' -f2 || echo 1800",
929
+ ],
930
+ "executionTimeout": ["5"],
931
+ },
932
+ )
933
+ cid = resp["Command"]["CommandId"]
934
+ time.sleep(1)
935
+ inv = ssm.get_command_invocation(
936
+ CommandId=cid, InstanceId=engine["instance_id"]
937
+ )
938
+ if inv.get("Status") == "Success":
939
+ out = (inv.get("StandardOutputContent") or "").strip()
940
+ if out:
941
+ idle_threshold_secs = int(out.splitlines()[0].strip())
942
+ except Exception:
943
+ idle_threshold_secs = None
944
+
945
+ if idle_threshold_secs is None:
946
+ idle_threshold_secs = 1800
947
+
948
+ status_lines.append(
949
+ f"Idle timeout: {idle_threshold_secs//60}m ({idle_threshold_secs}s)"
950
+ )
951
+
895
952
  # Health report (only if bootstrap finished)
896
953
  if stage_val == "finished":
897
954
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: dayhoff-tools
3
- Version: 1.8.6
3
+ Version: 1.8.8
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
@@ -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=UKX2B6DKAh82jiyocNMhtmWMhCbNyeOXONMmZ5yD1VE,107809
6
+ dayhoff_tools/cli/engine_commands.py,sha256=o_7d4YhHO5U_WncIowx91v6qCPnalFPqayx5p9CnSug,110214
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.8.6.dist-info/METADATA,sha256=4FFmSPx7EIfi8eLzspHfAdOZtt_Gj0aLWMQnJ2R2mP4,2914
31
- dayhoff_tools-1.8.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
32
- dayhoff_tools-1.8.6.dist-info/entry_points.txt,sha256=iAf4jteNqW3cJm6CO6czLxjW3vxYKsyGLZ8WGmxamSc,49
33
- dayhoff_tools-1.8.6.dist-info/RECORD,,
30
+ dayhoff_tools-1.8.8.dist-info/METADATA,sha256=2zQrmTSb1lXvkeAdwIRdRWtm5rWfztsj7JFWtIISC30,2914
31
+ dayhoff_tools-1.8.8.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
32
+ dayhoff_tools-1.8.8.dist-info/entry_points.txt,sha256=iAf4jteNqW3cJm6CO6czLxjW3vxYKsyGLZ8WGmxamSc,49
33
+ dayhoff_tools-1.8.8.dist-info/RECORD,,