evalstate HF Staff commited on
Commit
7ebdafb
·
verified ·
1 Parent(s): bb79bb8

Improve research app progress and timeline layout

Browse files
Files changed (1) hide show
  1. fastmcp_research_app.py +28 -12
fastmcp_research_app.py CHANGED
@@ -31,7 +31,7 @@ from starlette.middleware import Middleware
31
  from prefab_ui.actions import SetInterval, SetState
32
  from prefab_ui.actions.mcp import CallTool
33
  from prefab_ui.app import PrefabApp
34
- from prefab_ui.components import Badge, Card, CardContent, CardHeader, Column, Heading, If, Muted, Progress, Row, Text
35
  from prefab_ui.components.control_flow import ForEach
36
  from prefab_ui.rx import RESULT, Rx, STATE
37
 
@@ -112,6 +112,9 @@ class ResearchJob:
112
  "topic": self.topic,
113
  "status": self.status,
114
  "events": list(self.events),
 
 
 
115
  "result": self.result,
116
  "error": self.error,
117
  "done": self.status in {"completed", "failed"},
@@ -224,7 +227,7 @@ async def main() -> None:
224
 
225
  @app.ui(
226
  name="research",
227
- title="Research Agent",
228
  description="Open a live research app for a Hugging Face ecosystem research task.",
229
  )
230
  async def research(
@@ -274,31 +277,44 @@ async def main() -> None:
274
  ],
275
  ):
276
  with Row(justify="between", align="center"):
277
- Heading("Research Agent")
278
  Badge(STATE.job.status, variant="outline")
279
  Muted(STATE.topic)
280
 
281
  with Card():
282
  with CardHeader():
283
- Text("Progress")
284
  with CardContent():
285
- Progress(value=Rx("job.events.length"), max=20)
286
- with Column(gap=2):
287
- with If(STATE.job.error):
288
- Text(STATE.job.error, css_class="text-red-600")
289
- with If(STATE.job.result):
290
- Text(STATE.job.result, css_class="whitespace-pre-wrap")
291
- Muted("Research is running; this view refreshes automatically.")
292
 
293
  with Card():
294
  with CardHeader():
295
  Text("Timeline")
 
296
  with CardContent():
297
- with ForEach("job.events") as event:
298
  with Row(gap=2, align="start"):
299
  Badge(event.kind, variant="outline")
300
  Text(event.message)
301
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  return ui
303
 
304
  @app.tool()
 
31
  from prefab_ui.actions import SetInterval, SetState
32
  from prefab_ui.actions.mcp import CallTool
33
  from prefab_ui.app import PrefabApp
34
+ from prefab_ui.components import Badge, Card, CardContent, CardHeader, Column, Heading, If, Loader, Markdown, Muted, Progress, Row, Text
35
  from prefab_ui.components.control_flow import ForEach
36
  from prefab_ui.rx import RESULT, Rx, STATE
37
 
 
112
  "topic": self.topic,
113
  "status": self.status,
114
  "events": list(self.events),
115
+ "timeline_events": list(self.events[-24:]),
116
+ "event_count": len(self.events),
117
+ "activity_progress": 100 if self.status in {"completed", "failed"} else int(((time() - self.created_at) * 12) % 100),
118
  "result": self.result,
119
  "error": self.error,
120
  "done": self.status in {"completed", "failed"},
 
227
 
228
  @app.ui(
229
  name="research",
230
+ title="🤗 Research Agent",
231
  description="Open a live research app for a Hugging Face ecosystem research task.",
232
  )
233
  async def research(
 
277
  ],
278
  ):
279
  with Row(justify="between", align="center"):
280
+ Heading("🤗 Research Agent")
281
  Badge(STATE.job.status, variant="outline")
282
  Muted(STATE.topic)
283
 
284
  with Card():
285
  with CardHeader():
286
+ Text("Activity")
287
  with CardContent():
288
+ with Row(gap=3, align="center"):
289
+ Loader(variant="bars", size="sm")
290
+ Badge(STATE.job.status, variant="outline")
291
+ Muted("Working; the number of steps is not known in advance.")
292
+ Progress(value=STATE.job.activity_progress, max=100, gradient=True, size="sm")
 
 
293
 
294
  with Card():
295
  with CardHeader():
296
  Text("Timeline")
297
+ Muted("Showing the latest 24 events; older events roll off the visible list.")
298
  with CardContent():
299
+ with ForEach("job.timeline_events") as event:
300
  with Row(gap=2, align="start"):
301
  Badge(event.kind, variant="outline")
302
  Text(event.message)
303
 
304
+ with If(STATE.job.error):
305
+ with Card():
306
+ with CardHeader():
307
+ Text("Error")
308
+ with CardContent():
309
+ Text(STATE.job.error, css_class="text-red-600")
310
+
311
+ with If(STATE.job.result):
312
+ with Card():
313
+ with CardHeader():
314
+ Text("Final result")
315
+ with CardContent():
316
+ Markdown(STATE.job.result, css_class="whitespace-pre-wrap")
317
+
318
  return ui
319
 
320
  @app.tool()