hypercli-cli 0.8.3__tar.gz → 0.8.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.
Files changed (21) hide show
  1. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/PKG-INFO +1 -1
  2. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/claw.py +174 -4
  3. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/pyproject.toml +1 -1
  4. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/.gitignore +0 -0
  5. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/README.md +0 -0
  6. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/__init__.py +0 -0
  7. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/billing.py +0 -0
  8. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/cli.py +0 -0
  9. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/comfyui.py +0 -0
  10. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/flow.py +0 -0
  11. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/instances.py +0 -0
  12. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/jobs.py +0 -0
  13. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/keys.py +0 -0
  14. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/llm.py +0 -0
  15. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/onboard.py +0 -0
  16. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/output.py +0 -0
  17. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/renders.py +0 -0
  18. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/tui/__init__.py +0 -0
  19. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/tui/job_monitor.py +0 -0
  20. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/user.py +0 -0
  21. {hypercli_cli-0.8.3 → hypercli_cli-0.8.5}/hypercli_cli/wallet.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypercli-cli
3
- Version: 0.8.3
3
+ Version: 0.8.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
@@ -318,13 +318,18 @@ def fetch_models(api_key: str, api_base: str = PROD_API_BASE) -> list[dict]:
318
318
  )
319
319
  resp.raise_for_status()
320
320
  data = resp.json().get("data", [])
321
+ # Known model metadata (context windows, reasoning, etc.)
322
+ MODEL_META = {
323
+ "kimi-k2.5": {"name": "Kimi K2.5", "reasoning": False, "contextWindow": 262144},
324
+ "glm-5": {"name": "GLM-5", "reasoning": True, "contextWindow": 202752},
325
+ }
321
326
  return [
322
327
  {
323
328
  "id": m["id"],
324
- "name": m["id"].replace("-", " ").title(),
325
- "reasoning": False,
329
+ "name": MODEL_META.get(m["id"], {}).get("name", m["id"].replace("-", " ").title()),
330
+ "reasoning": MODEL_META.get(m["id"], {}).get("reasoning", False),
326
331
  "input": ["text"],
327
- "contextWindow": 200000,
332
+ "contextWindow": MODEL_META.get(m["id"], {}).get("contextWindow", 200000),
328
333
  }
329
334
  for m in data
330
335
  if m.get("id")
@@ -338,7 +343,14 @@ def fetch_models(api_key: str, api_base: str = PROD_API_BASE) -> list[dict]:
338
343
  "name": "Kimi K2.5",
339
344
  "reasoning": False,
340
345
  "input": ["text"],
341
- "contextWindow": 200000,
346
+ "contextWindow": 262144,
347
+ },
348
+ {
349
+ "id": "glm-5",
350
+ "name": "GLM-5",
351
+ "reasoning": True,
352
+ "input": ["text"],
353
+ "contextWindow": 202752,
342
354
  },
343
355
  ]
344
356
 
