Spaces:
Running
Running
File size: 6,452 Bytes
8366946 592930d 8366946 |
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
"""Launches a Gradio app that runs an AI planning agent to find smart online deals.
Uses Python's built-in logging system for consistent logs.
Includes demo mode restrictions: MAX_DEMO_RUNS_PER_DAY runs per day.
"""
import os
from typing import Tuple
import gradio as gr
from src.agents.pipeline import run_and_stream_logs
from src.config.constants import (
IS_DEMO_VERSION,
MAX_CATEGORY_SELECTION,
MAX_DEMO_RUNS_PER_DAY,
PROJECT_NAME,
VERSION,
)
from src.config.feeds import CATEGORY_FEEDS
from src.ui.formatting import format_deals_table
from src.utils.logger import console
from src.utils.state_manager import can_run_app
PROJECT_NAME_CAP = PROJECT_NAME.capitalize()
REPO_URL = f"https://github.com/lisekarimi/{PROJECT_NAME}"
DOC_URL = f"https://lisekarimi.github.io/{PROJECT_NAME}"
def build_ui() -> gr.Blocks:
"""Constructs and returns the Gradio UI interface, with error handling."""
try:
with open(
os.path.join(os.path.dirname(__file__), "assets", "styles.css"), "r"
) as f:
css = f.read()
except Exception as e:
css = ""
console.print(f"[bold yellow]⚠️ Failed to load CSS:[/] {e}")
# Set initial UI state here
disable_btn = False
initial_status = "Loading demo status..."
# Building the UI
try:
with gr.Blocks(css=css, title=f"🏷️{PROJECT_NAME_CAP}") as ui:
with gr.Column(elem_id="app-container"):
# 🔝 Top content
gr.Markdown(f"<h1 id='app-title'>🏷️ {PROJECT_NAME_CAP} </h1>")
gr.Markdown(
"<h2 id='app-subtitle'>Autonomous AI Agents Snapping the Best "
"Deals Online</h2>"
)
gr.HTML(
f"""
<div id="intro-text">
<p>🏷️ <strong>Snapr</strong>,
<strong>an Agentic AI System</strong>,
discovers the best online deals for you—smart,
simple, and automatic.
Let <strong>AI</strong> do the work, so you can save money
without any effort.</p>
<h4>🤖 How It Works:</h4>
<p>1️⃣ Choose up to {MAX_CATEGORY_SELECTION}
categories to search.</p>
<p>2️⃣ Click "Find Smart Deals" — AI scans, estimates prices,
and filters top discounts.</p>
<p>3️⃣ See the best deals in a table with prices, discounts,
and direct links.</p>
</div>
"""
)
if IS_DEMO_VERSION:
gr.Markdown(
f"""
<p>⚠️ This is a demo version — limited to
{MAX_DEMO_RUNS_PER_DAY} global runs per day for all users.</p>
"""
)
gr.Markdown(
f"""
<p class="custom-links">📦 Want more?
You can <a href="{REPO_URL}"
target="_blank">run it locally</a>
with full <a href="{DOC_URL}/technical/localdev/"
target="_blank">instructions</a> and
<a href="{DOC_URL}"
target="_blank">documentation</a>.</p>
"""
)
with gr.Column(elem_id="left-col"):
category_selector = gr.Dropdown(
choices=list(CATEGORY_FEEDS.keys()),
value="Electronics",
multiselect=True,
label=(
f"🧭 Select up to {MAX_CATEGORY_SELECTION} Deal Categories"
),
elem_id="category-selector",
elem_classes="custom-dropdown",
)
run_btn = gr.Button(
"🔍 Find Smart Deals",
elem_id="run-btn",
variant="primary",
elem_classes="run-button",
interactive=not disable_btn,
)
status_msg = gr.HTML(value=initial_status, elem_id="status-message")
# Logs + deals
logs_output = gr.HTML(
value="""
<div id="logs-label">📜 Live Agent Logs</div>
<div id="scrollContent">
🕵️♀️ Click "🔍 Find Smart Deals" to wake the agents and
stream logs here!
</div>
"""
)
deals_output = gr.HTML(
value=format_deals_table([]), elem_id="deal-table"
)
# Connect button
run_btn.click(
fn=run_and_stream_logs,
inputs=[category_selector],
outputs=[logs_output, deals_output, run_btn, status_msg],
)
# Status update on load
@ui.load(outputs=[status_msg, run_btn])
def update_status_on_load() -> Tuple[str, gr.update]:
"""Sets demo status and button state on UI load."""
can_run, status = can_run_app()
btn_state = gr.update(
interactive=can_run,
elem_classes=(
["run-button", "btn-disabled"]
if not can_run
else ["run-button"]
),
)
return status, btn_state
# Bottom: version info
gr.Markdown(
f"""
<p class="version-banner">
🔖 <strong>
<a href="{DOC_URL}/CHANGELOG"
target="_blank">Version {VERSION}</a>
</strong>
</p>
"""
)
return ui
except Exception as e:
console.print(f"[bold red]❌ Failed to build UI:[/] {e}")
raise
|