import gradio as gr import time # Inspired by: https://www.gradio.app/guides/agents-and-tool-usage # Custom timer solution described by Claude Sonnet 4.6: # https://claude.ai/share/d7adc776-05f2-4c2b-a93a-9cf6089dd7be def interact_with_agent(prompt, messages=[]): """Simulate generation of two assistant messages after delays""" time.sleep(4) messages.append( gr.ChatMessage( role="assistant", content="First message — gr.Chatbot() timer stops here" ) ) yield messages time.sleep(4) messages.append( gr.ChatMessage(role="assistant", content="Second message — Custom timer stops here") ) yield messages def str_to_message(content, role="user"): return [gr.ChatMessage(role=role, content=content)] timer_html = """
""" timer_js = """ let startTime = null; let interval = null; const el = element.querySelector('#agent-timer'); el.addEventListener('agent-timer:start', () => { startTime = Date.now(); el.textContent = '⏱ 0.0s'; interval = setInterval(() => { const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); el.textContent = '⏱ ' + elapsed + 's'; }, 100); }); el.addEventListener('agent-timer:stop', () => { if (interval) { clearInterval(interval); interval = null; const elapsed = ((Date.now() - startTime) / 1000).toFixed(1); el.textContent = '✓ ' + elapsed + 's'; } }); """ chatbot_overlay_css = """ #timer-display { position: absolute; bottom: 0px; } """ with gr.Blocks() as demo: with gr.Row(): with gr.Column(): gr.Markdown( """ ## Gradio chatbot timer that stops at the last (not first) yielded agent message **Submit any user message to launch a chatbot simulation that responds with two assistant messages with a 4-second delay before each one.** - The built-in `gr.Chatbot` timer (*lower right*) stops after the first message. - The custom timer (*lower left*) keeps going until the last message is yielded. - The custom timer is implemented in JavaScript and CSS and depends on `gr.HTML` capabilities in Gradio 6. """ ) input = gr.Textbox( "Start the timers!", label="User message", autofocus=True, submit_btn=True, ) gr.Markdown( """ ### App history - 2025-07-25: Create demo to support [Gradio issue #11637](https://github.com/gradio-app/gradio/issues/11637) (Gradio 5.38.2) - 2026-05-30: Add custom timer using [gr.HTML](https://huggingface.co/blog/gradio-html-one-shot-apps) (Gradio 6.15.2) """ ) with gr.Column(): chatbot = gr.Chatbot() gr.HTML(value=timer_html, js_on_load=timer_js, elem_id="timer-display") input.submit( # Update chatbot UI with user message immediately str_to_message, input, chatbot, ).then( # Start custom timer lambda: None, None, None, js="() => document.getElementById('agent-timer')" "?.dispatchEvent(new CustomEvent('agent-timer:start'))", ).then( # Update chatbot UI with assistant messages interact_with_agent, [input, chatbot], chatbot, ).then( # Stop custom timer lambda: None, None, None, js="() => document.getElementById('agent-timer')" "?.dispatchEvent(new CustomEvent('agent-timer:stop'))", ) demo.launch(css=chatbot_overlay_css)