VibecoderMcSwaggins commited on
Commit
26fdadb
Β·
unverified Β·
2 Parent(s): 580b270 3d0c731

Merge pull request #138 from The-Obstacle-Is-The-Way/claude/gradio-specs-alignment-014wuSArAiv3SWQMnfUoCSBM

Browse files
docs/specs/SPEC-22-PROGRESS-BAR-REMOVAL.md CHANGED
@@ -1,127 +1,151 @@
1
- # SPEC-22: Progress Bar Removal
2
 
3
- **Status:** READY FOR IMPLEMENTATION
4
- **Priority:** P3 (Cosmetic UX fix)
5
  **Effort:** 15 minutes
6
  **PR Scope:** Single file fix
7
 
8
  ---
9
 
10
- ## Problem Statement
11
 
12
- The `gr.Progress()` bar conflicts with Gradio's `ChatInterface`, causing visual glitches:
13
- - Progress bar "floats" in the middle of chat output
14
- - Text overlaps with progress bar
15
- - Looks unprofessional
16
-
17
- **Root Cause:** `gr.Progress()` is designed for `gr.Interface`, not `ChatInterface`. It's a known Gradio limitation.
18
 
19
  ---
20
 
21
- ## Current Code (BROKEN)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
  ```python
24
- # src/app.py - research_agent function
25
- async def research_agent(
26
- message: str,
27
- history: list[dict[str, Any]],
28
- domain: str = "sexual_health",
29
- api_key: str = "",
30
- api_key_state: str = "",
31
- progress: gr.Progress = gr.Progress(), # ← PROBLEM: Causes visual glitches
32
- ) -> AsyncGenerator[str, None]:
33
- ...
34
- if event.type == "started":
35
- progress(0, desc="Starting research...") # ← These cause overlap
36
- elif event.type == "progress":
37
- progress(p, desc=event.message)
38
  ```
39
 
 
 
40
  ---
41
 
42
- ## Required Fix
43
 
44
- Remove `gr.Progress()` entirely. We already have emoji status messages in chat output.
45
 
46
  ```python
47
- # src/app.py - Fixed version
48
- async def research_agent(
49
- message: str,
50
- history: list[dict[str, Any]],
51
- domain: str = "sexual_health",
52
- api_key: str = "",
53
- api_key_state: str = "",
54
- # REMOVED: progress: gr.Progress = gr.Progress(),
55
- ) -> AsyncGenerator[str, None]:
56
- ...
57
- # REMOVED: All progress(...) calls
58
 
59
- # KEEP: Emoji status messages are already being yielded
60
- # These work great with ChatInterface:
61
- # yield "⏱️ **PROGRESS**: Round 1/5 (~3m 0s remaining)"
 
62
  ```
63
 
64
- ---
65
 
66
- ## Implementation Checklist
67
-
68
- - [ ] Open `src/app.py`
69
- - [ ] Remove `progress: gr.Progress = gr.Progress()` from `research_agent` signature
70
- - [ ] Remove all `progress(...)` calls inside `research_agent`
71
- - [ ] Verify emoji status yields are still present (they should be)
72
- - [ ] Run `uv run python -c "from src.app import create_demo; print('OK')"`
73
- - [ ] Run `make check`
74
- - [ ] Test locally: `uv run python src/app.py` and verify no floating progress bar
75
 
76
  ---
77
 
78
- ## What We Keep
79
 
80
- The emoji status messages in chat output:
81
 
82
- ```
83
- ⏱️ **PROGRESS**: Round 1/5 (~3m 0s remaining)
84
- πŸ”¬ **Step 2: SearchAgent** - Searching for evidence...
85
- βœ… **COMPLETE**: Research finished in 45 seconds
86
- ```
87
 
88
- These are yielded directly to chat and work perfectly with `ChatInterface`.
 
 
 
 
 
 
 
89
 
90
- ---
 
 
91
 
92
- ## Acceptance Criteria
93
 
94
- 1. No `gr.Progress()` in `research_agent` function signature
95
- 2. No `progress(...)` calls in `research_agent` function body
96
- 3. Emoji status messages still appear in chat output
97
- 4. No floating/overlapping progress bar in UI
98
- 5. `make check` passes
99
 
