hte-cli 0.2.12__py3-none-any.whl → 0.2.14__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.
- hte_cli/cli.py +29 -111
- {hte_cli-0.2.12.dist-info → hte_cli-0.2.14.dist-info}/METADATA +1 -1
- {hte_cli-0.2.12.dist-info → hte_cli-0.2.14.dist-info}/RECORD +5 -5
- {hte_cli-0.2.12.dist-info → hte_cli-0.2.14.dist-info}/WHEEL +0 -0
- {hte_cli-0.2.12.dist-info → hte_cli-0.2.14.dist-info}/entry_points.txt +0 -0
hte_cli/cli.py
CHANGED
|
@@ -310,113 +310,21 @@ def session_join(ctx, session_id: str, force_setup: bool):
|
|
|
310
310
|
cached_images.append(img)
|
|
311
311
|
continue
|
|
312
312
|
|
|
313
|
-
# Need to pull - show
|
|
314
|
-
|
|
315
|
-
layer_progress: dict[str, dict] = {} # layer_id -> {current, total, phase}
|
|
316
|
-
last_display = [""]
|
|
317
|
-
|
|
318
|
-
def parse_size(s: str) -> float:
|
|
319
|
-
"""Parse size string like '10.5MB' or '1.2GB' to bytes."""
|
|
320
|
-
if not s:
|
|
321
|
-
return 0
|
|
322
|
-
s = s.strip()
|
|
323
|
-
multipliers = {"B": 1, "KB": 1024, "MB": 1024**2, "GB": 1024**3}
|
|
324
|
-
for suffix, mult in multipliers.items():
|
|
325
|
-
if s.upper().endswith(suffix):
|
|
326
|
-
try:
|
|
327
|
-
return float(s[:-len(suffix)].strip()) * mult
|
|
328
|
-
except ValueError:
|
|
329
|
-
return 0
|
|
330
|
-
try:
|
|
331
|
-
return float(s)
|
|
332
|
-
except ValueError:
|
|
333
|
-
return 0
|
|
334
|
-
|
|
335
|
-
def format_size(b: float) -> str:
|
|
336
|
-
"""Format bytes to human readable."""
|
|
337
|
-
if b >= 1024**3:
|
|
338
|
-
return f"{b/1024**3:.1f}GB"
|
|
339
|
-
elif b >= 1024**2:
|
|
340
|
-
return f"{b/1024**2:.0f}MB"
|
|
341
|
-
elif b >= 1024:
|
|
342
|
-
return f"{b/1024:.0f}KB"
|
|
343
|
-
return f"{b:.0f}B"
|
|
344
|
-
|
|
313
|
+
# Need to pull - show progress
|
|
314
|
+
last_status = ["connecting..."]
|
|
345
315
|
with console.status(f"[yellow]↓[/yellow] {short_name} [dim]connecting...[/dim]") as status:
|
|
346
316
|
def show_progress(image: str, line: str):
|
|
347
|
-
#
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
line,
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
# Check for completed layers
|
|
360
|
-
complete_match = re.search(r"([a-f0-9]+):\s*(Pull complete|Download complete|Already exists)", line)
|
|
361
|
-
if complete_match:
|
|
362
|
-
layer_id = complete_match.group(1)
|
|
363
|
-
if layer_id in layer_progress:
|
|
364
|
-
layer_progress[layer_id]["current"] = layer_progress[layer_id]["total"]
|
|
365
|
-
layer_progress[layer_id]["phase"] = "done"
|
|
366
|
-
|
|
367
|
-
# Track waiting layers
|
|
368
|
-
waiting_match = re.search(r"([a-f0-9]+):\s*Waiting", line)
|
|
369
|
-
if waiting_match:
|
|
370
|
-
layer_id = waiting_match.group(1)
|
|
371
|
-
if layer_id not in layer_progress:
|
|
372
|
-
layer_progress[layer_id] = {"current": 0, "total": 0, "phase": "waiting"}
|
|
373
|
-
|
|
374
|
-
# Aggregate progress
|
|
375
|
-
total_current = sum(lp.get("current", 0) for lp in layer_progress.values())
|
|
376
|
-
total_size = sum(lp.get("total", 0) for lp in layer_progress.values())
|
|
377
|
-
downloading = sum(1 for lp in layer_progress.values() if lp.get("phase") == "Downloading")
|
|
378
|
-
extracting = sum(1 for lp in layer_progress.values() if lp.get("phase") == "Extracting")
|
|
379
|
-
done_layers = sum(1 for lp in layer_progress.values() if lp.get("phase") == "done")
|
|
380
|
-
waiting = sum(1 for lp in layer_progress.values() if lp.get("phase") == "waiting")
|
|
381
|
-
total_layers = len(layer_progress)
|
|
382
|
-
|
|
383
|
-
# Find largest active layer for detail display
|
|
384
|
-
active_layers = [(lid, lp) for lid, lp in layer_progress.items()
|
|
385
|
-
if lp.get("phase") in ("Downloading", "Extracting") and lp.get("total", 0) > 0]
|
|
386
|
-
largest_layer = None
|
|
387
|
-
if active_layers:
|
|
388
|
-
largest_layer = max(active_layers, key=lambda x: x[1].get("total", 0))
|
|
389
|
-
|
|
390
|
-
# Build display
|
|
391
|
-
if total_size > 1024 * 1024: # >1MB meaningful data
|
|
392
|
-
display = f"{format_size(total_current)}/{format_size(total_size)}"
|
|
393
|
-
# Show largest layer progress
|
|
394
|
-
if largest_layer:
|
|
395
|
-
lid, lp = largest_layer
|
|
396
|
-
pct = (lp["current"] / lp["total"] * 100) if lp["total"] > 0 else 0
|
|
397
|
-
display += f" | {lid[:8]}: {format_size(lp['current'])}/{format_size(lp['total'])} ({pct:.0f}%)"
|
|
398
|
-
elif total_layers > 0:
|
|
399
|
-
# Show layer counts
|
|
400
|
-
parts = []
|
|
401
|
-
if downloading > 0:
|
|
402
|
-
parts.append(f"{downloading} downloading")
|
|
403
|
-
if extracting > 0:
|
|
404
|
-
parts.append(f"{extracting} extracting")
|
|
405
|
-
if done_layers > 0:
|
|
406
|
-
parts.append(f"{done_layers} done")
|
|
407
|
-
if waiting > 0:
|
|
408
|
-
parts.append(f"{waiting} waiting")
|
|
409
|
-
display = ", ".join(parts) if parts else "starting..."
|
|
410
|
-
elif "Pulling" in line:
|
|
411
|
-
display = "preparing..."
|
|
412
|
-
elif line.strip():
|
|
413
|
-
display = line[:40]
|
|
414
|
-
else:
|
|
415
|
-
return
|
|
416
|
-
|
|
417
|
-
if display != last_display[0]:
|
|
418
|
-
last_display[0] = display
|
|
419
|
-
status.update(f"[yellow]↓[/yellow] {short_name} [dim]{display}[/dim]")
|
|
317
|
+
# Show docker output directly - includes MB progress from PTY
|
|
318
|
+
# Lines look like: "abc123: Downloading 360.9MB/4.075GB"
|
|
319
|
+
if ": " in line:
|
|
320
|
+
parts = line.split(": ", 1)
|
|
321
|
+
if len(parts) == 2:
|
|
322
|
+
layer_id = parts[0][-8:]
|
|
323
|
+
layer_status = parts[1][:45]
|
|
324
|
+
display = f"{layer_id}: {layer_status}"
|
|
325
|
+
if display != last_status[0]:
|
|
326
|
+
last_status[0] = display
|
|
327
|
+
status.update(f"[yellow]↓[/yellow] {short_name} [dim]{display}[/dim]")
|
|
420
328
|
|
|
421
329
|
success = pull_image_with_progress(img, on_progress=show_progress)
|
|
422
330
|
|
|
@@ -446,6 +354,15 @@ def session_join(ctx, session_id: str, force_setup: bool):
|
|
|
446
354
|
console.print("[dim]Skipping setup (use --force-setup to re-run)[/dim]")
|
|
447
355
|
console.print()
|
|
448
356
|
|
|
357
|
+
# Check if session was cancelled during setup
|
|
358
|
+
try:
|
|
359
|
+
updated_session = api.get_session(session_id)
|
|
360
|
+
if updated_session.get("status") == "cancelled":
|
|
361
|
+
console.print("[yellow]Session was cancelled. Exiting.[/yellow]")
|
|
362
|
+
sys.exit(0)
|
|
363
|
+
except APIError:
|
|
364
|
+
pass # Continue if we can't check - server might be temporarily unavailable
|
|
365
|
+
|
|
449
366
|
# Step 4: Show instructions
|
|
450
367
|
if session_info.get("instructions"):
|
|
451
368
|
console.print(Panel(session_info["instructions"], title="Task Instructions"))
|
|
@@ -454,18 +371,19 @@ def session_join(ctx, session_id: str, force_setup: bool):
|
|
|
454
371
|
# Step 3: Run the task using TaskRunner
|
|
455
372
|
step_num = "3" if (not is_reconnect or force_setup) and images else "2" if (not is_reconnect or force_setup) else "1"
|
|
456
373
|
console.print(f"[bold]Step {step_num}:[/bold] Starting task environment...")
|
|
374
|
+
console.print("[dim]Launching Docker containers...[/dim]")
|
|
375
|
+
console.print()
|
|
457
376
|
|
|
458
377
|
events.docker_started()
|
|
459
378
|
|
|
460
379
|
runner = TaskRunner()
|
|
461
380
|
eval_log_bytes = None
|
|
462
381
|
try:
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
)
|
|
382
|
+
result = runner.run_from_assignment(
|
|
383
|
+
assignment=assignment,
|
|
384
|
+
compose_yaml=compose_yaml,
|
|
385
|
+
files_zip=files_zip,
|
|
386
|
+
)
|
|
469
387
|
# Read eval log before cleanup
|
|
470
388
|
if result.eval_log_path and result.eval_log_path.exists():
|
|
471
389
|
eval_log_bytes = result.eval_log_path.read_bytes()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
hte_cli/__init__.py,sha256=fDGXp-r8bIoLtlQnn5xJ_CpwMhonvk9bGjZQsjA2mDI,914
|
|
2
2
|
hte_cli/__main__.py,sha256=63n0gNGfskidWDU0aAIF2N8lylVCLYKVIkrN9QiORoo,107
|
|
3
3
|
hte_cli/api_client.py,sha256=m42kfFZS72Nu_VuDwxRsLNy4ziCcvgk7KNWBh9gwqy0,9257
|
|
4
|
-
hte_cli/cli.py,sha256=
|
|
4
|
+
hte_cli/cli.py,sha256=d1_FhXeGkzrFucEOZd3uZhFPffvk4aRHKRbG9pZz9qo,41590
|
|
5
5
|
hte_cli/config.py,sha256=42Xv__YMSeRLs2zhGukJkIXFKtnBtYCHnONfViGyt2g,3387
|
|
6
6
|
hte_cli/errors.py,sha256=1J5PpxcUKBu6XjigMMCPOq4Zc12tnv8LhAsiaVFWLQM,2762
|
|
7
7
|
hte_cli/events.py,sha256=Zn-mroqaLHNzdT4DFf8st1Qclglshihdc09dBfCN070,5522
|
|
@@ -9,7 +9,7 @@ hte_cli/image_utils.py,sha256=TLwJdswUQrSD2bQcAXW03R8j8WG2pbHzd12TWcE7zy4,6418
|
|
|
9
9
|
hte_cli/runner.py,sha256=DhC8FMjHwfLR193iP4thLDRZrNssYA9KH1WYKU2JKeg,13535
|
|
10
10
|
hte_cli/scorers.py,sha256=sFoPJePRt-K191-Ga4cVmrldruJclYXTOLkU_C9nCDI,6025
|
|
11
11
|
hte_cli/version_check.py,sha256=WVZyGy2XfAghQYdd2N9-0Qfg-7pgp9gt4761-PnmacI,1708
|
|
12
|
-
hte_cli-0.2.
|
|
13
|
-
hte_cli-0.2.
|
|
14
|
-
hte_cli-0.2.
|
|
15
|
-
hte_cli-0.2.
|
|
12
|
+
hte_cli-0.2.14.dist-info/METADATA,sha256=91S9qXd9btOSrtUhmnupFoxfrL6iXX0eh_8csVCP1qE,3768
|
|
13
|
+
hte_cli-0.2.14.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
14
|
+
hte_cli-0.2.14.dist-info/entry_points.txt,sha256=XbyEEi1H14DFAt0Kdl22e_IRVEGzimSzYSh5HlhKlFA,41
|
|
15
|
+
hte_cli-0.2.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|