dayhoff-tools 1.9.4__py3-none-any.whl → 1.9.5__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 +113 -29
- {dayhoff_tools-1.9.4.dist-info → dayhoff_tools-1.9.5.dist-info}/METADATA +1 -1
- {dayhoff_tools-1.9.4.dist-info → dayhoff_tools-1.9.5.dist-info}/RECORD +5 -5
- {dayhoff_tools-1.9.4.dist-info → dayhoff_tools-1.9.5.dist-info}/WHEEL +0 -0
- {dayhoff_tools-1.9.4.dist-info → dayhoff_tools-1.9.5.dist-info}/entry_points.txt +0 -0
@@ -778,15 +778,24 @@ def engine_status(
|
|
778
778
|
return "[green]Active[/green]"
|
779
779
|
if running_state in ("stopped", "stopping"):
|
780
780
|
return "[dim]N/A[/dim]"
|
781
|
-
|
782
|
-
|
783
|
-
if
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
)
|
789
|
-
|
781
|
+
|
782
|
+
# If we don't have idle info at all, show N/A
|
783
|
+
if not idle_info.get("available"):
|
784
|
+
return "[dim]N/A[/dim]"
|
785
|
+
|
786
|
+
# If idle, show time/threshold if available, otherwise show uncertainty
|
787
|
+
if idle_info.get("status") == "idle":
|
788
|
+
idle_seconds_v = idle_info.get("idle_seconds")
|
789
|
+
thresh_v = idle_info.get("idle_threshold")
|
790
|
+
if isinstance(idle_seconds_v, (int, float)) and isinstance(thresh_v, (int, float)):
|
791
|
+
return f"[yellow]Idle {int(idle_seconds_v)//60}m/{int(thresh_v)//60}m[/yellow]"
|
792
|
+
elif isinstance(thresh_v, (int, float)):
|
793
|
+
return f"[yellow]Idle ?/{int(thresh_v)//60}m[/yellow]"
|
794
|
+
else:
|
795
|
+
return "[yellow]Idle ?/?[/yellow]"
|
796
|
+
|
797
|
+
# Default to N/A if we can't determine status
|
798
|
+
return "[dim]N/A[/dim]"
|
790
799
|
|
791
800
|
active_disp = _compute_active_disp(idle_detector)
|
792
801
|
|
@@ -916,8 +925,12 @@ def engine_status(
|
|
916
925
|
},
|
917
926
|
)
|
918
927
|
cid = res["Command"]["CommandId"]
|
919
|
-
|
920
|
-
|
928
|
+
# Wait up to 2 seconds for SSM command to complete (was 1 second)
|
929
|
+
for _ in range(4): # 4 * 0.5 = 2 seconds
|
930
|
+
time.sleep(0.5)
|
931
|
+
inv = ssm.get_command_invocation(CommandId=cid, InstanceId=instance_id)
|
932
|
+
if inv["Status"] in ["Success", "Failed"]:
|
933
|
+
break
|
921
934
|
if inv["Status"] != "Success":
|
922
935
|
return None
|
923
936
|
content = inv["StandardOutputContent"].strip()
|
@@ -1037,23 +1050,10 @@ def engine_status(
|
|
1037
1050
|
status_lines.append(_sensor_line(" IDE ", "IDEConnectionSensor", "🖥"))
|
1038
1051
|
status_lines.append(_sensor_line("Docker", "DockerWorkloadSensor", "🐳"))
|
1039
1052
|
|
1040
|
-
#
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
thresh_secs = int(idle_detector.get("idle_threshold", 0))
|
1045
|
-
if thresh_secs > 0:
|
1046
|
-
active_disp = (
|
1047
|
-
f"[yellow]Idle {idle_secs//60}m/{thresh_secs//60}m[/yellow]"
|
1048
|
-
)
|
1049
|
-
# Rewrite top header line (index 0) to include updated display
|
1050
|
-
all_header = top_lines[0]
|
1051
|
-
# Replace the portion after two spaces (name and running state fixed)
|
1052
|
-
top_lines[0] = (
|
1053
|
-
f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n"
|
1054
|
-
)
|
1055
|
-
except Exception:
|
1056
|
-
pass
|
1053
|
+
# Recompute display with latest idle detector data
|
1054
|
+
active_disp = _compute_active_disp(idle_detector)
|
1055
|
+
# Rewrite top header line (index 0) to include updated display
|
1056
|
+
top_lines[0] = f"[blue]{engine['name']}[/blue] {run_disp} {active_disp}\n"
|
1057
1057
|
|
1058
1058
|
# Combine top summary and details
|
1059
1059
|
all_lines = top_lines + status_lines
|
@@ -2631,6 +2631,9 @@ def idle_timeout_cmd(
|
|
2631
2631
|
set: Optional[str] = typer.Option(
|
2632
2632
|
None, "--set", "-s", help="New timeout (e.g., 2h30m, 45m)"
|
2633
2633
|
),
|
2634
|
+
status: bool = typer.Option(
|
2635
|
+
False, "--status", help="Show detailed idle status (faster than full engine status)"
|
2636
|
+
),
|
2634
2637
|
):
|
2635
2638
|
"""Show or set the engine idle-detector timeout."""
|
2636
2639
|
check_aws_sso()
|
@@ -2645,9 +2648,90 @@ def idle_timeout_cmd(
|
|
2645
2648
|
engine = resolve_engine(name_or_id, engines)
|
2646
2649
|
|
2647
2650
|
ssm = boto3.client("ssm", region_name="us-east-1")
|
2651
|
+
|
2652
|
+
# Handle --status flag for quick idle status check
|
2653
|
+
if status:
|
2654
|
+
console.print(f"[bold]Idle Status for {engine['name']}:[/bold]")
|
2655
|
+
|
2656
|
+
# Fetch state file with longer timeout for reliability
|
2657
|
+
try:
|
2658
|
+
resp = ssm.send_command(
|
2659
|
+
InstanceIds=[engine["instance_id"]],
|
2660
|
+
DocumentName="AWS-RunShellScript",
|
2661
|
+
Parameters={
|
2662
|
+
"commands": [
|
2663
|
+
"cat /var/run/idle-detector/last_state.json 2>/dev/null || echo '{}'"
|
2664
|
+
],
|
2665
|
+
"executionTimeout": ["10"],
|
2666
|
+
},
|
2667
|
+
)
|
2668
|
+
cid = resp["Command"]["CommandId"]
|
2669
|
+
|
2670
|
+
# Wait up to 3 seconds for result
|
2671
|
+
for _ in range(6): # 6 * 0.5 = 3 seconds
|
2672
|
+
time.sleep(0.5)
|
2673
|
+
inv = ssm.get_command_invocation(
|
2674
|
+
CommandId=cid, InstanceId=engine["instance_id"]
|
2675
|
+
)
|
2676
|
+
if inv["Status"] in ["Success", "Failed"]:
|
2677
|
+
break
|
2678
|
+
|
2679
|
+
if inv["Status"] == "Success":
|
2680
|
+
import json
|
2681
|
+
content = inv["StandardOutputContent"].strip()
|
2682
|
+
if content and content != "{}":
|
2683
|
+
data = json.loads(content)
|
2684
|
+
|
2685
|
+
# Extract key values
|
2686
|
+
is_idle = data.get("idle", False)
|
2687
|
+
timeout_sec = data.get("timeout_sec", "?")
|
2688
|
+
idle_seconds = data.get("idle_seconds", 0) if is_idle else 0
|
2689
|
+
|
2690
|
+
# Display status
|
2691
|
+
if is_idle:
|
2692
|
+
if isinstance(timeout_sec, int) and isinstance(idle_seconds, int):
|
2693
|
+
console.print(f" Status: [yellow]Idle {idle_seconds//60}m/{timeout_sec//60}m[/yellow]")
|
2694
|
+
remaining = max(0, timeout_sec - idle_seconds)
|
2695
|
+
console.print(f" Time until shutdown: [red]{remaining//60}m {remaining%60}s[/red]")
|
2696
|
+
else:
|
2697
|
+
console.print(f" Status: [yellow]Idle (timing unavailable)[/yellow]")
|
2698
|
+
else:
|
2699
|
+
console.print(f" Status: [green]Active[/green]")
|
2700
|
+
if isinstance(timeout_sec, int):
|
2701
|
+
console.print(f" Timeout: {timeout_sec//60}m ({timeout_sec}s)")
|
2702
|
+
|
2703
|
+
# Show activity sensors
|
2704
|
+
console.print("\n[bold]Activity Sensors:[/bold]")
|
2705
|
+
reasons = data.get("reasons", [])
|
2706
|
+
for r in reasons:
|
2707
|
+
sensor = r.get("sensor", "Unknown")
|
2708
|
+
active = r.get("active", False)
|
2709
|
+
reason = r.get("reason", "")
|
2710
|
+
|
2711
|
+
# Map sensor names to icons and labels
|
2712
|
+
sensor_map = {
|
2713
|
+
"CoffeeLockSensor": ("☕", "Coffee"),
|
2714
|
+
"ActiveLoginSensor": ("🐚", "SSH"),
|
2715
|
+
"IDEConnectionSensor": ("🖥", "IDE"),
|
2716
|
+
"DockerWorkloadSensor": ("🐳", "Docker"),
|
2717
|
+
}
|
2718
|
+
|
2719
|
+
icon, label = sensor_map.get(sensor, ("?", sensor))
|
2720
|
+
status_str = "[green]YES[/green]" if active else "[dim]no[/dim]"
|
2721
|
+
console.print(f" {icon} {label:8} {status_str} {reason if active else ''}")
|
2722
|
+
|
2723
|
+
else:
|
2724
|
+
console.print("[yellow]⚠️ Could not read idle detector state[/yellow]")
|
2725
|
+
else:
|
2726
|
+
console.print(f"[red]❌ Failed to get status: {inv.get('StandardErrorContent', 'Unknown error')}[/red]")
|
2727
|
+
|
2728
|
+
except Exception as e:
|
2729
|
+
console.print(f"[red]❌ Error fetching idle status: {e}[/red]")
|
2730
|
+
|
2731
|
+
return
|
2648
2732
|
|
2649
2733
|
if set is None:
|
2650
|
-
# Show current
|
2734
|
+
# Show current timeout setting
|
2651
2735
|
resp = ssm.send_command(
|
2652
2736
|
InstanceIds=[engine["instance_id"]],
|
2653
2737
|
DocumentName="AWS-RunShellScript",
|
@@ -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=XFCaHWHhPIsOU43iyERel_hk3CgHPYFN3p8kVaQhuT0,111329
|
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.5.dist-info/METADATA,sha256=fw3aufIuu3G9jI14oECpLoIUP52JhhT0kpZQufTN5uo,2914
|
31
|
+
dayhoff_tools-1.9.5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
32
|
+
dayhoff_tools-1.9.5.dist-info/entry_points.txt,sha256=iAf4jteNqW3cJm6CO6czLxjW3vxYKsyGLZ8WGmxamSc,49
|
33
|
+
dayhoff_tools-1.9.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|