Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions scripts/generate-registry-meta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""Pull adapter_metadata.json files from harbor repo and generate registry-meta.json."""

import json
import os
import re
import shutil
import subprocess
import sys
import tempfile

HARBOR_REPO = "git@github.com:harbor-framework/harbor.git"
OUTPUT_PATH = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"src",
"app",
"(home)",
"registry",
"registry-meta.json",
)

BUILDER_PATTERN = re.compile(r"^(.+?)\s*\(([^)]+)\)$")


def parse_builder(raw: str) -> dict:
"""Parse 'Name (email)' into {"name": ..., "email": ...}."""
match = BUILDER_PATTERN.match(raw.strip())
if match:
return {"name": match.group(1).strip(), "email": match.group(2).strip()}
return {"name": raw.strip(), "email": ""}


def main():
clone_dir = tempfile.mkdtemp(prefix="harbor-")

try:
print(f"Cloning {HARBOR_REPO} (shallow)...")
subprocess.run(
["git", "clone", "--depth", "1", HARBOR_REPO, clone_dir],
check=True,
capture_output=True,
text=True,
)

adapters_dir = os.path.join(clone_dir, "adapters")
if not os.path.isdir(adapters_dir):
print("Error: adapters directory not found in harbor repo", file=sys.stderr)
sys.exit(1)

registry_meta: dict[str, dict] = {}
for entry in sorted(os.listdir(adapters_dir)):
metadata_path = os.path.join(adapters_dir, entry, "adapter_metadata.json")
if not os.path.isfile(metadata_path):
continue

with open(metadata_path, "r") as f:
data = json.load(f)

if not isinstance(data, list) or len(data) == 0:
continue

item = data[0]
adapter_name = item.get("adapter_name", entry)

raw_builders = item.get("adapter_builders", [])
if not isinstance(raw_builders, list):
raw_builders = []
contributors = [parse_builder(b) for b in raw_builders]

registry_meta[adapter_name] = {
"contributors": contributors,
"acknowledgement": "2077AI",
}

os.makedirs(os.path.dirname(OUTPUT_PATH), exist_ok=True)
with open(OUTPUT_PATH, "w") as f:
json.dump(registry_meta, f, indent=2)
f.write("\n")

print(f"Generated {OUTPUT_PATH} with {len(registry_meta)} entries.")

finally:
shutil.rmtree(clone_dir, ignore_errors=True)


if __name__ == "__main__":
main()
21 changes: 21 additions & 0 deletions src/app/(home)/registry/dataset-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Heart, User } from "lucide-react";
import Link from "next/link";
import { toast } from "sonner";

Expand All @@ -18,13 +19,17 @@ interface DatasetCardProps {
version: string;
description: string | null;
taskCount: number;
contributors?: { name: string; email: string }[];
acknowledgement?: string;
}

export function DatasetCard({
name,
version,
description,
taskCount,
contributors,
acknowledgement,
}: DatasetCardProps) {
const datasetString = `${name}@${version}`;

Expand Down Expand Up @@ -64,6 +69,22 @@ export function DatasetCard({
</CardDescription>
</CardHeader>
<CardContent className="gap-4 flex-1 flex flex-col justify-between">
{(contributors?.length || acknowledgement) && (
<div className="flex flex-col gap-1.5 text-xs text-muted-foreground font-code">
{contributors?.map((c, i) => (
<span key={i} className="flex items-center gap-1.5">
<User className="size-3 shrink-0" />
{c.name}
</span>
))}
{acknowledgement && (
<span className="flex items-center gap-1.5">
<Heart className="size-3 shrink-0" />
{acknowledgement}
</span>
)}
</div>
)}
<div
className="cursor-default"
onClick={(e) => {
Expand Down
24 changes: 15 additions & 9 deletions src/app/(home)/registry/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createClient } from "@/lib/supabase/server";
import type { Tables } from "@/lib/supabase/types";
import type { Metadata } from "next";
import { DatasetCard } from "./dataset-card";
import registryMeta from "./registry-meta.json";

export const revalidate = 60;

Expand Down Expand Up @@ -66,15 +67,20 @@ export default async function RegistryPage() {
) : (
<div className="border-l border-t rounded-xl overflow-hidden">
<div className="grid grid-cols-1 md:grid-cols-2">
{datasets.map((dataset) => (
<DatasetCard
key={`${dataset.name}:${dataset.version}`}
name={dataset.name}
version={dataset.version}
description={dataset.description}
taskCount={dataset.dataset_task[0]?.count ?? 0}
/>
))}
{datasets.map((dataset) => {
const meta = (registryMeta as Record<string, { contributors: { name: string; email: string }[]; acknowledgement: string }>)[dataset.name];
return (
<DatasetCard
key={`${dataset.name}:${dataset.version}`}
name={dataset.name}
version={dataset.version}
description={dataset.description}
taskCount={dataset.dataset_task[0]?.count ?? 0}
contributors={meta?.contributors}
acknowledgement={meta?.acknowledgement}
/>
);
})}
</div>
</div>
)}
Expand Down
14 changes: 14 additions & 0 deletions src/app/(home)/registry/registry-meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"terminal-bench": {
"contributors": [
{ "name": "Harbor Team", "email": "" }
],
"acknowledgement": "2077AI"
},
"swebench-verified": {
"contributors": [
{ "name": "Harbor Team", "email": "" }
],
"acknowledgement": "2077AI"
}
}