dayhoff-tools 1.9.6__tar.gz → 1.9.8__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.
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/PKG-INFO +1 -1
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/cli/engine_commands.py +41 -47
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/pyproject.toml +1 -1
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/README.md +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/__init__.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/chemistry/standardizer.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/chemistry/utils.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/cli/__init__.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/cli/cloud_commands.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/cli/main.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/cli/swarm_commands.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/cli/utility_commands.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/deployment/base.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/deployment/deploy_aws.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/deployment/deploy_gcp.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/deployment/deploy_utils.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/deployment/job_runner.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/deployment/processors.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/deployment/swarm.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/embedders.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/fasta.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/file_ops.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/h5.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/intake/gcp.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/intake/gtdb.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/intake/kegg.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/intake/mmseqs.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/intake/structure.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/intake/uniprot.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/logs.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/sqlite.py +0 -0
- {dayhoff_tools-1.9.6 → dayhoff_tools-1.9.8}/dayhoff_tools/warehouse.py +0 -0
@@ -710,19 +710,13 @@ def engine_status(
|
|
710
710
|
|
711
711
|
# Fast status display (default)
|
712
712
|
if not detailed:
|
713
|
-
#
|
714
|
-
|
715
|
-
|
716
|
-
console.print("[red]❌ Failed to fetch engine details[/red]")
|
717
|
-
raise typer.Exit(1)
|
718
|
-
|
719
|
-
engine_details = response.json()
|
720
|
-
engine = engine_details.get("engine", engine)
|
721
|
-
attached_studios = engine_details.get("attached_studios", [])
|
713
|
+
# Skip the API call for studios - use basic info we already have
|
714
|
+
attached_studios = []
|
715
|
+
studio_user = engine.get("user") # Use the engine's user as studio owner
|
722
716
|
|
723
717
|
# Fetch idle status via SSM with longer timeout
|
724
718
|
ssm = boto3.client("ssm", region_name="us-east-1")
|
725
|
-
idle_data =
|
719
|
+
idle_data = None # Use None to indicate no data received
|
726
720
|
|
727
721
|
if engine["state"].lower() == "running":
|
728
722
|
try:
|
@@ -751,11 +745,10 @@ def engine_status(
|
|
751
745
|
content = inv["StandardOutputContent"].strip()
|
752
746
|
if content and content != "{}":
|
753
747
|
idle_data = json.loads(content)
|
748
|
+
else:
|
749
|
+
idle_data = {} # Empty response but SSM worked
|
754
750
|
except Exception:
|
755
|
-
|
756
|
-
|
757
|
-
# Build status display
|
758
|
-
hourly_cost = HOURLY_COSTS.get(engine["engine_type"], 0)
|
751
|
+
idle_data = None # SSM failed
|
759
752
|
|
760
753
|
# Determine running state display
|
761
754
|
running_state = engine["state"].lower()
|
@@ -773,48 +766,45 @@ def engine_status(
|
|
773
766
|
# Determine idle/active status
|
774
767
|
idle_disp = ""
|
775
768
|
if running_state == "running":
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
remaining = max(0, timeout_sec - idle_seconds)
|
783
|
-
idle_disp = f" [yellow]Idle {idle_seconds//60}m/{timeout_sec//60}m: [red]{remaining//60}m {remaining%60}s[/red] left[/yellow]"
|
784
|
-
else:
|
785
|
-
idle_disp = " [yellow]Idle ?/?[/yellow]"
|
769
|
+
if idle_data is None:
|
770
|
+
# SSM failed - we don't know the status
|
771
|
+
idle_disp = " [dim]N/A[/dim]"
|
772
|
+
elif not idle_data:
|
773
|
+
# Empty data - likely very early in boot
|
774
|
+
idle_disp = " [dim]N/A[/dim]"
|
786
775
|
else:
|
787
|
-
|
776
|
+
# We have data
|
777
|
+
is_idle = idle_data.get("idle", False)
|
778
|
+
timeout_sec = idle_data.get("timeout_sec")
|
779
|
+
idle_seconds = idle_data.get("idle_seconds", 0) if is_idle else 0
|
780
|
+
|
781
|
+
if is_idle:
|
782
|
+
if isinstance(timeout_sec, int) and isinstance(idle_seconds, int):
|
783
|
+
remaining = max(0, timeout_sec - idle_seconds)
|
784
|
+
remaining_mins = remaining // 60
|
785
|
+
if remaining_mins == 0:
|
786
|
+
idle_disp = f" [yellow]Idle {idle_seconds//60}m/{timeout_sec//60}m: [red]<1m[/red] left[/yellow]"
|
787
|
+
else:
|
788
|
+
idle_disp = f" [yellow]Idle {idle_seconds//60}m/{timeout_sec//60}m: [red]{remaining_mins}m[/red] left[/yellow]"
|
789
|
+
else:
|
790
|
+
idle_disp = " [yellow]Idle ?/?[/yellow]"
|
791
|
+
else:
|
792
|
+
# Actively not idle
|
793
|
+
idle_disp = " [green]Active[/green]"
|
788
794
|
|
789
|
-
# Build status lines
|
795
|
+
# Build status lines - minimal info for fast view
|
790
796
|
status_lines = [
|
791
797
|
f"[blue]{engine['name']}[/blue] {run_disp}{idle_disp}\n",
|
792
798
|
]
|
793
799
|
|
794
|
-
# Add studios if attached
|
795
|
-
if attached_studios:
|
796
|
-
studio_names = [f"[magenta]{s.get('user', 'studio')}[/magenta]" for s in attached_studios]
|
797
|
-
status_lines.append(f"Studios: {', '.join(studio_names)}")
|
798
|
-
|
799
|
-
status_lines.append("") # blank line
|
800
|
-
|
801
|
-
# Basic info
|
802
|
-
status_lines.extend([
|
803
|
-
f"Type: {engine['engine_type']} ({engine['instance_type']})",
|
804
|
-
f"User: {engine['user']}",
|
805
|
-
f"IP: {engine.get('public_ip', 'N/A')}",
|
806
|
-
f"$/hour: ${hourly_cost:.2f}",
|
807
|
-
])
|
808
|
-
|
809
800
|
# Add activity sensors if we have idle data
|
810
|
-
if idle_data.get("reasons"):
|
811
|
-
status_lines.append("")
|
812
|
-
status_lines.append("[bold]Activity:[/bold]")
|
801
|
+
if idle_data and idle_data.get("reasons"):
|
802
|
+
status_lines.append("") # blank line before sensors
|
813
803
|
|
814
804
|
sensor_map = {
|
815
805
|
"CoffeeLockSensor": ("☕", "Coffee"),
|
816
806
|
"ActiveLoginSensor": ("🐚", "SSH"),
|
817
|
-
"IDEConnectionSensor": ("🖥", "IDE"),
|
807
|
+
"IDEConnectionSensor": ("🖥 ", "IDE"),
|
818
808
|
"DockerWorkloadSensor": ("🐳", "Docker"),
|
819
809
|
}
|
820
810
|
|
@@ -822,7 +812,7 @@ def engine_status(
|
|
822
812
|
sensor = r.get("sensor", "Unknown")
|
823
813
|
active = r.get("active", False)
|
824
814
|
icon, label = sensor_map.get(sensor, ("?", sensor))
|
825
|
-
status_str = "[green]YES[/green]" if active else "[dim]
|
815
|
+
status_str = "[green]YES[/green]" if active else "[dim]nope[/dim]"
|
826
816
|
status_lines.append(f" {icon} {label:6} {status_str}")
|
827
817
|
|
828
818
|
# Display in a nice panel
|
@@ -913,7 +903,11 @@ def engine_status(
|
|
913
903
|
thresh_v = idle_info.get("idle_threshold")
|
914
904
|
if isinstance(idle_seconds_v, (int, float)) and isinstance(thresh_v, (int, float)):
|
915
905
|
remaining = max(0, int(thresh_v) - int(idle_seconds_v))
|
916
|
-
|
906
|
+
remaining_mins = remaining // 60
|
907
|
+
if remaining_mins == 0:
|
908
|
+
return f"[yellow]Idle {int(idle_seconds_v)//60}m/{int(thresh_v)//60}m: [red]<1m[/red] left[/yellow]"
|
909
|
+
else:
|
910
|
+
return f"[yellow]Idle {int(idle_seconds_v)//60}m/{int(thresh_v)//60}m: [red]{remaining_mins}m[/red] left[/yellow]"
|
917
911
|
elif isinstance(thresh_v, (int, float)):
|
918
912
|
return f"[yellow]Idle ?/{int(thresh_v)//60}m[/yellow]"
|
919
913
|
else:
|
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
|
|
5
5
|
|
6
6
|
[project]
|
7
7
|
name = "dayhoff-tools"
|
8
|
-
version = "1.9.
|
8
|
+
version = "1.9.8"
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|