Spaces:
Running
Running
File size: 3,302 Bytes
9c84f9d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | """Project management commands — local YAML or remote API."""
import click
from solar_eval.cli.config import config
from solar_eval.cli.formatters import format_projects_table
def _resolve_project_id(client, name_or_id: str) -> str:
"""Resolve a project name to its API ID (remote mode only)."""
if len(name_or_id) == 24:
try:
int(name_or_id, 16)
return name_or_id
except ValueError:
pass
projects = client.get("/api/projects")
for p in projects:
if p["name"] == name_or_id:
return p["id"]
raise click.ClickException(f"Project not found: {name_or_id}")
@click.group("projects")
def projects_group() -> None:
"""Manage evaluation projects."""
@projects_group.command("list")
@click.pass_context
def list_projects(ctx: click.Context) -> None:
"""List projects (from YAML locally, or from API remotely)."""
cfg = ctx.obj["config"]
if cfg.is_remote:
from solar_eval.cli.client import EvalClient
client = EvalClient(cfg.remote_url, cfg.timeout)
projects = client.get("/api/projects")
if not projects:
click.secho("No projects found.", fg="yellow")
return
click.secho(format_projects_table(projects), fg="blue")
else:
from solar_eval.core.project_loader import load_all_project_configs
configs = load_all_project_configs(cfg.projects_dir, cfg.config_dirs)
if not configs:
click.secho(f"No project YAML files in {cfg.projects_dir}", fg="yellow")
return
rows = [{
"name": c["name"],
"display_name": c.get("display_name", c["name"]),
"description": c.get("description", ""),
"task_count": len(c.get("tasks", [])),
} for c in configs]
click.secho(format_projects_table(rows), fg="blue")
@projects_group.command("show")
@click.argument("name")
@click.pass_context
def show_project(ctx: click.Context, name: str) -> None:
"""Show project details by name."""
cfg = ctx.obj["config"]
if cfg.is_remote:
from solar_eval.cli.client import EvalClient
client = EvalClient(cfg.remote_url, cfg.timeout)
project_id = _resolve_project_id(client, name)
project = client.get(f"/api/projects/{project_id}")
else:
from solar_eval.core.project_loader import load_all_project_configs
configs = load_all_project_configs(cfg.projects_dir, cfg.config_dirs)
project = next((c for c in configs if c["name"] == name), None)
if not project:
raise click.ClickException(f"Project not found: {name}")
project["display_name"] = project.get("display_name", name)
project["config"] = project
click.secho(f"Project: {project.get('display_name', name)}", fg="blue", bold=True)
click.echo(f" Name: {project.get('name', name)}")
click.echo(f" Description: {project.get('description', '-')}")
tasks = project.get("config", {}).get("tasks", project.get("tasks", []))
if tasks:
click.echo(f" Tasks ({len(tasks)}):")
for t in tasks:
ev = t.get("evaluator", {})
click.echo(f" - {t['name']} (pipeline: {t.get('pipeline', '?')}, evaluator: {ev.get('type', '?')})")
|