|
1 | 1 | """kalibr verify - Check that Kalibr is configured correctly.""" |
2 | 2 |
|
3 | 3 | import os |
| 4 | +import uuid |
4 | 5 |
|
| 6 | +import httpx |
5 | 7 | import typer |
6 | 8 | from rich.console import Console |
7 | 9 |
|
@@ -44,7 +46,83 @@ def verify() -> None: |
44 | 46 | console.print(" Fix: Ensure your KALIBR_API_KEY and KALIBR_TENANT_ID are valid.") |
45 | 47 | all_ok = False |
46 | 48 |
|
47 | | - # Step 4: Check provider API keys (warning only) |
| 49 | + # Step 4: Live round-trip test |
| 50 | + if all_ok: |
| 51 | + console.print("Testing live connectivity...") |
| 52 | + |
| 53 | + base_url = os.environ.get("KALIBR_INTELLIGENCE_URL", "https://kalibr-intelligence.fly.dev") |
| 54 | + headers = { |
| 55 | + "X-API-Key": api_key, |
| 56 | + "X-Tenant-ID": tenant_id, |
| 57 | + "Content-Type": "application/json", |
| 58 | + } |
| 59 | + test_goal = f"__verify__{uuid.uuid4().hex[:8]}" |
| 60 | + path_id = None |
| 61 | + |
| 62 | + try: |
| 63 | + # Register a test path |
| 64 | + r1 = httpx.post( |
| 65 | + f"{base_url}/api/v1/routing/paths", |
| 66 | + json={"goal": test_goal, "model_id": "gpt-4o-mini", "risk_level": "low"}, |
| 67 | + headers=headers, |
| 68 | + timeout=10, |
| 69 | + ) |
| 70 | + if r1.status_code != 200: |
| 71 | + console.print(f"[red]✗ Intelligence service unreachable: {r1.status_code}[/red]") |
| 72 | + console.print(" Fix: Check that your API key and tenant ID are valid.") |
| 73 | + raise typer.Exit(1) |
| 74 | + path_id = r1.json().get("path_id") |
| 75 | + |
| 76 | + # Request a routing decision |
| 77 | + r2 = httpx.post( |
| 78 | + f"{base_url}/api/v1/routing/decide", |
| 79 | + json={"goal": test_goal, "task_risk_level": "low"}, |
| 80 | + headers=headers, |
| 81 | + timeout=10, |
| 82 | + ) |
| 83 | + if r2.status_code != 200: |
| 84 | + console.print(f"[red]✗ Routing decision failed: {r2.status_code}[/red]") |
| 85 | + raise typer.Exit(1) |
| 86 | + trace_id = r2.json().get("trace_id") |
| 87 | + |
| 88 | + # Report outcome |
| 89 | + r3 = httpx.post( |
| 90 | + f"{base_url}/api/v1/intelligence/report-outcome", |
| 91 | + json={"trace_id": trace_id, "goal": test_goal, "success": True}, |
| 92 | + headers=headers, |
| 93 | + timeout=10, |
| 94 | + ) |
| 95 | + if r3.status_code != 200: |
| 96 | + console.print(f"[red]✗ Outcome reporting failed: {r3.status_code}[/red]") |
| 97 | + raise typer.Exit(1) |
| 98 | + |
| 99 | + console.print("[green]✓ Live round-trip: register → decide → report → OK[/green]") |
| 100 | + |
| 101 | + except typer.Exit: |
| 102 | + all_ok = False |
| 103 | + raise |
| 104 | + except httpx.TimeoutException: |
| 105 | + console.print("[red]✗ Intelligence service timed out[/red]") |
| 106 | + console.print(" Check your network connection or try again in a moment.") |
| 107 | + all_ok = False |
| 108 | + raise typer.Exit(1) |
| 109 | + except Exception as e: |
| 110 | + console.print(f"[red]✗ Connectivity check failed: {e}[/red]") |
| 111 | + all_ok = False |
| 112 | + raise typer.Exit(1) |
| 113 | + finally: |
| 114 | + # Clean up: delete the test path regardless of outcome |
| 115 | + if path_id: |
| 116 | + try: |
| 117 | + httpx.delete( |
| 118 | + f"{base_url}/api/v1/routing/paths/{path_id}", |
| 119 | + headers=headers, |
| 120 | + timeout=5, |
| 121 | + ) |
| 122 | + except Exception: |
| 123 | + pass # Best-effort cleanup |
| 124 | + |
| 125 | + # Step 5: Check provider API keys (warning only) |
48 | 126 | provider_keys = { |
49 | 127 | "ANTHROPIC_API_KEY": "for claude-* models", |
50 | 128 | "OPENAI_API_KEY": "for gpt-* and o1-*, o3-* models", |
|
0 commit comments