Skip to content

Commit e7cf8a3

Browse files
authored
feat(cli): enhance hardware command to display availability status (#223)
* feat(cli): enhance hardware command to display availability status * format
1 parent b256c61 commit e7cf8a3

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

src/together/lib/cli/api/endpoints/create.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import sys
44

55
import click
6-
from rich import print
76

87
from together import APIError, Together, omit
98
from together.lib.cli.api._utils import handle_api_errors
@@ -124,8 +123,13 @@ def create(
124123
extra_query={"availability_zone": availability_zone or omit},
125124
)
126125
except APIError as e:
127-
if "check the hardware api" in str(e.args[0]).lower() or "invalid hardware provided" in str(e.args[0]).lower():
128-
print("Invalid hardware provided")
126+
if (
127+
"check the hardware api" in str(e.args[0]).lower()
128+
or "invalid hardware provided" in str(e.args[0]).lower()
129+
or "the selected configuration" in str(e.args[0]).lower()
130+
):
131+
click.secho("Invalid hardware selected.", fg="red", err=True)
132+
click.echo("\nAvailable hardware options:")
129133
ctx.invoke(hardware, available=True, model=model, json=False)
130134
sys.exit(1)
131135
raise e

src/together/lib/cli/api/endpoints/hardware.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
from __future__ import annotations
22

3+
import re
34
import json as json_lib
5+
from typing import Any, Dict, List
46

57
import click
8+
from tabulate import tabulate
69

710
from together import Together, omit
11+
from together.types import HardwareListResponse
812
from together.lib.cli.api._utils import handle_api_errors
913
from together.lib.utils.serializer import datetime_serializer
1014

@@ -21,20 +25,47 @@
2125
@handle_api_errors("Endpoints")
2226
def hardware(client: Together, model: str | None, json: bool, available: bool) -> None:
2327
"""List all available hardware options, optionally filtered by model."""
24-
message = "Available hardware options:" if available else "All hardware options:"
25-
click.echo(message, err=True)
2628
hardware_options = client.hardware.list(model=model or omit)
27-
# hardware_options = client.endpoints.list_hardware(model)
29+
2830
if available:
2931
hardware_options.data = [
3032
hardware
3133
for hardware in hardware_options.data
3234
if hardware.availability is not None and hardware.availability.status == "available"
3335
]
34-
3536
if json:
3637
json_output = [hardware.model_dump() for hardware in hardware_options.data]
3738
click.echo(json_lib.dumps(json_output, default=datetime_serializer, indent=2))
3839
else:
39-
for hardware in hardware_options.data:
40-
click.echo(f" {hardware.id}", err=True)
40+
_format_hardware_options(hardware_options, show_availability=model is not None)
41+
42+
43+
def _format_hardware_options(hardware_options: HardwareListResponse, show_availability: bool = True) -> None:
44+
display_list: List[Dict[str, Any]] = []
45+
46+
for hw in hardware_options.data:
47+
data = {
48+
"Hardware ID": hw.id,
49+
"GPU": re.sub(r"\-\d+[a-zA-Z][a-zA-Z]$", "", hw.specs.gpu_type)
50+
if hw.specs and hw.specs.gpu_type
51+
else "N/A",
52+
"Memory": f"{int(hw.specs.gpu_memory)}GB" if hw.specs else "N/A",
53+
"Count": hw.specs.gpu_count if hw.specs else "N/A",
54+
"Price (per minute)": (f"${hw.pricing.cents_per_minute / 100:.2f}" if hw.pricing else "N/A"),
55+
}
56+
57+
if show_availability:
58+
status_display = "—"
59+
if hw.availability:
60+
status = hw.availability.status
61+
# Add visual indicators for status
62+
if status == "available":
63+
status_display = click.style("✓ available", fg="green")
64+
elif status == "unavailable":
65+
status_display = click.style("✗ unavailable", fg="red")
66+
else: # insufficient
67+
status_display = click.style("⚠ insufficient", fg="yellow")
68+
data["availability"] = status_display
69+
display_list.append(data)
70+
71+
click.echo(tabulate(display_list, headers="keys", numalign="left"))

0 commit comments

Comments
 (0)