agharsallah commited on
Commit Β·
52b556c
1
Parent(s): ed6315a
feat(about): add About tab with project overview, architecture, and links
Browse files- README.md +46 -9
- src/ui/fishbowl/about.py +193 -0
- src/ui/fishbowl/app.py +11 -0
README.md
CHANGED
|
@@ -8,18 +8,45 @@ sdk_version: "6.16.0"
|
|
| 8 |
python_version: "3.10"
|
| 9 |
app_file: app.py
|
| 10 |
pinned: true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
---
|
| 12 |
|
| 13 |
# Multi-Agent Land
|
| 14 |
|
| 15 |
-
|
| 16 |
-
interactive story engine where the AI is load-bearing for the experience.
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
---
|
| 25 |
|
|
@@ -67,13 +94,18 @@ A **tiny theater engine** powered by specialist small-model agents. Agents neve
|
|
| 67 |
call each other directly β they post typed events to a shared append-only ledger,
|
| 68 |
and every view (the stage, the memory, the UI) is a projection derived from that log.
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
What makes it *super modular*:
|
| 71 |
- **Config, not code.** Agents, scenarios, casts, model tiers, tool grants, and
|
| 72 |
budgets are declarative YAML under `config/`, validated by a schema. Add a world
|
| 73 |
by adding files β proven by `tests/test_modularity.py` (zero engine edits).
|
| 74 |
- **A model per agent.** Each agent declares a logical profile (`tiny`/`fast`/
|
| 75 |
-
`balanced`/`strong`); a `ModelRouter` binds it to a concrete small model
|
| 76 |
-
β€4B worker with a β€32B judge in one cast.
|
| 77 |
- **Capability-checked tools.** Agents call tools only if their manifest grants
|
| 78 |
them β the contract that fronts in-process tools today and MCP servers later.
|
| 79 |
- **Built to run for hours.** The ledger is the checkpoint: `restore()` resumes a
|
|
@@ -254,3 +286,8 @@ uv run scripts/snapshot_progress.py
|
|
| 254 |
# 4. Confirm nothing broke
|
| 255 |
uv run pytest tests/ -q
|
| 256 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
python_version: "3.10"
|
| 9 |
app_file: app.py
|
| 10 |
pinned: true
|
| 11 |
+
tags:
|
| 12 |
+
- agent-demo-track
|
| 13 |
+
- track:wood
|
| 14 |
+
- sponsor:openai
|
| 15 |
+
- sponsor:nvidia
|
| 16 |
+
- sponsor:modal
|
| 17 |
+
- sponsor:openbmb
|
| 18 |
+
- achievement:offbrand
|
| 19 |
+
- achievement:sharing
|
| 20 |
+
- achievement:fieldnotes
|
| 21 |
---
|
| 22 |
|
| 23 |
# Multi-Agent Land
|
| 24 |
|
| 25 |
+
**Small models, one shared log, and a clear view of how agents behave in motion.**
|
|
|
|
| 26 |
|
| 27 |
+
Most multi-agent systems are hard to inspect: agents call each other directly and the
|
| 28 |
+
state gets messy. We wanted to *see* small agents in action β not isolated prompts, but
|
| 29 |
+
small models interacting over time: **debating, collaborating, playing games, and
|
| 30 |
+
pushing each other** in a shared environment.
|
| 31 |
+
|
| 32 |
+
So we built one. Every action β thoughts, tool calls, state updates β is appended to a
|
| 33 |
+
single **immutable log**. When one agent asks, another answers, a judge evaluates, and a
|
| 34 |
+
keeper tracks progress, *nothing is sent agent-to-agent* β every interaction flows
|
| 35 |
+
through that one shared ledger. So you can follow the whole run, step by step.
|
| 36 |
+
|
| 37 |
+
---
|
| 38 |
+
|
| 39 |
+
## Submission
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
- **π¬ Demo video:** https://youtu.be/v8-zR6eTbDM
|
| 43 |
+
- **π£ Social post:** https://www.linkedin.com/posts/gharsallah_huggingface-hackathon-buildsmall-activity-7472383877991501824-8vxO
|
| 44 |
+
- **π» GitHub link:** https://github.com/abducodez/multi-agent-land
|
| 45 |
+
- **π₯ Team (Hugging Face usernames):** <!-- TODO: list every teammate's HF username; each must register + join the org separately -->
|
| 46 |
+
- `@agharsalah`
|
| 47 |
+
|
| 48 |
+
> Tags (track + badges) live in the YAML block at the top of this README β without
|
| 49 |
+
> them the project can't be placed in a category.
|
| 50 |
|
| 51 |
---
|
| 52 |
|
|
|
|
| 94 |
call each other directly β they post typed events to a shared append-only ledger,
|
| 95 |
and every view (the stage, the memory, the UI) is a projection derived from that log.
|
| 96 |
|
| 97 |
+
**The loop is simple:** define the environment and the agent roles, then launch them in
|
| 98 |
+
the multi-agent lab. Each scenario can run for a long time β agents debate, collaborate,
|
| 99 |
+
play games, and push each other β while a live telemetry view lets you follow the whole
|
| 100 |
+
run step by step.
|
| 101 |
+
|
| 102 |
What makes it *super modular*:
|
| 103 |
- **Config, not code.** Agents, scenarios, casts, model tiers, tool grants, and
|
| 104 |
budgets are declarative YAML under `config/`, validated by a schema. Add a world
|
| 105 |
by adding files β proven by `tests/test_modularity.py` (zero engine edits).
|
| 106 |
- **A model per agent.** Each agent declares a logical profile (`tiny`/`fast`/
|
| 107 |
+
`balanced`/`strong`); a `ModelRouter` binds it to a concrete small model served on
|
| 108 |
+
Modal β **Nemotron, MiniCPM, Gemma**. Mix a β€4B worker with a β€32B judge in one cast.
|
| 109 |
- **Capability-checked tools.** Agents call tools only if their manifest grants
|
| 110 |
them β the contract that fronts in-process tools today and MCP servers later.
|
| 111 |
- **Built to run for hours.** The ledger is the checkpoint: `restore()` resumes a
|
|
|
|
| 286 |
# 4. Confirm nothing broke
|
| 287 |
uv run pytest tests/ -q
|
| 288 |
```
|
| 289 |
+
|
| 290 |
+
---
|
| 291 |
+
|
| 292 |
+
Small models, one shared log, and a clear view of how agents behave in motion.
|
| 293 |
+
**This is Multi-Agent Land.**
|
src/ui/fishbowl/about.py
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""The About tab β a compact, self-contained tour of Multi-Agent Land.
|
| 2 |
+
|
| 3 |
+
What it is, how it works (an HTML/CSS recreation of the agent-ensemble architecture so
|
| 4 |
+
it scales crisply and lives in the CRT theme rather than a flat PNG), and the links a
|
| 5 |
+
judge or visitor needs: the submission video, the GitHub repo, LinkedIn, and the three
|
| 6 |
+
Hugging Face field-notes articles.
|
| 7 |
+
|
| 8 |
+
Pure HTML β no state, no callbacks. Everything is scoped under ``.fishbowl`` so the
|
| 9 |
+
theater stylesheet applies; the About-only rules live in the inline ``<style>`` block.
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
from __future__ import annotations
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
|
| 16 |
+
# ββ links ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 17 |
+
# Repo + articles are known; the video and LinkedIn URLs are filled in by the team
|
| 18 |
+
# (left as obvious placeholders so a missing link reads as TODO, never as broken chrome).
|
| 19 |
+
GITHUB_URL = "https://github.com/abducodez/multi-agent-land"
|
| 20 |
+
VIDEO_URL = "https://youtu.be/v8-zR6eTbDM"
|
| 21 |
+
LINKEDIN_URL = "https://www.linkedin.com/in/gharsallah/"
|
| 22 |
+
ARTICLES = [
|
| 23 |
+
("The overview", "https://huggingface.co/blog/build-small-hackathon/multi-agents-land"),
|
| 24 |
+
(
|
| 25 |
+
"Different scenarios",
|
| 26 |
+
"https://huggingface.co/blog/build-small-hackathon/six-playable-woods-and-a-fishbowl-to-watch-them",
|
| 27 |
+
),
|
| 28 |
+
("Architecture", "https://huggingface.co/blog/build-small-hackathon/one-engine-three-costumes"),
|
| 29 |
+
]
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
# ββ architecture diagram (HTML/CSS recreation of agent_ensemble_architecture.png) ββ
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def _node(title: str, sub: str, *, tone: str, dashed: bool = False) -> str:
|
| 36 |
+
"""One labelled box in the diagram. ``tone`` β {engine, ledger, oversight}."""
|
| 37 |
+
cls = f"ab-node ab-{tone}" + (" ab-dashed" if dashed else "")
|
| 38 |
+
return f'<div class="{cls}"><div class="ab-node-title">{title}</div><div class="ab-node-sub">{sub}</div></div>'
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def _architecture_html() -> str:
|
| 42 |
+
"""Three columns β engine Β· ledger Β· oversight & UI β wired by arrow glyphs.
|
| 43 |
+
|
| 44 |
+
Mirrors the source diagram: the Conductor β Context builder β Worker agents β Tools
|
| 45 |
+
pipeline on the left, the append-only Event ledger in the centre, and the Observer /
|
| 46 |
+
Judge oversight feeding the Client UI on the right."""
|
| 47 |
+
engine = (
|
| 48 |
+
_node("Conductor", "scheduler Β· budgets", tone="engine")
|
| 49 |
+
+ '<div class="ab-arrow ab-down">β</div>'
|
| 50 |
+
+ _node("Context builder", "per-agent memory", tone="engine")
|
| 51 |
+
+ '<div class="ab-arrow ab-down">β</div>'
|
| 52 |
+
+ _node("Worker agents", "small specialist models", tone="engine")
|
| 53 |
+
+ '<div class="ab-arrow ab-down">β</div>'
|
| 54 |
+
+ _node("Tools (MCP)", "pluggable via registry", tone="engine")
|
| 55 |
+
+ _node("+ register new module", "", tone="engine", dashed=True)
|
| 56 |
+
)
|
| 57 |
+
ledger = _node("Event ledger", "append-only event log", tone="ledger")
|
| 58 |
+
oversight = (
|
| 59 |
+
_node("Client UI", "renders the stream", tone="oversight")
|
| 60 |
+
+ '<div class="ab-arrow ab-up">β</div>'
|
| 61 |
+
+ _node("Observer agent", "renders the stream", tone="oversight")
|
| 62 |
+
+ _node("Judge / moderator", "promote Β· gate Β· decide", tone="oversight")
|
| 63 |
+
)
|
| 64 |
+
legend = (
|
| 65 |
+
'<div class="ab-legend">'
|
| 66 |
+
'<span class="ab-key ab-engine"></span>engine'
|
| 67 |
+
'<span class="ab-key ab-ledger"></span>ledger'
|
| 68 |
+
'<span class="ab-key ab-oversight"></span>oversight & UI'
|
| 69 |
+
"</div>"
|
| 70 |
+
)
|
| 71 |
+
return (
|
| 72 |
+
'<div class="ab-arch">'
|
| 73 |
+
f'<div class="ab-col ab-col-engine">{engine}</div>'
|
| 74 |
+
'<div class="ab-wire ab-wire-l">β</div>'
|
| 75 |
+
f'<div class="ab-col ab-col-ledger">{ledger}</div>'
|
| 76 |
+
'<div class="ab-wire ab-wire-r">β</div>'
|
| 77 |
+
f'<div class="ab-col ab-col-oversight">{oversight}</div>'
|
| 78 |
+
"</div>" + legend
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
# ββ tab body βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 83 |
+
|
| 84 |
+
_ABOUT_CSS = """
|
| 85 |
+
.fishbowl .ab-wrap { max-width: 1080px; margin: 0 auto; padding: 28px 22px 40px; line-height: 1.65; }
|
| 86 |
+
.fishbowl .ab-hero h1 { font-size: 30px; letter-spacing: 0.04em; color: var(--ink); }
|
| 87 |
+
.fishbowl .ab-hero .ab-tag { color: var(--cyan); font-style: italic; margin-top: 6px; }
|
| 88 |
+
.fishbowl .ab-lede { color: var(--ink-mid); margin: 16px 0 8px; font-size: 15px; }
|
| 89 |
+
.fishbowl .ab-lede b { color: var(--lime); font-weight: 600; }
|
| 90 |
+
.fishbowl .ab-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
| 91 |
+
gap: 12px; margin: 18px 0 6px; }
|
| 92 |
+
.fishbowl .ab-card { padding: 14px 16px; }
|
| 93 |
+
.fishbowl .ab-card h4 { color: var(--cyan); font-size: 13px; letter-spacing: 0.06em; margin-bottom: 6px; }
|
| 94 |
+
.fishbowl .ab-card p { color: var(--ink-mid); font-size: 13px; margin: 0; }
|
| 95 |
+
|
| 96 |
+
.fishbowl .ab-section-title { margin: 30px 0 14px; }
|
| 97 |
+
|
| 98 |
+
/* architecture diagram */
|
| 99 |
+
.fishbowl .ab-arch { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr;
|
| 100 |
+
align-items: start; gap: 8px; margin: 6px 0 10px; }
|
| 101 |
+
.fishbowl .ab-col { display: flex; flex-direction: column; gap: 6px; }
|
| 102 |
+
.fishbowl .ab-col-ledger { justify-content: center; align-self: stretch; }
|
| 103 |
+
.fishbowl .ab-node { border: 1.5px solid var(--line); border-radius: var(--r-lg);
|
| 104 |
+
padding: 12px 14px; text-align: center; background: var(--panel); }
|
| 105 |
+
.fishbowl .ab-node-title { font-family: var(--font-display); font-weight: 700; font-size: 14px; }
|
| 106 |
+
.fishbowl .ab-node-sub { font-size: 11px; color: var(--ink-dim); margin-top: 3px; }
|
| 107 |
+
.fishbowl .ab-engine { border-color: var(--teal); background: rgba(43,196,180,0.10); }
|
| 108 |
+
.fishbowl .ab-engine .ab-node-title { color: var(--lime); }
|
| 109 |
+
.fishbowl .ab-ledger { border-color: var(--violet); background: rgba(155,140,255,0.12);
|
| 110 |
+
min-height: 100%; display: flex; flex-direction: column; justify-content: center; }
|
| 111 |
+
.fishbowl .ab-ledger .ab-node-title { color: var(--violet); font-size: 16px; }
|
| 112 |
+
.fishbowl .ab-oversight { border-color: var(--coral); background: rgba(255,143,125,0.10); }
|
| 113 |
+
.fishbowl .ab-oversight .ab-node-title { color: var(--coral); }
|
| 114 |
+
.fishbowl .ab-dashed { border-style: dashed; background: transparent; opacity: 0.7; }
|
| 115 |
+
.fishbowl .ab-dashed .ab-node-title { font-size: 12px; color: var(--ink-dim); }
|
| 116 |
+
.fishbowl .ab-arrow { text-align: center; color: var(--ink-faint); font-size: 16px; line-height: 1; }
|
| 117 |
+
.fishbowl .ab-wire { align-self: center; color: var(--ink-faint); font-size: 22px; padding-top: 40px; }
|
| 118 |
+
.fishbowl .ab-legend { display: flex; align-items: center; justify-content: center; gap: 8px;
|
| 119 |
+
flex-wrap: wrap; margin-top: 14px; color: var(--ink-dim); font-size: 12px; }
|
| 120 |
+
.fishbowl .ab-key { width: 13px; height: 13px; border-radius: 3px; display: inline-block;
|
| 121 |
+
margin-left: 14px; border: 1.5px solid; }
|
| 122 |
+
.fishbowl .ab-key.ab-engine { border-color: var(--teal); background: rgba(43,196,180,0.18); }
|
| 123 |
+
.fishbowl .ab-key.ab-ledger { border-color: var(--violet); background: rgba(155,140,255,0.2); }
|
| 124 |
+
.fishbowl .ab-key.ab-oversight { border-color: var(--coral); background: rgba(255,143,125,0.18); }
|
| 125 |
+
|
| 126 |
+
/* link row */
|
| 127 |
+
.fishbowl .ab-links { display: flex; flex-wrap: wrap; gap: 10px; margin: 10px 0 4px; }
|
| 128 |
+
.fishbowl a.ab-link { text-decoration: none; }
|
| 129 |
+
.fishbowl .ab-articles { margin: 10px 0 0; padding: 0; list-style: none; }
|
| 130 |
+
.fishbowl .ab-articles li { margin: 6px 0; }
|
| 131 |
+
.fishbowl .ab-articles a { color: var(--cyan); text-decoration: none; }
|
| 132 |
+
.fishbowl .ab-articles a:hover { color: #fff; text-shadow: var(--glow); }
|
| 133 |
+
|
| 134 |
+
@media (max-width: 760px) {
|
| 135 |
+
.fishbowl .ab-arch { grid-template-columns: 1fr; }
|
| 136 |
+
.fishbowl .ab-wire { display: none; }
|
| 137 |
+
}
|
| 138 |
+
"""
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def _links_html() -> str:
|
| 142 |
+
articles = "".join(
|
| 143 |
+
f'<li>π <a href="{url}" target="_blank" rel="noopener">{label}</a></li>' for label, url in ARTICLES
|
| 144 |
+
)
|
| 145 |
+
return f"""
|
| 146 |
+
<div class="fishbowl">
|
| 147 |
+
<div class="ab-links">
|
| 148 |
+
<a class="ab-link" href="{VIDEO_URL}" target="_blank" rel="noopener"><span class="btn primary">βΆ Submission video</span></a>
|
| 149 |
+
<a class="ab-link" href="{GITHUB_URL}" target="_blank" rel="noopener"><span class="btn"> GitHub</span></a>
|
| 150 |
+
<a class="ab-link" href="{LINKEDIN_URL}" target="_blank" rel="noopener"><span class="btn">in LinkedIn</span></a>
|
| 151 |
+
</div>
|
| 152 |
+
<div class="ab-section-title eyebrow">Field notes · articles</div>
|
| 153 |
+
<ul class="ab-articles">{articles}</ul>
|
| 154 |
+
</div>
|
| 155 |
+
"""
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def build_about() -> dict:
|
| 159 |
+
"""Render the About tab. Pure HTML islands wrapped in the ``.fishbowl`` scope root."""
|
| 160 |
+
gr.HTML(f"<style>{_ABOUT_CSS}</style>")
|
| 161 |
+
gr.HTML(
|
| 162 |
+
"""
|
| 163 |
+
<div class="fishbowl"><div class="ab-wrap">
|
| 164 |
+
<div class="ab-hero">
|
| 165 |
+
<h1>◉ Multi-Agent Land</h1>
|
| 166 |
+
<div class="ab-tag">small minds · one ledger · ≤ 32B</div>
|
| 167 |
+
</div>
|
| 168 |
+
<p class="ab-lede">
|
| 169 |
+
A small-model, multi-agent interactive story engine built on an <b>append-only event
|
| 170 |
+
ledger</b>. Agents never call each other — they post typed events to a shared log,
|
| 171 |
+
and every view (stage, memory, UI) is a <b>projection</b> of that log. One tiny
|
| 172 |
+
event-sourced engine powers many delightful worlds: a whimsical forest theater, a
|
| 173 |
+
mystery-solving blackboard swarm, a tool-using oracle grove — not three apps, but
|
| 174 |
+
three YAML configs of the <b>same engine</b>.
|
| 175 |
+
</p>
|
| 176 |
+
<div class="ab-grid">
|
| 177 |
+
<div class="panel ab-card"><h4>Genuinely alive</h4><p>Watch small specialist agents
|
| 178 |
+
write, judge, remember, and render strange interactive scenes in real time.</p></div>
|
| 179 |
+
<div class="panel ab-card"><h4>AI is load-bearing</h4><p>The multi-agent drama is the
|
| 180 |
+
product — the magic comes from the models, not the scaffolding.</p></div>
|
| 181 |
+
<div class="panel ab-card"><h4>One engine, three costumes</h4><p>Agents bind to models by
|
| 182 |
+
declarative YAML profile; each runs on the small model that fits its job.</p></div>
|
| 183 |
+
</div>
|
| 184 |
+
</div></div>
|
| 185 |
+
"""
|
| 186 |
+
)
|
| 187 |
+
gr.HTML(
|
| 188 |
+
f'<div class="fishbowl"><div class="ab-wrap" style="padding-top:0">'
|
| 189 |
+
f'<div class="ab-section-title eyebrow">How it works · the agent ensemble</div>'
|
| 190 |
+
f"{_architecture_html()}</div></div>"
|
| 191 |
+
)
|
| 192 |
+
gr.HTML(f'<div class="ab-wrap" style="padding-top:0">{_links_html()}</div>')
|
| 193 |
+
return {}
|
src/ui/fishbowl/app.py
CHANGED
|
@@ -49,6 +49,15 @@ except Exception: # pragma: no cover - degrade gracefully if the archive unit i
|
|
| 49 |
return "βΆ (run)"
|
| 50 |
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
try: # hall of fame: the competitive high-score board (Workstream 6.2 + 6.3)
|
| 53 |
from src.ui.fishbowl.hall_of_fame import build_hall_of_fame, wire_sessions_render
|
| 54 |
except Exception: # pragma: no cover - degrade gracefully if the unit is absent
|
|
@@ -731,6 +740,8 @@ def build_app() -> gr.Blocks:
|
|
| 731 |
build_telemetry()
|
| 732 |
with gr.Tab("π Hall of Fame", id="hall"):
|
| 733 |
hall_handles = build_hall_of_fame()
|
|
|
|
|
|
|
| 734 |
|
| 735 |
# CRT foreground layers (scanlines + vignette, above content, click-through).
|
| 736 |
gr.HTML(_CRT_FG_HTML)
|
|
|
|
| 49 |
return "βΆ (run)"
|
| 50 |
|
| 51 |
|
| 52 |
+
try: # about: a compact project tour β what it is, the architecture, the submission links
|
| 53 |
+
from src.ui.fishbowl.about import build_about
|
| 54 |
+
except Exception: # pragma: no cover - degrade gracefully if the unit is absent
|
| 55 |
+
|
| 56 |
+
def build_about() -> dict:
|
| 57 |
+
gr.HTML('<div class="fishbowl"><div class="fishbowl-placeholder">About β coming soon.</div></div>')
|
| 58 |
+
return {}
|
| 59 |
+
|
| 60 |
+
|
| 61 |
try: # hall of fame: the competitive high-score board (Workstream 6.2 + 6.3)
|
| 62 |
from src.ui.fishbowl.hall_of_fame import build_hall_of_fame, wire_sessions_render
|
| 63 |
except Exception: # pragma: no cover - degrade gracefully if the unit is absent
|
|
|
|
| 740 |
build_telemetry()
|
| 741 |
with gr.Tab("π Hall of Fame", id="hall"):
|
| 742 |
hall_handles = build_hall_of_fame()
|
| 743 |
+
with gr.Tab("About", id="about"):
|
| 744 |
+
build_about()
|
| 745 |
|
| 746 |
# CRT foreground layers (scanlines + vignette, above content, click-through).
|
| 747 |
gr.HTML(_CRT_FG_HTML)
|