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 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 aggregated progress across all layers
314
- import re
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
- # Parse: "abc123: Downloading 10.5MB/50MB" or "abc123: Extracting 10MB/50MB"
348
- size_match = re.search(
349
- r"([a-f0-9]+):\s*(Downloading|Extracting)\s+(\d+\.?\d*\s*[kMGT]?B)/(\d+\.?\d*\s*[kMGT]?B)",
350
- line, re.IGNORECASE
351
- )
352
- if size_match:
353
- layer_id = size_match.group(1)
354
- phase = size_match.group(2)
355
- current = parse_size(size_match.group(3))
356
- total = parse_size(size_match.group(4))
357
- layer_progress[layer_id] = {"current": current, "total": total, "phase": phase}
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
- with console.status("[dim]Launching Docker containers (this may take a minute)...[/dim]"):
464
- result = runner.run_from_assignment(
465
- assignment=assignment,
466
- compose_yaml=compose_yaml,
467
- files_zip=files_zip,
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hte-cli
3
- Version: 0.2.12
3
+ Version: 0.2.14
4
4
  Summary: Human Time-to-Completion Evaluation CLI
5
5
  Project-URL: Homepage, https://github.com/sean-peters-au/lyptus-mono
6
6
  Author: Lyptus Research
@@ -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=VnUp0A71JUw35VaN_Xlbusn6_2LD2ZkcnenO3LBc0LE,46464
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.12.dist-info/METADATA,sha256=mpWz2A-3JiJquxws5sM1KdCclRqDw3sGGYXeY6XPjhY,3768
13
- hte_cli-0.2.12.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
- hte_cli-0.2.12.dist-info/entry_points.txt,sha256=XbyEEi1H14DFAt0Kdl22e_IRVEGzimSzYSh5HlhKlFA,41
15
- hte_cli-0.2.12.dist-info/RECORD,,
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,,