Conversation
🪼 branch checks and previews
Install Gradio from this PR pip install https://huggingface.co/buckets/gradio/pypi-previews/resolve/1f0477a9c866650ee45775c1dda0c33bedf91cff/gradio-6.11.0-py3-none-any.whlInstall Gradio Python Client from this PR pip install "gradio-client @ git+https://github.com/gradio-app/gradio@1f0477a9c866650ee45775c1dda0c33bedf91cff#subdirectory=client/python"Install Gradio JS Client from this PR npm install https://gradio-npm-previews.s3.amazonaws.com/1f0477a9c866650ee45775c1dda0c33bedf91cff/gradio-client-2.1.0.tgz |
🦄 change detectedThis Pull Request includes changes to the following packages.
|
|
this is a bit complicated, why don't we just move the handshake logic to the JS client? Its kinda weird that it is split up anyway. |
|
Yes I was just looking into that possibility @pngwn! |
|
pretty small i think:
Would get rid of the duplication too which is nice. |
|
Does this approach look reasonable @pngwn? Going to test it to confirm |
|
Yep looks good! The module level variable is fine because we only need to go through this once, even if there are multiple client instances. |
|
Was trying to test this, but the npm package is published as a tarball: @pngwn is there a simple way I can test this in a Space? I want to do something like this: from gradio import Server
from fastapi.responses import HTMLResponse
app = Server()
@app.mcp.tool(name="add")
@app.api(name="add")
def add(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b
@app.mcp.tool(name="multiply")
@app.api(name="multiply")
def multiply(a: int, b: int) -> int:
"""Multiply two numbers together."""
return a * b
@app.get("/", response_class=HTMLResponse)
async def homepage():
return """
<!DOCTYPE html>
<html>
<head><title>Calculator</title>
<style>
* { margin: 0; box-sizing: border-box; font-family: 'Courier New', monospace; }
body { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: #1a1a2e; color: #fff;}
.calc { background: #16213e; padding: 2rem; border-radius: 1rem; box-shadow: 0 8px 32px rgba(0,0,0,.4); width: 320px; }
#out { background: #0f3460; color: #0f0; font-size: 2rem; text-align: right; padding: .75rem 1rem; border-radius: .5rem; min-height: 3rem; margin-bottom: 1rem; }
.row { display: flex; gap: .5rem; margin-bottom: .5rem; }
input { flex: 1; min-width: 0; padding: .6rem; font-size: 1.2rem; border: none; border-radius: .5rem; background: #e2e2e2; text-align: center; }
button { flex: 1; padding: .6rem; font-size: 1rem; border: none; border-radius: .5rem; cursor: pointer; font-weight: bold; color: #fff; }
.add { background: #e94560; } .mul { background: #533483; }
button:hover { opacity: .85; }
</style></head>
<body>
<div class="calc">
<div id="out">0</div>
Operands
<div class="row"><input id="a" type="number" value="3"><input id="b" type="number" value="5"></div>
Operation
<div class="row"><button class="add" onclick="run('add')">+</button><button class="mul" onclick="run('multiply')">×</button></div>
</div>
<script type="module">
import { client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js";
const app = await client(location.origin);
window.run = async (ep) => {
const a = parseInt(document.getElementById("a").value), b = parseInt(document.getElementById("b").value);
document.getElementById("out").textContent = (await app.predict("/" + ep, { a, b })).data;
};
</script>
</body>
</html>"""
if __name__ == "__main__":
app.launch(mcp_server=True)but using the Client from this .tgz URL |
|
Ok so I ended up just rebuilding it on the Space, there might be a better way, but this seems to work as it uses up by ZeroGPU quota correctly:
https://huggingface.co/spaces/abidlabs/zgpt2 cc @gary149 @yvrjsharma for visibility |
| } from "./constants"; | ||
| declare const BROWSER_BUILD: boolean; | ||
|
|
||
| initialize_zerogpu_handshake(); |
There was a problem hiding this comment.
Why is this happening here?
There was a problem hiding this comment.
Where else could it go? I put it module init because it needs to finish before the first user request. Otherwise that first request can race the iframe auth handshake and not include the forwarded headers.
There was a problem hiding this comment.
I was thinking it'd go in submit.ts or the client init. But let me know if I'm misunderstanding!
There was a problem hiding this comment.
I don't think we should put it in submit.ts because either we'd have to block until we have the headers or it might not get the headers quickly enough. We could do it in Client init I think (happy to move it there), but this is the closest to what we had previously (when we had it happen as part of the page initialization itself)
There was a problem hiding this comment.
Ok let's keep as is then! But it's also currently being called in submit.ts. Is it intentional?
There was a problem hiding this comment.
Yeah that seems unnecessary, will remove
freddyaboulton
left a comment
There was a problem hiding this comment.
Thanks for the fix @abidlabs

Fixes: #13209