hypercli-cli 0.4.3__tar.gz → 0.4.5__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.
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/PKG-INFO +2 -1
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/billing.py +6 -6
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/comfyui.py +5 -5
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/instances.py +9 -9
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/jobs.py +15 -15
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/llm.py +1 -1
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/renders.py +15 -15
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/tui/__init__.py +1 -1
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/tui/job_monitor.py +4 -4
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/user.py +3 -3
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/pyproject.toml +2 -1
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/.gitignore +0 -0
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/README.md +0 -0
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/__init__.py +0 -0
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/cli.py +0 -0
- {hypercli_cli-0.4.3 → hypercli_cli-0.4.5}/hypercli_cli/output.py +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hypercli-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.5
|
|
4
4
|
Summary: CLI for HyperCLI - GPU orchestration and LLM API
|
|
5
5
|
Project-URL: Homepage, https://hypercli.com
|
|
6
6
|
Project-URL: Documentation, https://docs.hypercli.com
|
|
7
|
+
Project-URL: Repository, https://github.com/hypercli/monorepo
|
|
7
8
|
Author-email: HyperCLI <support@hypercli.com>
|
|
8
9
|
License-Expression: MIT
|
|
9
10
|
Requires-Python: >=3.10
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""hyper billing commands"""
|
|
2
2
|
import typer
|
|
3
3
|
from hypercli import C3
|
|
4
4
|
from .output import output, console, spinner
|
|
@@ -15,9 +15,9 @@ def balance(
|
|
|
15
15
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
16
16
|
):
|
|
17
17
|
"""Get account balance"""
|
|
18
|
-
|
|
18
|
+
client = get_client()
|
|
19
19
|
with spinner("Fetching balance..."):
|
|
20
|
-
bal =
|
|
20
|
+
bal = client.billing.balance()
|
|
21
21
|
|
|
22
22
|
if fmt == "table":
|
|
23
23
|
console.print()
|
|
@@ -39,9 +39,9 @@ def transactions(
|
|
|
39
39
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
40
40
|
):
|
|
41
41
|
"""List transactions"""
|
|
42
|
-
|
|
42
|
+
client = get_client()
|
|
43
43
|
with spinner("Fetching transactions..."):
|
|
44
|
-
txs =
|
|
44
|
+
txs = client.billing.transactions(limit=limit, page=page)
|
|
45
45
|
|
|
46
46
|
if fmt == "json":
|
|
47
47
|
output(txs, fmt)
|
|
@@ -55,6 +55,6 @@ def invoices(
|
|
|
55
55
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
56
56
|
):
|
|
57
57
|
"""List invoices"""
|
|
58
|
-
|
|
58
|
+
client = get_client()
|
|
59
59
|
# TODO: Add invoices to SDK
|
|
60
60
|
console.print("[dim]Invoices endpoint not yet implemented in SDK[/dim]")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""hyper comfyui commands - Run ComfyUI workflows on GPU"""
|
|
2
2
|
import random
|
|
3
3
|
import threading
|
|
4
4
|
from pathlib import Path
|
|
@@ -297,7 +297,7 @@ def run(
|
|
|
297
297
|
raise typer.Exit(1)
|
|
298
298
|
raise typer.Exit(0)
|
|
299
299
|
|
|
300
|
-
|
|
300
|
+
client = get_client()
|
|
301
301
|
|
|
302
302
|
# Get or create job
|
|
303
303
|
try:
|
|
@@ -677,7 +677,7 @@ def show(
|
|
|
677
677
|
@app.command("status")
|
|
678
678
|
def status():
|
|
679
679
|
"""Show running ComfyUI job status"""
|
|
680
|
-
|
|
680
|
+
client = get_client()
|
|
681
681
|
|
|
682
682
|
with spinner("Checking for running jobs..."):
|
|
683
683
|
job = ComfyUIJob.get_running(c3)
|
|
@@ -712,7 +712,7 @@ def download(
|
|
|
712
712
|
auth: bool = typer.Option(False, "--auth", help="Use Bearer token auth"),
|
|
713
713
|
):
|
|
714
714
|
"""Download outputs from a running ComfyUI instance"""
|
|
715
|
-
|
|
715
|
+
client = get_client()
|
|
716
716
|
|
|
717
717
|
# Get job
|
|
718
718
|
if instance:
|
|
@@ -806,7 +806,7 @@ def download(
|
|
|
806
806
|
@app.command("stop")
|
|
807
807
|
def stop():
|
|
808
808
|
"""Stop running ComfyUI job"""
|
|
809
|
-
|
|
809
|
+
client = get_client()
|
|
810
810
|
|
|
811
811
|
with spinner("Finding running job..."):
|
|
812
812
|
job = ComfyUIJob.get_running(c3)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""hyper instances commands"""
|
|
2
2
|
import typer
|
|
3
3
|
from typing import Optional
|
|
4
4
|
from hypercli import C3
|
|
@@ -18,9 +18,9 @@ def list_instances(
|
|
|
18
18
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
19
19
|
):
|
|
20
20
|
"""List available GPU instances with pricing"""
|
|
21
|
-
|
|
21
|
+
client = get_client()
|
|
22
22
|
with spinner("Fetching instances..."):
|
|
23
|
-
available =
|
|
23
|
+
available = client.instances.list_available(gpu_type=gpu, region=region)
|
|
24
24
|
|
|
25
25
|
if fmt == "json":
|
|
26
26
|
output(available, "json")
|
|
@@ -58,9 +58,9 @@ def list_gpus(
|
|
|
58
58
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
59
59
|
):
|
|
60
60
|
"""List available GPU types"""
|
|
61
|
-
|
|
61
|
+
client = get_client()
|
|
62
62
|
with spinner("Fetching GPU types..."):
|
|
63
|
-
types =
|
|
63
|
+
types = client.instances.types()
|
|
64
64
|
|
|
65
65
|
if fmt == "json":
|
|
66
66
|
output({k: {"name": v.name, "description": v.description, "configs": [
|
|
@@ -105,9 +105,9 @@ def list_regions(
|
|
|
105
105
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
106
106
|
):
|
|
107
107
|
"""List available regions"""
|
|
108
|
-
|
|
108
|
+
client = get_client()
|
|
109
109
|
with spinner("Fetching regions..."):
|
|
110
|
-
regions =
|
|
110
|
+
regions = client.instances.regions()
|
|
111
111
|
|
|
112
112
|
if fmt == "json":
|
|
113
113
|
output({k: {"description": v.description, "country": v.country} for k, v in regions.items()}, "json")
|
|
@@ -143,7 +143,7 @@ def launch(
|
|
|
143
143
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
144
144
|
):
|
|
145
145
|
"""Launch a new GPU instance"""
|
|
146
|
-
|
|
146
|
+
client = get_client()
|
|
147
147
|
|
|
148
148
|
# Parse env vars
|
|
149
149
|
env_dict = None
|
|
@@ -164,7 +164,7 @@ def launch(
|
|
|
164
164
|
ports_dict[name] = int(port_num)
|
|
165
165
|
|
|
166
166
|
with spinner("Launching instance..."):
|
|
167
|
-
job =
|
|
167
|
+
job = client.jobs.create(
|
|
168
168
|
image=image,
|
|
169
169
|
command=command,
|
|
170
170
|
gpu_type=gpu,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""hyper jobs commands"""
|
|
2
2
|
import typer
|
|
3
3
|
from typing import Optional
|
|
4
4
|
from hypercli import C3
|
|
@@ -17,9 +17,9 @@ def list_jobs(
|
|
|
17
17
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
18
18
|
):
|
|
19
19
|
"""List all jobs"""
|
|
20
|
-
|
|
20
|
+
client = get_client()
|
|
21
21
|
with spinner("Fetching jobs..."):
|
|
22
|
-
jobs =
|
|
22
|
+
jobs = client.jobs.list(state=state)
|
|
23
23
|
|
|
24
24
|
if fmt == "json":
|
|
25
25
|
output(jobs, "json")
|
|
@@ -36,9 +36,9 @@ def get_job(
|
|
|
36
36
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
37
37
|
):
|
|
38
38
|
"""Get job details"""
|
|
39
|
-
|
|
39
|
+
client = get_client()
|
|
40
40
|
with spinner("Fetching job..."):
|
|
41
|
-
job =
|
|
41
|
+
job = client.jobs.get(job_id)
|
|
42
42
|
output(job, fmt)
|
|
43
43
|
|
|
44
44
|
|
|
@@ -48,13 +48,13 @@ def logs(
|
|
|
48
48
|
follow: bool = typer.Option(False, "--follow", "-f", help="Stream logs"),
|
|
49
49
|
):
|
|
50
50
|
"""Get job logs"""
|
|
51
|
-
|
|
51
|
+
client = get_client()
|
|
52
52
|
|
|
53
53
|
if follow:
|
|
54
54
|
_follow_job(job_id)
|
|
55
55
|
else:
|
|
56
56
|
with spinner("Fetching logs..."):
|
|
57
|
-
logs_str =
|
|
57
|
+
logs_str = client.jobs.logs(job_id)
|
|
58
58
|
console.print(logs_str)
|
|
59
59
|
|
|
60
60
|
|
|
@@ -65,13 +65,13 @@ def metrics(
|
|
|
65
65
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
66
66
|
):
|
|
67
67
|
"""Get job GPU metrics"""
|
|
68
|
-
|
|
68
|
+
client = get_client()
|
|
69
69
|
|
|
70
70
|
if watch:
|
|
71
71
|
_watch_metrics(job_id)
|
|
72
72
|
else:
|
|
73
73
|
with spinner("Fetching metrics..."):
|
|
74
|
-
m =
|
|
74
|
+
m = client.jobs.metrics(job_id)
|
|
75
75
|
if fmt == "json":
|
|
76
76
|
output(m, "json")
|
|
77
77
|
else:
|
|
@@ -83,9 +83,9 @@ def cancel(
|
|
|
83
83
|
job_id: str = typer.Argument(..., help="Job ID"),
|
|
84
84
|
):
|
|
85
85
|
"""Cancel a running job"""
|
|
86
|
-
|
|
86
|
+
client = get_client()
|
|
87
87
|
with spinner("Cancelling job..."):
|
|
88
|
-
|
|
88
|
+
client.jobs.cancel(job_id)
|
|
89
89
|
success(f"Job {job_id} cancelled")
|
|
90
90
|
|
|
91
91
|
|
|
@@ -96,9 +96,9 @@ def extend(
|
|
|
96
96
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
97
97
|
):
|
|
98
98
|
"""Extend job runtime"""
|
|
99
|
-
|
|
99
|
+
client = get_client()
|
|
100
100
|
with spinner("Extending runtime..."):
|
|
101
|
-
job =
|
|
101
|
+
job = client.jobs.extend(job_id, runtime)
|
|
102
102
|
if fmt == "json":
|
|
103
103
|
output(job, "json")
|
|
104
104
|
else:
|
|
@@ -178,12 +178,12 @@ def _watch_metrics(job_id: str):
|
|
|
178
178
|
import time
|
|
179
179
|
from rich.live import Live
|
|
180
180
|
|
|
181
|
-
|
|
181
|
+
client = get_client()
|
|
182
182
|
|
|
183
183
|
with Live(console=console, refresh_per_second=2) as live:
|
|
184
184
|
while True:
|
|
185
185
|
try:
|
|
186
|
-
m =
|
|
186
|
+
m = client.jobs.metrics(job_id)
|
|
187
187
|
live.update(_render_metrics(m))
|
|
188
188
|
time.sleep(1)
|
|
189
189
|
except KeyboardInterrupt:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""hyper renders commands"""
|
|
2
2
|
import time
|
|
3
3
|
import typer
|
|
4
4
|
from typing import Optional
|
|
@@ -20,9 +20,9 @@ def list_renders(
|
|
|
20
20
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
21
21
|
):
|
|
22
22
|
"""List all renders"""
|
|
23
|
-
|
|
23
|
+
client = get_client()
|
|
24
24
|
with spinner("Fetching renders..."):
|
|
25
|
-
renders =
|
|
25
|
+
renders = client.renders.list(state=state, template=template, type=type)
|
|
26
26
|
|
|
27
27
|
if fmt == "json":
|
|
28
28
|
output(renders, "json")
|
|
@@ -39,9 +39,9 @@ def get_render(
|
|
|
39
39
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
40
40
|
):
|
|
41
41
|
"""Get render details"""
|
|
42
|
-
|
|
42
|
+
client = get_client()
|
|
43
43
|
with spinner("Fetching render..."):
|
|
44
|
-
render =
|
|
44
|
+
render = client.renders.get(render_id)
|
|
45
45
|
output(render, fmt)
|
|
46
46
|
|
|
47
47
|
|
|
@@ -57,7 +57,7 @@ def create_render(
|
|
|
57
57
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
58
58
|
):
|
|
59
59
|
"""Create a new render"""
|
|
60
|
-
|
|
60
|
+
client = get_client()
|
|
61
61
|
|
|
62
62
|
params = {
|
|
63
63
|
"template": template,
|
|
@@ -68,7 +68,7 @@ def create_render(
|
|
|
68
68
|
params["region"] = region
|
|
69
69
|
|
|
70
70
|
with spinner("Creating render..."):
|
|
71
|
-
render =
|
|
71
|
+
render = client.renders.create(params=params, render_type=render_type, notify_url=notify_url)
|
|
72
72
|
|
|
73
73
|
if fmt == "json" and not wait:
|
|
74
74
|
output(render, "json")
|
|
@@ -87,13 +87,13 @@ def status(
|
|
|
87
87
|
fmt: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
88
88
|
):
|
|
89
89
|
"""Get render status"""
|
|
90
|
-
|
|
90
|
+
client = get_client()
|
|
91
91
|
|
|
92
92
|
if watch:
|
|
93
93
|
_watch_status(c3, render_id)
|
|
94
94
|
else:
|
|
95
95
|
with spinner("Fetching status..."):
|
|
96
|
-
s =
|
|
96
|
+
s = client.renders.status(render_id)
|
|
97
97
|
output(s, fmt)
|
|
98
98
|
|
|
99
99
|
|
|
@@ -102,9 +102,9 @@ def cancel(
|
|
|
102
102
|
render_id: str = typer.Argument(..., help="Render ID"),
|
|
103
103
|
):
|
|
104
104
|
"""Cancel a render"""
|
|
105
|
-
|
|
105
|
+
client = get_client()
|
|
106
106
|
with spinner("Cancelling render..."):
|
|
107
|
-
|
|
107
|
+
client.renders.cancel(render_id)
|
|
108
108
|
success(f"Render {render_id} cancelled")
|
|
109
109
|
|
|
110
110
|
|
|
@@ -113,7 +113,7 @@ def _wait_for_render(c3: C3, render_id: str, fmt: str, poll_interval: float = 2.
|
|
|
113
113
|
console.print("Waiting for completion...")
|
|
114
114
|
|
|
115
115
|
while True:
|
|
116
|
-
status =
|
|
116
|
+
status = client.renders.status(render_id)
|
|
117
117
|
progress_str = f" ({status.progress:.0%})" if status.progress is not None else ""
|
|
118
118
|
console.print(f" State: {status.state}{progress_str}")
|
|
119
119
|
|
|
@@ -122,7 +122,7 @@ def _wait_for_render(c3: C3, render_id: str, fmt: str, poll_interval: float = 2.
|
|
|
122
122
|
time.sleep(poll_interval)
|
|
123
123
|
|
|
124
124
|
# Get final render details
|
|
125
|
-
render =
|
|
125
|
+
render = client.renders.get(render_id)
|
|
126
126
|
|
|
127
127
|
if fmt == "json":
|
|
128
128
|
output(render, "json")
|
|
@@ -163,11 +163,11 @@ def _watch_status(c3: C3, render_id: str, poll_interval: float = 2.0):
|
|
|
163
163
|
with Live(console=console, refresh_per_second=2) as live:
|
|
164
164
|
while True:
|
|
165
165
|
try:
|
|
166
|
-
status =
|
|
166
|
+
status = client.renders.status(render_id)
|
|
167
167
|
render = None
|
|
168
168
|
|
|
169
169
|
if status.state in ("completed", "failed", "cancelled"):
|
|
170
|
-
render =
|
|
170
|
+
render = client.renders.get(render_id)
|
|
171
171
|
live.update(render_status_panel(status, render))
|
|
172
172
|
break
|
|
173
173
|
|
|
@@ -164,7 +164,7 @@ async def _run_job_monitor_async(
|
|
|
164
164
|
stop_on_status_complete: bool = False,
|
|
165
165
|
):
|
|
166
166
|
"""Async job monitor - uses SDK LogStream for logs"""
|
|
167
|
-
|
|
167
|
+
client = C3()
|
|
168
168
|
logs: deque[str] = deque(maxlen=MAX_LOG_LINES)
|
|
169
169
|
log_stream: Optional[LogStream] = None
|
|
170
170
|
log_task: Optional[asyncio.Task] = None
|
|
@@ -180,7 +180,7 @@ async def _run_job_monitor_async(
|
|
|
180
180
|
with console.status("[cyan]Connecting..."):
|
|
181
181
|
while not job:
|
|
182
182
|
try:
|
|
183
|
-
job =
|
|
183
|
+
job = client.jobs.get(job_id)
|
|
184
184
|
except Exception:
|
|
185
185
|
await asyncio.sleep(1)
|
|
186
186
|
|
|
@@ -218,7 +218,7 @@ async def _run_job_monitor_async(
|
|
|
218
218
|
while not stop_event.is_set():
|
|
219
219
|
try:
|
|
220
220
|
if job and job.state in ("assigned", "running"):
|
|
221
|
-
metrics = await asyncio.to_thread(
|
|
221
|
+
metrics = await asyncio.to_thread(client.jobs.metrics, job_id)
|
|
222
222
|
except Exception:
|
|
223
223
|
pass
|
|
224
224
|
await asyncio.sleep(2)
|
|
@@ -228,7 +228,7 @@ async def _run_job_monitor_async(
|
|
|
228
228
|
nonlocal job, log_stream, log_task, ws_status
|
|
229
229
|
while not stop_event.is_set():
|
|
230
230
|
try:
|
|
231
|
-
job = await asyncio.to_thread(
|
|
231
|
+
job = await asyncio.to_thread(client.jobs.get, job_id)
|
|
232
232
|
|
|
233
233
|
# Start log stream when job is ready
|
|
234
234
|
if job.state in ("assigned", "running") and log_stream is None and job.job_key:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""hyper user commands"""
|
|
2
2
|
import typer
|
|
3
3
|
from hypercli import C3
|
|
4
4
|
from .output import output, spinner
|
|
@@ -13,7 +13,7 @@ def user_info(
|
|
|
13
13
|
):
|
|
14
14
|
"""Get current user info"""
|
|
15
15
|
if ctx.invoked_subcommand is None:
|
|
16
|
-
|
|
16
|
+
client = C3()
|
|
17
17
|
with spinner("Fetching user info..."):
|
|
18
|
-
user =
|
|
18
|
+
user = client.user.get()
|
|
19
19
|
output(user, fmt)
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hypercli-cli"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.5"
|
|
8
8
|
description = "CLI for HyperCLI - GPU orchestration and LLM API"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -32,6 +32,7 @@ hyper = "hypercli_cli.cli:cli"
|
|
|
32
32
|
[project.urls]
|
|
33
33
|
Homepage = "https://hypercli.com"
|
|
34
34
|
Documentation = "https://docs.hypercli.com"
|
|
35
|
+
Repository = "https://github.com/hypercli/monorepo"
|
|
35
36
|
|
|
36
37
|
[tool.hatch.build.targets.wheel]
|
|
37
38
|
packages = ["hypercli_cli"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|