mishig HF Staff commited on
Commit
afb907c
·
1 Parent(s): e7ef588

Initial: proxy Space that injects api-instructions meta tag

Browse files
Files changed (3) hide show
  1. Dockerfile +6 -0
  2. app.py +77 -0
  3. requirements.txt +3 -0
Dockerfile ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+ WORKDIR /app
3
+ COPY requirements.txt .
4
+ RUN pip install --no-cache-dir -r requirements.txt
5
+ COPY app.py .
6
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import httpx
3
+ from fastapi import FastAPI, Request
4
+ from fastapi.responses import HTMLResponse
5
+
6
+ app = FastAPI()
7
+
8
+ HF_TOKEN = os.environ.get("HF_TOKEN", "")
9
+
10
+
11
+ def build_agent_prompt(space_info: dict) -> str:
12
+ space_id = space_info.get("id", "")
13
+ subdomain = space_info.get("subdomain", "")
14
+ description = space_info.get("ai_short_description") or (space_info.get("cardData") or {}).get("short_description")
15
+ base_url = f"https://{subdomain}.hf.space"
16
+
17
+ prefix = f"To use this application ({space_id}: {description}) — " if description else ""
18
+ return (
19
+ f'{prefix}API schema: GET {base_url}/gradio_api/info — '
20
+ f'Call endpoint: POST {base_url}/gradio_api/call/{{endpoint}} {{"data": [...]}} — '
21
+ f'Poll result: GET {base_url}/gradio_api/call/{{endpoint}}/{{event_id}} — '
22
+ f'auth: Bearer $HF_TOKEN'
23
+ )
24
+
25
+
26
+ @app.get("/proxy/{namespace}/{repo}", response_class=HTMLResponse)
27
+ async def proxy_space(namespace: str, repo: str, request: Request):
28
+ space_id = f"{namespace}/{repo}"
29
+ headers = {}
30
+ if HF_TOKEN:
31
+ headers["Authorization"] = f"Bearer {HF_TOKEN}"
32
+
33
+ async with httpx.AsyncClient(follow_redirects=True) as client:
34
+ # Fetch space info from API
35
+ api_resp = await client.get(f"https://huggingface.co/api/spaces/{space_id}", headers=headers)
36
+ if api_resp.status_code != 200:
37
+ return HTMLResponse(f"<html><body>Space not found: {space_id}</body></html>", status_code=404)
38
+
39
+ space_info = api_resp.json()
40
+
41
+ if space_info.get("sdk") != "gradio":
42
+ return HTMLResponse(f"<html><body>Only Gradio spaces are supported. This space uses: {space_info.get('sdk')}</body></html>", status_code=400)
43
+
44
+ # Fetch the actual space page HTML
45
+ page_resp = await client.get(f"https://huggingface.co/spaces/{space_id}", headers=headers)
46
+ html = page_resp.text
47
+
48
+ # Build the meta tag
49
+ prompt = build_agent_prompt(space_info)
50
+ meta_tag = f'<meta name="api-instructions" content="{prompt}">'
51
+
52
+ # Inject meta tag after <head> or at the start
53
+ if "<head>" in html:
54
+ html = html.replace("<head>", f"<head>\n{meta_tag}", 1)
55
+ elif "<HEAD>" in html:
56
+ html = html.replace("<HEAD>", f"<HEAD>\n{meta_tag}", 1)
57
+ else:
58
+ html = f"{meta_tag}\n{html}"
59
+
60
+ return HTMLResponse(html)
61
+
62
+
63
+ @app.get("/", response_class=HTMLResponse)
64
+ async def home():
65
+ return HTMLResponse("""
66
+ <html>
67
+ <head><title>Agent Meta Tag Proxy</title></head>
68
+ <body style="font-family: sans-serif; max-width: 600px; margin: 40px auto; padding: 0 20px;">
69
+ <h1>Agent Meta Tag Proxy</h1>
70
+ <p>This Space injects a <code>&lt;meta name="api-instructions"&gt;</code> tag into Gradio Space pages for AI agent discovery.</p>
71
+ <h3>Usage</h3>
72
+ <pre>/proxy/{namespace}/{repo}</pre>
73
+ <h3>Example</h3>
74
+ <a href="/proxy/mrfakename/Z-Image-Turbo">/proxy/mrfakename/Z-Image-Turbo</a>
75
+ </body>
76
+ </html>
77
+ """)
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ httpx