@@ -404,3 +416,161 @@ def openclaw_setup(
404
416
  if default:
405
417
  console.print(f" default model: hyperclaw/{models[0]['id']}")
406
418
  console.print("\nRun: [bold]openclaw gateway restart[/bold]")
419
+
420
+
421
+ # ---------------------------------------------------------------------------
422
+ # hyper claw config — generate / apply provider configs for various tools
423
+ # ---------------------------------------------------------------------------
424
+
425
+ def _resolve_api_key(key: str | None) -> str:
426
+ """Resolve API key from --key flag or ~/.hypercli/claw-key.json."""
427
+ if key:
428
+ return key
429
+ if CLAW_KEY_PATH.exists():
430
+ with open(CLAW_KEY_PATH) as f:
431
+ k = json.load(f).get("key", "")
432
+ if k:
433
+ return k
434
+ console.print("[red]❌ No API key found.[/red]")
435
+ console.print("Either pass [bold]--key sk-...[/bold] or subscribe first:")
436
+ console.print(" [bold]hyper claw subscribe 1aiu[/bold]")
437
+ raise typer.Exit(1)
438
+
439
+
440
+ def _config_openclaw(api_key: str, models: list[dict]) -> dict:
441
+ """OpenClaw openclaw.json provider snippet."""
442
+ return {
443
+ "models": {
444
+ "mode": "merge",
445
+ "providers": {
446
+ "hyperclaw": {
447
+ "baseUrl": "https://api.hyperclaw.app/v1",
448
+ "apiKey": api_key,
449
+ "api": "openai-completions",
450
+ "models": models,
451
+ }
452
+ }
453
+ },
454
+ "agents": {
455
+ "defaults": {
456
+ "models": {
457
+ **{f"hyperclaw/{m['id']}": {"alias": m['id'].split('-')[0]} for m in models}
458
+ }
459
+ }
460
+ }
461
+ }
462
+
463
+
464
+ def _config_opencode(api_key: str, models: list[dict]) -> dict:
465
+ """OpenCode opencode.json provider snippet."""
466
+ model_entries = {}
467
+ for m in models:
468
+ model_entries[m["id"]] = {"name": m["id"]}
469
+ return {
470
+ "$schema": "https://opencode.ai/config.json",
471
+ "provider": {
472
+ "hypercli": {
473
+ "npm": "@ai-sdk/openai-compatible",
474
+ "name": "HyperCLI",
475
+ "options": {
476
+ "baseURL": "https://api.hyperclaw.app/v1",
477
+ "apiKey": api_key,
478
+ },
479
+ "models": model_entries,
480
+ }
481
+ }
482
+ }
483
+
484
+
485
+ def _config_env(api_key: str, models: list[dict]) -> str:
486
+ """Shell env vars for generic OpenAI-compatible tools."""
487
+ lines = [
488
+ f'export OPENAI_API_KEY="{api_key}"',
489
+ 'export OPENAI_BASE_URL="https://api.hyperclaw.app/v1"',
490
+ f'# Available models: {", ".join(m["id"] for m in models)}',
491
+ ]
492
+ return "\n".join(lines)
493
+
494
+
495
+ FORMAT_CHOICES = ["openclaw", "opencode", "env"]
496
+
497
+
498
+ @app.command("config")
499
+ def config_cmd(
500
+ format: str = typer.Argument(
501
+ None,
502
+ help=f"Output format: {', '.join(FORMAT_CHOICES)}. Omit to show all.",
503
+ ),
504
+ key: str = typer.Option(None, "--key", "-k", help="API key (sk-...). Falls back to ~/.hypercli/claw-key.json"),
505
+ apply: bool = typer.Option(False, "--apply", help="Write config to the appropriate file (openclaw/opencode only)"),
506
+ dev: bool = typer.Option(False, "--dev", help="Use dev API"),
507
+ ):
508
+ """Generate provider configs for OpenClaw, OpenCode, and other tools.
509
+
510
+ Examples:
511
+ hyper claw config # Show all configs
512
+ hyper claw config openclaw # OpenClaw snippet
513
+ hyper claw config opencode --key sk-... # OpenCode with explicit key
514
+ hyper claw config openclaw --apply # Write directly to openclaw.json
515
+ hyper claw config env # Shell export lines
516
+ """
517
+ api_key = _resolve_api_key(key)
518
+ api_base = DEV_API_BASE if dev else PROD_API_BASE
519
+
520
+ # Validate key & fetch models
521
+ console.print(f"[dim]Validating key against {api_base}...[/dim]")
522
+ models = fetch_models(api_key, api_base)
523
+ model_names = ", ".join(m["id"] for m in models)
524
+ console.print(f"[green]✓[/green] Key valid — models: [bold]{model_names}[/bold]\n")
525
+
526
+ formats = [format] if format else FORMAT_CHOICES
527
+ for fmt in formats:
528
+ if fmt not in FORMAT_CHOICES:
529
+ console.print(f"[red]Unknown format: {fmt}[/red]")
530
+ console.print(f"Choose from: {', '.join(FORMAT_CHOICES)}")
531
+ raise typer.Exit(1)
532
+
533
+ for fmt in formats:
534
+ if fmt == "openclaw":
535
+ snippet = _config_openclaw(api_key, models)
536
+ _show_snippet("OpenClaw", "~/.openclaw/openclaw.json", snippet, apply, OPENCLAW_CONFIG_PATH)
537
+ elif fmt == "opencode":
538
+ snippet = _config_opencode(api_key, models)
539
+ target = Path.cwd() / "opencode.json"
540
+ _show_snippet("OpenCode", "opencode.json", snippet, apply, target)
541
+ elif fmt == "env":
542
+ console.print("[bold]── Shell Environment ──[/bold]")
543
+ console.print(_config_env(api_key, models))
544
+ console.print()
545
+
546
+
547
+ def _show_snippet(name: str, path_hint: str, data: dict, apply: bool, target_path: Path):
548
+ """Print a JSON snippet and optionally apply it."""
549
+ console.print(f"[bold]── {name} ({path_hint}) ──[/bold]")
550
+ formatted = json.dumps(data, indent=2)
551
+ console.print(formatted)
552
+ console.print()
553
+
554
+ if apply:
555
+ if target_path.exists():
556
+ with open(target_path) as f:
557
+ existing = json.load(f)
558
+ _deep_merge(existing, data)
559
+ merged = existing
560
+ else:
561
+ merged = data
562
+
563
+ target_path.parent.mkdir(parents=True, exist_ok=True)
564
+ with open(target_path, "w") as f:
565
+ json.dump(merged, f, indent=2)
566
+ f.write("\n")
567
+ console.print(f"[green]✅ Written to {target_path}[/green]\n")
568
+
569
+
570
+ def _deep_merge(base: dict, overlay: dict):
571
+ """Recursively merge overlay into base (mutates base)."""
572
+ for k, v in overlay.items():
573
+ if k in base and isinstance(base[k], dict) and isinstance(v, dict):
574
+ _deep_merge(base[k], v)
575
+ else:
576
+ base[k] = v
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hypercli-cli"
7
- version = "0.8.3"
7
+ version = "0.8.5"
8
8
  description = "CLI for HyperCLI - GPU orchestration and LLM API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes
File without changes