100
  ---
101
 
102
- ## Dependencies
103
 
104
- None. This is a standalone cosmetic fix.
 
 
 
 
 
 
105
 
106
  ---
107
 
108
- ## Testing
109
 
110
  ```bash
111
- # Start local server
112
- uv run python src/app.py
113
-
114
- # In browser:
115
- # 1. Submit a research query
116
- # 2. Verify NO floating progress bar appears
117
- # 3. Verify emoji status messages DO appear in chat
118
- # 4. Verify chat messages don't have visual glitches
119
  ```
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  ---
122
 
123
- ## Notes
124
 
125
- - This is the recommended fix from Gradio's own documentation
126
- - `ChatInterface.show_progress="minimal"` (default) still shows a spinner, which is fine
127
- - If we need a real progress bar later, we'd need to refactor to `gr.Blocks` wrapper
 
1
+ # SPEC-22: Remove Unsupported gr.Progress from ChatInterface
2
 
3
+ **Status:** IMPLEMENTED
4
+ **Priority:** P3 (Technical debt cleanup)
5
  **Effort:** 15 minutes
6
  **PR Scope:** Single file fix
7
 
8
  ---
9
 
10
+ ## Executive Summary
11
 
12
+ We are using `gr.Progress()` with `gr.ChatInterface`, but **Gradio does not support this combination**. This is not a workaround - this is the correct fix to align with Gradio's architecture.
 
 
 
 
 
13
 
14
  ---
15
 
