test-ui / app.py
geeksiddhant's picture
Update app.py
45d0aa5 verified
Raw
History Blame Contribute Delete
5.22 kB
import os
import gradio as gr
import requests
from supabase import create_client
# The frontend runs on a machine the USER controls, so it only ever gets keys
# that are safe in a browser. SUPABASE_ANON_KEY is the public, publishable key —
# safe precisely because RLS guards every row (db/03_policies.sql). The
# service_role key never comes near this file.
BACKEND_URL = os.environ.get("BACKEND_URL", "http://127.0.0.1:8000/diagnose")
supabase = create_client(
os.environ["SUPABASE_URL"],
os.environ["SUPABASE_ANON_KEY"],
)
# ---------------------------------------------------------------------------
# Auth: get the user a passport (JWT) before they can use the app.
#
# We do NOT build a users table or hash passwords — Supabase Auth does that.
# We just ask it to sign someone up or log them in, and keep the access_token
# it hands back. That token is the passport we attach to every backend call.
# ---------------------------------------------------------------------------
def _explain(error: Exception) -> str:
"""Turn a Supabase auth error into one human sentence."""
message = getattr(error, "message", None) or str(error)
return f"That did not work: {message}"
def log_in(email, password):
"""Exchange email + password for a session, then reveal the chat."""
if not email or not password:
return None, gr.update(), gr.update(), "Enter an email and a password."
try:
result = supabase.auth.sign_in_with_password(
{"email": email, "password": password}
)
except Exception as error: # wrong password, unknown user, etc.
return None, gr.update(), gr.update(), _explain(error)
session = result.session
if session is None:
return None, gr.update(), gr.update(), "Could not start a session."
# Logged in: stash the token, hide the login box, show the chat.
return (
session.access_token,
gr.update(visible=False),
gr.update(visible=True),
"",
)
def sign_up(email, password):
"""Create the account. This project has 'Confirm email' ON, so no session
is returned yet — the user must click the link in their inbox first, then
log in. (If you turn confirmation OFF, a session comes straight back and the
`session is not None` branch below logs them in immediately.)"""
if not email or not password:
return None, gr.update(), gr.update(), "Enter an email and a password."
try:
result = supabase.auth.sign_up({"email": email, "password": password})
except Exception as error: # already registered, weak password, etc.
return None, gr.update(), gr.update(), _explain(error)
session = result.session
if session is None:
# Email confirmation is on: account made, but no passport until verified.
return (
None,
gr.update(),
gr.update(),
"Account created. Check your email to confirm, then log in.",
)
return (
session.access_token,
gr.update(visible=False),
gr.update(visible=True),
"",
)
# ---------------------------------------------------------------------------
# The chat, now carrying the passport.
# ---------------------------------------------------------------------------
def diagnose(message, history, token):
if not token:
return "Your session expired. Please reload and log in again."
try:
response = requests.post(
BACKEND_URL,
json={"workflow_description": message},
# The passport. The backend hands this straight to Supabase to learn
# who is asking — it never trusts a name in the request body.
headers={"Authorization": f"Bearer {token}"},
timeout=60,
)
response.raise_for_status()
return response.text
except requests.RequestException as e:
return f"Could not reach the backend.\n\n{e}"
with gr.Blocks(title="Workflow Diagnoser") as demo:
# Holds the JWT for the length of the browser session.
token_state = gr.State(None)
# ---- Login view (what you see first) ----
with gr.Column(visible=True) as login_view:
gr.Markdown(
"# Workflow Diagnoser\n"
"Log in or sign up to start. Your conversations are private to you."
)
email = gr.Textbox(label="Email", placeholder="you@example.com")
password = gr.Textbox(label="Password", type="password")
with gr.Row():
login_btn = gr.Button("Log in", variant="primary")
signup_btn = gr.Button("Sign up")
status = gr.Markdown()
# ---- Chat view (hidden until you have a passport) ----
with gr.Column(visible=False) as chat_view:
gr.ChatInterface(
diagnose,
additional_inputs=[token_state],
title="Workflow Diagnoser",
description="Describe one repeated task you do at work.",
)
outputs = [token_state, login_view, chat_view, status]
login_btn.click(log_in, [email, password], outputs)
signup_btn.click(sign_up, [email, password], outputs)
if __name__ == "__main__":
demo.launch()