16
+ ## Technical Background
17
+
18
+ ### Gradio's Progress Mechanisms
19
+
20
+ | Mechanism | Designed For | Works With ChatInterface |
21
+ |-----------|--------------|-------------------------|
22
+ | `gr.Progress()` | `gr.Interface` | ❌ NO - causes visual glitches |
23
+ | `show_progress` param | `ChatInterface` | βœ… YES - built-in spinner/timer |
24
+ | Streaming yields | `ChatInterface` | βœ… YES - native support |
25
+ | `ChatMessage.metadata.status` | `ChatInterface` | βœ… YES - per-message indicators |
26
+
27
+ ### Why gr.Progress Fails with ChatInterface
28
+
29
+ 1. **GitHub Issue [#5967](https://github.com/gradio-app/gradio/issues/5967)**: "gr.Progress is not integrated with ChatInterface or Chatbots" - closed without resolution (Jan 2024)
30
+ 2. **Visual symptoms**: Progress bar floats in middle of chat output, overlaps text
31
+ 3. **Root cause**: `gr.Progress` injects UI into the output component area, but `ChatInterface` manages its own output rendering
32
+
33
+ ### What We Already Have (Working)
34
+
35
+ Our `research_agent` function already yields semantic status messages:
36
 
37
  ```python
38
+ yield "🧠 **Backend**: Paid API (OpenAI) | **Domain**: Sexual Health"
39
+ yield "⏳ **Processing...** Searching PubMed, ClinicalTrials.gov..."
40
+ # During orchestration:
41
+ yield "⏱️ **PROGRESS**: Round 1/5 (~3m 0s remaining)"
42
+ yield "πŸ”¬ **Step 2: SearchAgent** - Searching for evidence..."
43
+ yield "βœ… **COMPLETE**: Research finished"
 
 
 
 
 
 
 
 
44
  ```
45
 
46
+ These work perfectly with ChatInterface streaming.
47
+
48
  ---
49
 
50
+ ## The Fix
51
 
52
+ ### What to Remove
53
 
54
  ```python
55
+ # src/app.py - REMOVE from research_agent signature:
56
+ progress: gr.Progress = gr.Progress(), # noqa: B008
 
 
 
 
 
 
 
 
 
57
 
58
+ # src/app.py - REMOVE all progress() calls:
59
+ progress(0, desc="Starting research...")
60
+ progress(0.1, desc="Multi-agent reasoning...")
61
+ progress(p, desc=event.message)
62
  ```
63
 
64
+ ### What to Add (Optional Enhancement)
65
 
66
+ ```python
67
+ # src/app.py - In create_demo(), add show_progress for built-in spinner:
68
+ demo = gr.ChatInterface(
69
+ fn=research_agent,
70
+ show_progress="full", # Shows spinner + runtime timer (Gradio native)
71
+ ...
72
+ )
73
+ ```
 
74
 
75
  ---
76
 
77
+ ## Why This Is The Correct Approach (Not A Workaround)
78
 
79
+ ### ❌ What Would Be Over-Engineering
80
 
81
+ Refactoring from `ChatInterface` to `gr.Blocks` + `gr.Chatbot` just to support `gr.Progress`:
 
 
 
 
82
 
83
+ | ChatInterface provides FREE | gr.Blocks would require manual |
84
+ |---------------------------|-------------------------------|
85
+ | MCP server support | Unknown if compatible |
86
+ | Chat history state | Manual `gr.State` management |
87
+ | Submit/Stop buttons | Manual button wiring |
88
+ | Example handling | Manual click handlers |
89
+ | Streaming support | Manual async iteration |
90
+ | Accordion for inputs | Manual accordion component |
91
 
92
+ **Effort**: Days of refactoring + testing
93
+ **Benefit**: A progress bar (which we already have via emoji status)
94
+ **Verdict**: Not justified
95
 
96
+ ### βœ… What Is Professional Engineering
97
 
98
+ 1. Use `ChatInterface` as designed (high-level, batteries-included)
99
+ 2. Remove unsupported feature (`gr.Progress`)
100
+ 3. Rely on supported mechanisms:
101
+ - Streaming status yields (already implemented)
102
+ - `show_progress="full"` (Gradio native)
103
 
104
  ---
105
 
106
+ ## Implementation Checklist
107
 
108
+ - [x] Open `src/app.py`
109
+ - [x] Remove `progress: gr.Progress = gr.Progress()` from `research_agent` signature
110
+ - [x] Remove all `progress(...)` calls from `research_agent`
111
+ - [x] Add `show_progress="full"` to `gr.ChatInterface` constructor
112
+ - [x] Verify emoji status yields still present in orchestrator events
113
+ - [x] Run `make check`
114
+ - [ ] Test locally: `uv run python src/app.py`
115
 
116
  ---
117
 
118
+ ## Verification
119
 
120
  ```bash
121
+ # Verify no gr.Progress usage in codebase
122
+ grep -rn "gr.Progress" src/
123
+
124
+ # Should return empty (no matches)
 
 
 
 
125
  ```
126
 
127
+ ### Manual Test
128
+ 1. Start app: `uv run python src/app.py`
129
+ 2. Submit a research query
130
+ 3. Verify:
131
+ - βœ… Gradio spinner appears (top-right timer)
132
+ - βœ… Emoji status messages stream in chat
133
+ - ❌ No floating/overlapping progress bar
134
+
135
+ ---
136
+
137
+ ## Acceptance Criteria
138
+
139
+ 1. No `gr.Progress` in codebase
140
+ 2. `show_progress="full"` added to ChatInterface
141
+ 3. Emoji status messages continue working
142
+ 4. No visual glitches in UI
143
+ 5. `make check` passes
144
+
145
  ---
146
 
147
+ ## References
148
 
149
+ - [Gradio ChatInterface Docs](https://www.gradio.app/docs/gradio/chatinterface)
150
+ - [Gradio Progress Bars Guide](https://www.gradio.app/guides/progress-bars)
151
+ - [GitHub #5967: Progress bar for ChatInterface](https://github.com/gradio-app/gradio/issues/5967)
docs/specs/SPEC-23-GRADIO-MODERNIZATION.md ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # SPEC-23: Gradio 6.0 Modernization Audit
2
+
3
+ **Status:** READY FOR IMPLEMENTATION
4
+ **Priority:** P3 (Technical alignment)
5
+ **Effort:** 30 minutes
6
+ **Dependencies:** SPEC-22 (Progress Bar Removal)
7
+ **Gradio Version:** 6.0.1 (December 2025)
8
+ **Last Verified:** 2025-12-07
9
+
10
+ ---
11
+
12
+ ## Executive Summary
13
+
14
+ Audit of `src/app.py` against Gradio 6.0.1 best practices. Identifies parameters we should add or update for full alignment with modern Gradio.
15
+
16
+ ---
17
+
18
+ ## Gradio Architecture Clarification
19
+
20
+ ### The Three High-Level Classes
21
+
22
+ | Class | Purpose | Flexibility | Use Case |
23
+ |-------|---------|-------------|----------|
24
+ | `gr.Blocks` | Low-level building blocks | Most flexible | Custom layouts, multiple components |
25
+ | `gr.Interface` | Input β†’ Output wrapper | Medium | ML models, transformations |
26
+ | `gr.ChatInterface` | Chat app wrapper | Opinionated | **Chatbots (what we use)** |
27
+
28
+ ### Inheritance Hierarchy
29
+
30
+ ```
31
+ gr.Blocks (base)
32
+ ↑
33
+ gr.ChatInterface (inherits from Blocks, adds chat-specific features)
34
+ ```
35
+
36
+ **Key insight:** `ChatInterface` IS a `Blocks` context internally. We're not mixing different things - we're using the right abstraction for a chat app.
37
+
38
+ ### What ChatInterface Gives Us (For Free)
39
+
40
+ - Chat history state management
41
+ - Submit/Stop buttons
42
+ - Streaming support
43
+ - Example handling
44
+ - `additional_inputs` accordion
45
+ - MCP server support (`mcp_server=True`)
46
+
47
+ ### When Would We Need Pure `gr.Blocks`?
48
+
49
+ Only if we needed:
50
+ - Multiple independent chat windows
51
+ - Complex multi-panel layouts
52
+ - Non-chat components as primary UI
53
+
54
+ **Verdict:** `ChatInterface` is the correct choice for DeepBoner.
55
+
56
+ ---
57
+
58
+ ## Current State vs Best Practices
59
+
60
+ | Feature | Current | Best Practice | Action |
61
+ |---------|---------|---------------|--------|
62
+ | `type` param | Not set (legacy) | `type="messages"` | **ADD** - Uses OpenAI-style message format |
63
+ | `fill_height` | Not set | `fill_height=True` | **ADD** - Chat fills vertical space |
64
+ | `autoscroll` | Not set | `autoscroll=True` | **ADD** - Auto-scroll to latest message |
65
+ | `show_progress` | Not set (minimal) | `show_progress="full"` | **ADD** - Per SPEC-22 |
66
+ | `gr.Progress` | Used (broken) | Remove | **REMOVE** - Per SPEC-22 |
67
+
68
+ ---
69
+
70
+ ## Detailed Findings
71
+
72
+ ### 1. Message Format (`type="messages"`)
73
+
74
+ **Current:** Not specified (uses legacy tuple format)
75
+ **Recommended:** `type="messages"`
76
+
77
+ The `type="messages"` format uses OpenAI-style dictionaries:
78
+ ```python
79
+ {"role": "user" | "assistant", "content": str}
80
+ ```
81
+
82
+ This is the modern standard and aligns with our LLM backends.
83
+
84
+ **Note:** This may require updating how we handle `history` parameter.
85
+
86
+ ### 2. Fill Height (`fill_height=True`)
87
+
88
+ **Current:** Not set
89
+ **Recommended:** `fill_height=True`
90
+
91
+ Makes the chat interface fill available vertical space. Better UX on larger screens.
92
+
93
+ **Known Issue:** [GitHub #10407](https://github.com/gradio-app/gradio/issues/10407) - May conflict with `save_history=True`. We don't use `save_history`, so should be fine.
94
+
95
+ ### 3. Autoscroll (`autoscroll=True`)
96
+
97
+ **Current:** Not set
98
+ **Recommended:** `autoscroll=True`
99
+
100
+ Ensures chat auto-scrolls to the latest message during streaming. Critical for long research outputs.
101
+
102
+ ---
103
+
104
+ ## Implementation Checklist
105
+
106
+ ### SPEC-22 Items (Do First)
107
+ - [ ] Remove `progress: gr.Progress = gr.Progress()` from `research_agent` signature
108
+ - [ ] Remove all `progress(...)` calls in `research_agent`
109
+
110
+ ### SPEC-23 Items
111
+ - [ ] Add `show_progress="full"` to `gr.ChatInterface`
112
+ - [ ] Add `fill_height=True` to `gr.ChatInterface`
113
+ - [ ] Add `autoscroll=True` to `gr.ChatInterface`
114
+ - [ ] Evaluate `type="messages"` migration (may require history format changes)
115
+
116
+ ---
117
+
118
+ ## Code Changes
119
+
120
+ ### Before (Current)
121
+ ```python
122
+ demo = gr.ChatInterface(
123
+ fn=research_agent,
124
+ title="πŸ† DeepBoner",
125
+ description=description,
126
+ examples=[...],
127
+ cache_examples=False,
128
+ run_examples_on_click=False,
129
+ additional_inputs_accordion=additional_inputs_accordion,
130
+ additional_inputs=[...],
131
+ )
132
+ ```
133
+
134
+ ### After (Modernized)
135
+ ```python
136
+ demo = gr.ChatInterface(
137
+ fn=research_agent,
138
+ title="πŸ† DeepBoner",
139
+ description=description,
140
+ examples=[...],
141
+ cache_examples=False,
142
+ run_examples_on_click=False,
143
+ additional_inputs_accordion=additional_inputs_accordion,
144
+ additional_inputs=[...],
145
+ # SPEC-22: Use native progress instead of gr.Progress
146
+ show_progress="full",
147
+ # SPEC-23: Modern Gradio 6.0 settings
148
+ fill_height=True,
149
+ autoscroll=True,
150
+ # NOTE: type="messages" requires history format migration - evaluate separately
151
+ )
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Risk Assessment
157
+
158
+ | Change | Risk | Mitigation |
159
+ |--------|------|------------|
160
+ | `show_progress="full"` | Low | Native Gradio feature |
161
+ | `fill_height=True` | Low | May affect layout, test visually |
162
+ | `autoscroll=True` | Low | Native feature, improves UX |
163
+ | `type="messages"` | Medium | Requires history format changes - defer if needed |
164
+
165
+ ---
166
+
167
+ ## Verification
168
+
169
+ ```bash
170
+ # After changes
171
+ make check
172
+
173
+ # Manual test
174
+ uv run python src/app.py
175
+ # Verify:
176
+ # 1. Chat fills vertical space
177
+ # 2. Auto-scrolls during streaming
178
+ # 3. Spinner appears (not floating progress bar)
179
+ ```
180
+
181
+ ---
182
+
183
+ ## References
184
+
185
+ - [Gradio ChatInterface Docs](https://www.gradio.app/docs/gradio/chatinterface)
186
+ - [GitHub #10407: fill_height with save_history](https://github.com/gradio-app/gradio/issues/10407)
187
+ - [GitHub #11109: Autoscroll issue](https://github.com/gradio-app/gradio/issues/11109)
src/app.py CHANGED
@@ -5,6 +5,7 @@ from collections.abc import AsyncGenerator
5
  from typing import Any, Literal
6
 
7
  import gradio as gr
 
8
 
9
  from src.config.domain import ResearchDomain
10
  from src.orchestrators import create_orchestrator
@@ -13,6 +14,8 @@ from src.utils.exceptions import ConfigurationError
13
  from src.utils.models import OrchestratorConfig
14
  from src.utils.service_loader import warmup_services
15
 
 
 
16
  OrchestratorMode = Literal["advanced", "hierarchical"] # Unified Architecture (SPEC-16)
17
 
18
 
@@ -126,10 +129,9 @@ def _validate_inputs(
126
  async def research_agent(
127
  message: str,
128
  history: list[dict[str, Any]],
129
- domain: str = "sexual_health",
130
- api_key: str = "",
131
- api_key_state: str = "",
132
- progress: gr.Progress = gr.Progress(), # noqa: B008
133
  ) -> AsyncGenerator[str, None]:
134
  """
135
  Gradio chat function that runs the research agent.
@@ -140,10 +142,9 @@ async def research_agent(
140
  Args:
141
  message: User's research question
142
  history: Chat history (Gradio format)
143
- domain: Research domain
144
  api_key: Optional user-provided API key (BYOK - auto-detects provider)
145
- api_key_state: Persistent API key state (survives example clicks)
146
- progress: Gradio progress tracker
147
 
148
  Yields:
149
  Markdown-formatted responses for streaming
@@ -187,21 +188,8 @@ async def research_agent(
187
  )
188
 
189
  async for event in orchestrator.run(message):
190
- # Update progress bar
191
- if event.type == "started":
192
- progress(0, desc="Starting research...")
193
- elif event.type == "thinking":
194
- progress(0.1, desc="Multi-agent reasoning...")
195
- elif event.type == "progress":
196
- # Calculate progress percentage (fallback to 0.15 for events without iteration)
197
- p = 0.15
198
- max_iters = getattr(orchestrator, "_max_rounds", None) or getattr(
199
- getattr(orchestrator, "config", None), "max_iterations", 10
200
- )
201
- if event.iteration:
202
- # Map 0..max to 0.2..0.9
203
- p = 0.2 + (0.7 * (min(event.iteration, max_iters) / max_iters))
204
- progress(p, desc=event.message)
205
 
206
  # BUG FIX: Handle streaming events separately to avoid token-by-token spam
207
  if event.type == "streaming":
@@ -235,7 +223,8 @@ async def research_agent(
235
  yield "\n\n".join(response_parts)
236
 
237
  except Exception as e:
238
- yield f"❌ **Error**: {e!s}"
 
239
 
240
 
241
  def create_demo() -> tuple[gr.ChatInterface, gr.Accordion]:
@@ -272,6 +261,11 @@ def create_demo() -> tuple[gr.ChatInterface, gr.Accordion]:
272
  fn=research_agent,
273
  title="πŸ† DeepBoner",
274
  description=description,
 
 
 
 
 
275
  examples=[
276
  # SPEC-16: Mode is always "advanced" (unified architecture)
277
  # Examples now only need: [question, domain, api_key, api_key_state]
 
5
  from typing import Any, Literal
6
 
7
  import gradio as gr
8
+ import structlog
9
 
10
  from src.config.domain import ResearchDomain
11
  from src.orchestrators import create_orchestrator
 
14
  from src.utils.models import OrchestratorConfig
15
  from src.utils.service_loader import warmup_services
16
 
17
+ logger = structlog.get_logger(__name__)
18
+
19
  OrchestratorMode = Literal["advanced", "hierarchical"] # Unified Architecture (SPEC-16)
20
 
21
 
 
129
  async def research_agent(
130
  message: str,
131
  history: list[dict[str, Any]],
132
+ domain: str | None = None,
133
+ api_key: str | None = None,
134
+ api_key_state: str | None = None,
 
135
  ) -> AsyncGenerator[str, None]:
136
  """
137
  Gradio chat function that runs the research agent.
 
142
  Args:
143
  message: User's research question
144
  history: Chat history (Gradio format)
145
+ domain: Research domain (None defaults to "sexual_health")
146
  api_key: Optional user-provided API key (BYOK - auto-detects provider)
147
+ api_key_state: Persistent API key state (survives example clicks, can be None)
 
148
 
149
  Yields:
150
  Markdown-formatted responses for streaming
 
188
  )
189
 
190
  async for event in orchestrator.run(message):
191
+ # SPEC-22: Progress bar removed - gr.Progress() causes visual glitches
192
+ # with ChatInterface. Status feedback via AgentEvent.to_markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
193
 
194
  # BUG FIX: Handle streaming events separately to avoid token-by-token spam
195
  if event.type == "streaming":
 
223
  yield "\n\n".join(response_parts)
224
 
225
  except Exception as e:
226
+ logger.exception("research_agent_failed", error=str(e))
227
+ yield "❌ **Error**: Something went wrong. Please try again."
228
 
229
 
230
  def create_demo() -> tuple[gr.ChatInterface, gr.Accordion]:
 
261
  fn=research_agent,
262
  title="πŸ† DeepBoner",
263
  description=description,
264
+ # SPEC-22: Use native progress instead of gr.Progress (which breaks ChatInterface)
265
+ show_progress="full",
266
+ # SPEC-23: Gradio 6.0 best practices
267
+ fill_height=True,
268
+ autoscroll=True,
269
  examples=[
270
  # SPEC-16: Mode is always "advanced" (unified architecture)
271
  # Examples now only need: [question, domain, api_key, api_key_state]