Download app.py from FlyingNunchucks/11-distributed-auction-task-allocation-agent: direct link, hf CLI and curl.
- Browser
- Download file 33 kB
-
https://huggingface.co/spaces/FlyingNunchucks/11-distributed-auction-task-allocation-agent/resolve/main/app.py
- Command line
-
hf download hf://spaces/FlyingNunchucks/11-distributed-auction-task-allocation-agent/app.py
-
curl -L -o app.py https://huggingface.co/spaces/FlyingNunchucks/11-distributed-auction-task-allocation-agent/resolve/main/app.py
33 kB
| """Gradio demo for Agent 11 — Distributed Auction Task Allocation Agent.""" | |
| from __future__ import annotations | |
| import html | |
| import sys | |
| import time | |
| from pathlib import Path | |
| import gradio as gr | |
| ROOT = Path(__file__).resolve().parent | |
| SRC = ROOT / "src" | |
| if str(SRC) not in sys.path: | |
| sys.path.insert(0, str(SRC)) | |
| from auction_coordination.demo import ( # noqa: E402 | |
| DemoMode, | |
| DemoSnapshot, | |
| llm_runtime_status, | |
| run_demo, | |
| safe_run_demo, | |
| ) | |
| from auction_coordination.story import ( # noqa: E402 | |
| build_auction_story, | |
| build_peer_story_cards, | |
| ) | |
| AUCTION_HEADERS = ["Task", "Capability", "Winning peer", "Winning score", "Bids", "Abstentions", "Rounds", "Messages", "Execution cost", "Status"] | |
| BID_HEADERS = ["Task", "Peer", "Decision", "Capability", "Confidence", "Availability", "Est. cost", "Auction score", "Outcome", "Why"] | |
| ARCHITECTURE_HEADERS = ["Architecture", "Mission success", "Tasks completed", "Messages", "Messages / task", "Execution cost", "Allocation efficiency", "Allocation authority"] | |
| STRESS_HEADERS = ["Scenario", "Outcome", "Distributed messages", "Centralized messages", "Traffic multiple", "Execution cost", "Same workers", "Scenario design"] | |
| WORK_HEADERS = ["Task", "Peer", "Title", "Summary", "Findings", "Evidence IDs"] | |
| EVENT_HEADERS = ["Seq", "Event", "Task", "Round", "Actor", "Accepted", "Detail"] | |
| PEER_VISUALS = { | |
| "Atlas Research": ("🔭", "Research"), | |
| "Ledger Analyst": ("🧮", "Finance"), | |
| "Sentinel Risk": ("🛡️", "Risk"), | |
| "Veritas Evidence": ("🔎", "Verification"), | |
| "Mosaic Generalist": ("🧩", "Generalist"), | |
| "Quill Synthesis": ("✍️", "Synthesis"), | |
| } | |
| TASK_VISUALS = { | |
| "Market Attractiveness Research": "🌐", | |
| "Financial Quality Analysis": "💹", | |
| "Operating & Execution Risk Review": "⚠️", | |
| "Evidence Verification": "✅", | |
| "Executive Due-Diligence Synthesis": "📝", | |
| } | |
| EVENT_VISUALS = { | |
| "Task Announcement": "📣", | |
| "Bid": "💬", | |
| "Bid Abstention": "↩️", | |
| "Auction Closed": "🔒", | |
| "Task Award": "🏆", | |
| "Task Accepted": "🤝", | |
| "Task Result": "✅", | |
| "Task Failure": "❌", | |
| "Reauction Announcement": "🔁", | |
| "Escalation": "⚠️", | |
| } | |
| # The demo is intentionally paced for human observation. The protocol itself is | |
| # not slowed; only the presentation replay waits between yielded UI frames. | |
| PLAYBACK_DELAY_SECONDS = 0.22 | |
| EVENT_DELAY_MULTIPLIERS = { | |
| "Task Announcement": 2.2, | |
| "Bid": 1.0, | |
| "Bid Abstention": 1.0, | |
| "Auction Closed": 1.6, | |
| "Task Award": 2.6, | |
| "Task Accepted": 1.5, | |
| "Task Result": 2.8, | |
| "Task Failure": 2.8, | |
| "Reauction Announcement": 2.4, | |
| "Escalation": 3.0, | |
| } | |
| APP_CSS = """ | |
| .gradio-container { max-width: 980px !important; } | |
| .hero-card { | |
| border:1px solid rgba(148,163,184,.28); border-radius:24px; padding:28px 30px; | |
| margin-bottom:16px; background:linear-gradient(135deg,rgba(37,99,235,.16),rgba(16,185,129,.08)); | |
| } | |
| .hero-card h1 { margin:6px 0 8px; font-size:2.08rem; line-height:1.14; max-width:820px; } | |
| .hero-card p { margin:0; font-size:1.06rem; line-height:1.5; max-width:790px; opacity:.92; } | |
| .eyebrow,.section-kicker { text-transform:uppercase; letter-spacing:.11em; font-size:.78rem; font-weight:760; opacity:.74; } | |
| .section-title { margin:30px 0 10px; } | |
| .section-title h2 { margin:3px 0; font-size:1.58rem; line-height:1.25; } | |
| .kpi-grid { display:grid; grid-template-columns:1fr; gap:9px; margin:14px 0 24px; } | |
| .kpi-card { display:grid; grid-template-columns:minmax(145px,.75fr) 1fr 1fr; gap:14px; align-items:center; border:1px solid rgba(148,163,184,.25); border-radius:15px; padding:13px 16px; background:rgba(148,163,184,.035); } | |
| .kpi-topic { font-size:.84rem; font-weight:770; letter-spacing:.05em; text-transform:uppercase; opacity:.70; } | |
| .kpi-pair { display:flex; align-items:baseline; gap:8px; } | |
| .kpi-value { font-size:1.32rem; font-weight:800; line-height:1; } | |
| .kpi-label { font-size:.86rem; opacity:.76; } | |
| .story-strip { position:relative; display:grid; grid-template-columns:1fr; gap:10px; margin:12px 0 18px; padding-left:42px; } | |
| .story-strip::before { content:""; position:absolute; left:17px; top:22px; bottom:22px; width:2px; background:rgba(37,99,235,.20); } | |
| .story-node { position:relative; border:1px solid rgba(148,163,184,.25); border-radius:15px; padding:15px 17px; background:rgba(148,163,184,.035); } | |
| .story-node::before { content:""; position:absolute; left:-32px; top:23px; width:12px; height:12px; border-radius:50%; background:#2563eb; box-shadow:0 0 0 5px rgba(37,99,235,.10); } | |
| .story-head { display:flex; align-items:center; gap:9px; margin-bottom:5px; } | |
| .story-icon { font-size:1.32rem; } | |
| .story-node strong { font-size:1.06rem; } | |
| .story-node span { display:block; font-size:.97rem; opacity:.82; line-height:1.45; } | |
| .peer-grid { display:grid; grid-template-columns:1fr; gap:9px; margin:12px 0 18px; } | |
| .peer-card { display:grid; grid-template-columns:50px minmax(180px,.75fr) 1.35fr; gap:13px; align-items:center; border:1px solid rgba(148,163,184,.25); border-radius:16px; padding:14px 16px; background:rgba(148,163,184,.035); } | |
| .peer-avatar { width:44px; height:44px; display:flex; align-items:center; justify-content:center; border-radius:50%; font-size:1.34rem; background:rgba(37,99,235,.10); border:1px solid rgba(37,99,235,.20); } | |
| .peer-name { font-size:1.06rem; font-weight:800; line-height:1.15; } | |
| .peer-role { font-size:.89rem; opacity:.76; margin-top:4px; } | |
| .peer-details { min-width:0; } | |
| .peer-value { font-size:.96rem; line-height:1.45; margin-bottom:8px; } | |
| .chip-row { display:flex; gap:6px; flex-wrap:wrap; } | |
| .chip { border:1px solid rgba(148,163,184,.30); border-radius:999px; padding:4px 8px; font-size:.78rem; opacity:.90; } | |
| .flow-wrap { position:relative; display:grid; grid-template-columns:1fr; gap:9px; margin:12px 0 18px; padding-left:42px; } | |
| .flow-wrap::before { content:""; position:absolute; left:17px; top:25px; bottom:25px; width:2px; background:rgba(16,185,129,.23); } | |
| .flow-stage { position:relative; border:1px solid rgba(148,163,184,.25); border-radius:15px; padding:15px 17px; background:rgba(148,163,184,.035); } | |
| .flow-stage::before { content:""; position:absolute; left:-32px; top:23px; width:12px; height:12px; border-radius:50%; background:#10b981; box-shadow:0 0 0 5px rgba(16,185,129,.10); } | |
| .flow-stage strong { display:block; margin-bottom:6px; font-size:1.05rem; } | |
| .flow-stage small { font-size:.94rem; line-height:1.4; opacity:.78; } | |
| .start-stack { display:flex; gap:7px; flex-wrap:wrap; margin-top:9px; } | |
| .flow-card { border:1px solid rgba(148,163,184,.24); border-radius:999px; padding:6px 10px; font-size:.86rem; background:rgba(148,163,184,.03); } | |
| /* Live protocol playback */ | |
| .activity-shell { border:1px solid rgba(37,99,235,.26); border-radius:18px; padding:16px 18px; margin:14px 0 12px; background:linear-gradient(135deg,rgba(37,99,235,.09),rgba(16,185,129,.035)); } | |
| .activity-head { display:flex; justify-content:space-between; gap:16px; align-items:flex-start; margin-bottom:10px; } | |
| .activity-title-row { display:flex; align-items:center; gap:10px; } | |
| .activity-title { font-size:1.04rem; font-weight:800; } | |
| .activity-subtitle { font-size:.91rem; line-height:1.4; opacity:.78; margin-top:3px; } | |
| .activity-count { flex:0 0 auto; font-size:.82rem; font-weight:750; border:1px solid rgba(148,163,184,.28); border-radius:999px; padding:5px 9px; } | |
| .activity-spinner { width:24px; height:24px; box-sizing:border-box; border:4px solid rgba(37,99,235,.18); border-top-color:#2563eb; border-right-color:#10b981; border-radius:50%; animation:activity-spin .72s linear infinite; flex:0 0 auto; box-shadow:0 0 0 3px rgba(37,99,235,.06); } | |
| .activity-running-label { font-size:.72rem; font-weight:850; letter-spacing:.09em; color:#2563eb; border:1px solid rgba(37,99,235,.28); border-radius:999px; padding:4px 7px; background:rgba(37,99,235,.07); } | |
| @keyframes activity-spin { to { transform:rotate(360deg); } } | |
| .activity-progress { height:7px; border-radius:999px; overflow:hidden; background:rgba(148,163,184,.16); margin-bottom:12px; } | |
| .activity-progress > span { display:block; height:100%; background:linear-gradient(90deg,#2563eb,#10b981); transition:width .24s ease; } | |
| .activity-progress.indeterminate > span { width:34%; animation:activity-slide 1.05s ease-in-out infinite; } | |
| @keyframes activity-slide { 0% { transform:translateX(-110%); } 50% { transform:translateX(190%); } 100% { transform:translateX(-110%); } } | |
| .activity-feed { display:grid; gap:7px; } | |
| .activity-feed.activity-scroll { max-height:430px; overflow-y:auto; padding-right:8px; scrollbar-gutter:stable; } | |
| .activity-scroll-note { font-size:.82rem; opacity:.72; margin:2px 0 10px; } | |
| .activity-event { display:grid; grid-template-columns:32px minmax(0,1fr); gap:9px; align-items:start; border-top:1px solid rgba(148,163,184,.16); padding-top:8px; } | |
| .activity-event:first-child { border-top:0; padding-top:0; } | |
| .activity-event.latest { border-radius:10px; padding:8px 9px; margin:0 -9px; background:rgba(37,99,235,.075); border-top-color:transparent; } | |
| .activity-icon { font-size:1.05rem; line-height:1.45; } | |
| .activity-main { font-size:.94rem; line-height:1.35; } | |
| .activity-main strong { font-weight:800; } | |
| .activity-meta { font-size:.78rem; opacity:.67; margin-top:2px; } | |
| .activity-detail { font-size:.82rem; opacity:.77; margin-top:3px; line-height:1.35; } | |
| .activity-complete { border-color:rgba(16,185,129,.32); background:linear-gradient(135deg,rgba(16,185,129,.10),rgba(37,99,235,.04)); } | |
| .auction-grid { display:grid; grid-template-columns:1fr; gap:10px; margin-top:12px; } | |
| .auction-card { border:1px solid rgba(148,163,184,.25); border-radius:16px; padding:16px 18px; background:rgba(148,163,184,.035); } | |
| .auction-top { display:grid; grid-template-columns:minmax(0,1.28fr) minmax(210px,.72fr); gap:16px; align-items:start; } | |
| .auction-card h3 { margin:0 0 6px; font-size:1.10rem; line-height:1.3; } | |
| .auction-question { font-size:.95rem; line-height:1.45; opacity:.80; } | |
| .auction-winner { font-size:1rem; font-weight:800; margin-bottom:7px; } | |
| .auction-stats { display:flex; gap:6px; flex-wrap:wrap; } | |
| .auction-stat { border-radius:999px; border:1px solid rgba(148,163,184,.28); padding:4px 8px; font-size:.78rem; } | |
| .auction-card details { margin-top:10px; font-size:.92rem; line-height:1.45; } | |
| .auction-card summary { cursor:pointer; font-size:.94rem; font-weight:700; } | |
| .result-card { border:1px solid rgba(148,163,184,.25); border-radius:16px; padding:14px 17px; font-size:1rem; line-height:1.45; } | |
| .control-note { border-left:4px solid #2563eb; padding:12px 15px; background:rgba(37,99,235,.07); border-radius:8px; margin:10px 0; font-size:.96rem; line-height:1.45; } | |
| .tech-divider { margin-top:26px; padding-top:10px; border-top:1px solid rgba(148,163,184,.25); } | |
| @media(max-width:780px){ | |
| .gradio-container { max-width:100% !important; } | |
| .kpi-card { grid-template-columns:1fr; gap:7px; } | |
| .peer-card { grid-template-columns:50px 1fr; } | |
| .peer-details { grid-column:1 / -1; padding-left:63px; } | |
| .auction-top { grid-template-columns:1fr; } | |
| .activity-head { display:block; } | |
| .activity-count { display:inline-block; margin-top:8px; } | |
| .activity-feed.activity-scroll { max-height:360px; } | |
| } | |
| """ | |
| def _auction_rows(snapshot: DemoSnapshot) -> list[list[object]]: | |
| return [[r.task, r.capability, r.winner, r.score, r.bids, r.abstentions, r.rounds, r.messages, r.execution_cost, r.status] for r in snapshot.auction_rows] | |
| def _architecture_rows(snapshot: DemoSnapshot) -> list[list[object]]: | |
| return [[r.architecture, r.mission_success, r.tasks_completed, r.messages, r.messages_per_task, r.execution_cost, r.allocation_efficiency, r.allocation_authority] for r in snapshot.architecture_rows] | |
| def _stress_rows(snapshot: DemoSnapshot) -> list[list[object]]: | |
| return [[r.scenario, r.outcome, r.distributed_messages, r.centralized_messages, r.message_multiplier, r.execution_cost, r.same_workers, r.observation] for r in snapshot.stress_rows] | |
| def _work_rows(snapshot: DemoSnapshot) -> list[list[object]]: | |
| return [[r.task, r.peer, r.title, r.summary, r.findings, r.evidence] for r in snapshot.work_product_rows] | |
| def _event_rows(snapshot: DemoSnapshot) -> list[list[object]]: | |
| return [[r.sequence, r.event, r.task, r.round, r.actor, r.accepted, r.detail] for r in snapshot.event_rows] | |
| def _bid_rows(snapshot: DemoSnapshot) -> list[list[object]]: | |
| _, rows = build_auction_story(snapshot.mission) | |
| return [[r.task, r.peer, r.decision, r.capability, r.confidence, r.availability, r.estimated_cost, r.auction_score, r.outcome, r.reason] for r in rows] | |
| def _kpi_html(snapshot: DemoSnapshot) -> str: | |
| m = snapshot.mission.metrics | |
| efficiency = f"{m.allocation_efficiency:.0%}" if m.allocation_efficiency is not None else "—" | |
| groups = [ | |
| ("Workforce", ("6", "AI peers"), (f"{m.tasks_completed}/5", "work packages")), | |
| ("Marketplace", (str(m.total_bids), "bids submitted"), (str(m.total_messages), "protocol messages")), | |
| ("Outcome", (f"${m.total_synthetic_execution_cost:,.0f}", "synthetic cost"), (efficiency, "allocation efficiency")), | |
| ] | |
| cards = [] | |
| for topic, left, right in groups: | |
| cards.append( | |
| "<div class='kpi-card'>" | |
| f"<div class='kpi-topic'>{html.escape(topic)}</div>" | |
| f"<div class='kpi-pair'><span class='kpi-value'>{html.escape(left[0])}</span><span class='kpi-label'>{html.escape(left[1])}</span></div>" | |
| f"<div class='kpi-pair'><span class='kpi-value'>{html.escape(right[0])}</span><span class='kpi-label'>{html.escape(right[1])}</span></div>" | |
| "</div>" | |
| ) | |
| return "<div class='kpi-grid'>" + "".join(cards) + "</div>" | |
| def _team_html() -> str: | |
| rendered = [] | |
| for card in build_peer_story_cards(): | |
| icon, label = PEER_VISUALS[card.name] | |
| strengths = [part.strip() for part in card.strengths.split("·")] | |
| chips = "".join(f"<span class='chip'>{html.escape(item)}</span>" for item in strengths[:2]) | |
| rendered.append( | |
| "<div class='peer-card'>" | |
| f"<div class='peer-avatar'>{icon}</div>" | |
| f"<div><div class='peer-name'>{html.escape(card.name)}</div><div class='peer-role'>{html.escape(label)} · {html.escape(card.availability)} available</div></div>" | |
| "<div class='peer-details'>" | |
| f"<div class='peer-value'>{html.escape(card.business_value)}</div>" | |
| f"<div class='chip-row'>{chips}</div>" | |
| "</div></div>" | |
| ) | |
| return "<div class='peer-grid'>" + "".join(rendered) + "</div>" | |
| def _auction_story_html(snapshot: DemoSnapshot) -> str: | |
| cards, _ = build_auction_story(snapshot.mission) | |
| rendered = [] | |
| for card in cards: | |
| icon = TASK_VISUALS.get(card.task, "📌") | |
| rendered.append( | |
| "<div class='auction-card'><div class='auction-top'><div>" | |
| f"<h3>{icon} {html.escape(card.task)}</h3>" | |
| f"<div class='auction-question'>{html.escape(card.business_question)}</div></div><div>" | |
| f"<div class='auction-winner'>🏆 {html.escape(card.winner)}</div><div class='auction-stats'>" | |
| f"<span class='auction-stat'>{card.bids} bids</span>" | |
| f"<span class='auction-stat'>{card.abstentions} abstain</span>" | |
| f"<span class='auction-stat'>score {html.escape(card.winning_score)}</span>" | |
| f"<span class='auction-stat'>runner-up {html.escape(card.runner_up)}</span>" | |
| "</div></div></div>" | |
| f"<details><summary>Why this peer won</summary><p>{html.escape(card.why_winner)}</p></details></div>" | |
| ) | |
| return "<div class='auction-grid'>" + "".join(rendered) + "</div>" | |
| def _mission_status(snapshot: DemoSnapshot) -> str: | |
| m = snapshot.mission.metrics | |
| if m.mission_success: | |
| return f"### Mission completed ✅\n**{m.tasks_completed}/5** diligence tasks completed with application-controlled allocation." | |
| return f"### Mission escalated safely ⚠️\n**{m.tasks_completed}/5** tasks completed. Dependent work stopped instead of bypassing a failed boundary." | |
| def _raw_snapshot(snapshot: DemoSnapshot) -> dict[str, object]: | |
| m = snapshot.mission.metrics | |
| return { | |
| "mode": snapshot.mode.value, | |
| "mission_success": m.mission_success, | |
| "tasks_completed": m.tasks_completed, | |
| "total_bids": m.total_bids, | |
| "total_abstentions": m.total_abstentions, | |
| "total_messages": m.total_messages, | |
| "total_synthetic_execution_cost": m.total_synthetic_execution_cost, | |
| "allocation_efficiency": m.allocation_efficiency, | |
| "winning_peers": [row.winner for row in snapshot.auction_rows], | |
| } | |
| def _idle_activity_html() -> str: | |
| return ( | |
| "<div class='activity-shell'><div class='activity-head'><div>" | |
| "<div class='activity-title'>▶ Live Marketplace Activity</div>" | |
| "<div class='activity-subtitle'>Click <b>Run the diligence marketplace</b> to watch task announcements, peer bids, abstentions, awards, and results appear here.</div>" | |
| "</div><div class='activity-count'>Ready</div></div>" | |
| "<div class='activity-progress'><span style='width:0%'></span></div></div>" | |
| ) | |
| def _starting_activity_html(mode: DemoMode) -> str: | |
| mode_name = "LLM-assisted" if mode is DemoMode.LLM_ASSISTED else "Deterministic" | |
| return ( | |
| "<div class='activity-shell'><div class='activity-head'><div>" | |
| "<div class='activity-title-row'><span class='activity-spinner'></span><span class='activity-running-label'>RUNNING</span><div class='activity-title'>Starting marketplace</div></div>" | |
| f"<div class='activity-subtitle'>{html.escape(mode_name)} work-product execution selected. The system is computing the mission before replaying its audited protocol events.</div>" | |
| "</div><div class='activity-count'>Working</div></div>" | |
| "<div class='activity-progress indeterminate'><span></span></div>" | |
| "<div class='activity-subtitle'>The spinner and moving bar mean the run is still active even if no new protocol message is available yet.</div>" | |
| "</div>" | |
| ) | |
| def _event_action(event_name: str) -> str: | |
| return { | |
| "Task Announcement": "opened an auction", | |
| "Bid": "submitted a BID", | |
| "Bid Abstention": "ABSTAINED", | |
| "Auction Closed": "closed the auction", | |
| "Task Award": "issued the award", | |
| "Task Accepted": "accepted the assignment", | |
| "Task Result": "completed the work", | |
| "Task Failure": "reported a failure", | |
| "Reauction Announcement": "reopened the auction", | |
| "Escalation": "escalated the task", | |
| }.get(event_name, event_name.lower()) | |
| def _playback_delay_for_event(event_name: str, base_delay: float = PLAYBACK_DELAY_SECONDS) -> float: | |
| if base_delay <= 0: | |
| return 0.0 | |
| return base_delay * EVENT_DELAY_MULTIPLIERS.get(event_name, 1.0) | |
| def _activity_html(snapshot: DemoSnapshot, event_count: int, *, complete: bool = False) -> str: | |
| total = max(len(snapshot.event_rows), 1) | |
| event_count = max(0, min(event_count, len(snapshot.event_rows))) | |
| progress = 100 if complete else max(2, round((event_count / total) * 100)) | |
| if complete: | |
| visible_events = snapshot.event_rows[:event_count] | |
| else: | |
| visible_events = snapshot.event_rows[max(0, event_count - 8):event_count] | |
| completed_tasks = sum(1 for row in snapshot.event_rows[:event_count] if row.event == "Task Result") | |
| if event_count: | |
| current = snapshot.event_rows[event_count - 1] | |
| current_task, current_phase = current.task, current.event | |
| else: | |
| current_task, current_phase = "Preparing first auction", "Starting" | |
| if complete: | |
| title = "✅ Marketplace run complete" | |
| subtitle = f"{snapshot.mission.metrics.tasks_completed}/5 work packages completed. Final results are now published below." | |
| counter = f"{len(snapshot.event_rows)} messages" | |
| shell_class = "activity-shell activity-complete" | |
| title_html = f"<div class='activity-title'>{html.escape(title)}</div>" | |
| feed_class = "activity-feed activity-scroll" | |
| scroll_note = f"<div class='activity-scroll-note'>Scroll inside this transcript to review all {event_count} protocol messages.</div>" | |
| else: | |
| title = f"Live Marketplace Activity · {current_task}" | |
| subtitle = f"Phase: {current_phase} · Completed work packages: {completed_tasks}/5" | |
| counter = f"{event_count}/{len(snapshot.event_rows)} messages" | |
| shell_class = "activity-shell" | |
| title_html = f"<div class='activity-title-row'><span class='activity-spinner'></span><span class='activity-running-label'>RUNNING</span><div class='activity-title'>⚡ {html.escape(title)}</div></div>" | |
| feed_class = "activity-feed" | |
| scroll_note = "" | |
| rendered = [] | |
| for index, row in enumerate(visible_events): | |
| icon = EVENT_VISUALS.get(row.event, "•") | |
| actor = row.actor if row.actor != "—" else "Protocol" | |
| latest = " latest" if index == len(visible_events) - 1 and not complete else "" | |
| rendered.append( | |
| f"<div class='activity-event{latest}'><div class='activity-icon'>{icon}</div><div>" | |
| f"<div class='activity-main'><strong>{html.escape(actor)}</strong> {_event_action(row.event)} · {html.escape(row.task)}</div>" | |
| f"<div class='activity-meta'>Round {row.round} · Message {row.sequence} · {html.escape(row.event)}</div>" | |
| f"<div class='activity-detail'>{html.escape(row.detail)}</div></div></div>" | |
| ) | |
| feed = "".join(rendered) or "<div class='activity-subtitle'>Waiting for the first protocol message…</div>" | |
| return ( | |
| f"<div class='{shell_class}'><div class='activity-head'><div>{title_html}" | |
| f"<div class='activity-subtitle'>{html.escape(subtitle)}</div></div>" | |
| f"<div class='activity-count'>{html.escape(counter)}</div></div>" | |
| f"<div class='activity-progress'><span style='width:{progress}%'></span></div>" | |
| f"{scroll_note}<div class='{feed_class}'>{feed}</div></div>" | |
| ) | |
| def _outputs_for_snapshot(snapshot: DemoSnapshot): | |
| return ( | |
| _kpi_html(snapshot), _mission_status(snapshot), snapshot.executive_summary, | |
| _auction_story_html(snapshot), _auction_rows(snapshot), _bid_rows(snapshot), | |
| _work_rows(snapshot), _architecture_rows(snapshot), snapshot.stress_summary, | |
| _stress_rows(snapshot), _event_rows(snapshot), _raw_snapshot(snapshot), | |
| ) | |
| def _run_from_ui(mode_label: str): | |
| mode = DemoMode.LLM_ASSISTED if mode_label == "LLM-assisted" else DemoMode.DETERMINISTIC | |
| snapshot, error = safe_run_demo(mode) | |
| if snapshot is None: | |
| return ( | |
| "", "### Mission not started\n" + (error or "Live model configuration is unavailable."), | |
| "### No business result published\nChoose **Deterministic** to run the complete marketplace without a model provider.", | |
| "<div class='control-note'>Marketplace did not start, so there are no auction results to display.</div>", | |
| [], [], [], [], "", [], [], {"error": error, "mode": mode.value}, | |
| ) | |
| return _outputs_for_snapshot(snapshot) | |
| def _running_outputs(mode: DemoMode): | |
| return ( | |
| "<div class='control-note'><strong>Marketplace running.</strong> Final metrics will publish after the protocol playback completes.</div>", | |
| "### Mission running…\nWatch **Live Marketplace Activity** above for the current task and protocol phase.", | |
| "### Executive result pending\nThe final diligence synthesis will publish only after the work chain completes.", | |
| "<div class='control-note'>Auction outcomes will publish after the live protocol playback.</div>", | |
| [], [], [], [], "", [], [], {"status": "running", "mode": mode.value}, | |
| ) | |
| def _stream_run_from_ui(mode_label: str, playback_delay: float = PLAYBACK_DELAY_SECONDS): | |
| """Yield human-paced protocol playback frames before publishing final outputs.""" | |
| mode = DemoMode.LLM_ASSISTED if mode_label == "LLM-assisted" else DemoMode.DETERMINISTIC | |
| running = _running_outputs(mode) | |
| yield (_starting_activity_html(mode), *running) | |
| # Give the browser a brief chance to paint the animated running state before | |
| # the synchronous mission computation begins. | |
| if playback_delay > 0: | |
| time.sleep(min(0.18, playback_delay)) | |
| snapshot, error = safe_run_demo(mode) | |
| if snapshot is None: | |
| failed = _run_from_ui(mode_label) | |
| error_activity = ( | |
| "<div class='activity-shell'><div class='activity-head'><div>" | |
| "<div class='activity-title'>⚠️ Marketplace could not start</div>" | |
| f"<div class='activity-subtitle'>{html.escape(error or 'Runtime configuration is unavailable.')}</div>" | |
| "</div><div class='activity-count'>Stopped safely</div></div></div>" | |
| ) | |
| yield (error_activity, *failed) | |
| return | |
| for event_count, row in enumerate(snapshot.event_rows, start=1): | |
| yield (_activity_html(snapshot, event_count), *running) | |
| delay = _playback_delay_for_event(row.event, playback_delay) | |
| if delay > 0: | |
| time.sleep(delay) | |
| yield (_activity_html(snapshot, len(snapshot.event_rows), complete=True), *_outputs_for_snapshot(snapshot)) | |
| DEFAULT_SNAPSHOT = run_demo(DemoMode.DETERMINISTIC) | |
| DEFAULT_OUTPUTS = _outputs_for_snapshot(DEFAULT_SNAPSHOT) | |
| with gr.Blocks(title="Agent 11 — Distributed Auction Task Allocation", analytics_enabled=False) as demo: | |
| gr.HTML(""" | |
| <div class="hero-card"> | |
| <div class="eyebrow">Agent 11 · Distributed Task Marketplace</div> | |
| <h1>When several AI specialists can do the same work, who gets the assignment?</h1> | |
| <p>A fictional acquisition team turns five diligence jobs into a controlled internal marketplace. Peers choose whether to compete; deterministic application rules choose the winner.</p> | |
| </div> | |
| """) | |
| kpi_html = gr.HTML(DEFAULT_OUTPUTS[0]) | |
| gr.HTML(""" | |
| <div class="section-title"><div class="section-kicker">The business case</div><h2>Follow one decision from buyer to diligence result</h2></div> | |
| <div class="story-strip"> | |
| <div class="story-node"><div class="story-head"><div class="story-icon">🏢</div><strong>1 · Horizon Dynamics</strong></div><span>Buyer considering whether to advance a fictional acquisition.</span></div> | |
| <div class="story-node"><div class="story-head"><div class="story-icon">📦</div><strong>2 · Five diligence jobs</strong></div><span>Market, finance, risk, verification, and executive synthesis must be completed.</span></div> | |
| <div class="story-node"><div class="story-head"><div class="story-icon">⚖️</div><strong>3 · AI task marketplace</strong></div><span>Six peers independently BID or ABSTAIN under the same published rules.</span></div> | |
| <div class="story-node"><div class="story-head"><div class="story-icon">📋</div><strong>4 · Next-stage decision</strong></div><span>Validated specialist work becomes an executive diligence package.</span></div> | |
| </div> | |
| """) | |
| with gr.Accordion("Why use an auction instead of a manager?", open=False): | |
| gr.Markdown( | |
| "Several peers are qualified for overlapping work. The auction makes allocation explicit and auditable: " | |
| "who is qualified, available, confident enough to compete, within budget, and why one valid bid beat another. " | |
| "The demo is about **allocation authority**, not claiming auctions are always cheaper than centralized assignment." | |
| ) | |
| gr.HTML("<div class='section-title'><div class='section-kicker'>Meet the team</div><h2>Read the roster from top to bottom</h2></div>" + _team_html()) | |
| gr.HTML(""" | |
| <div class="section-title"><div class="section-kicker">Work flow</div><h2>The diligence package advances through three stages</h2></div> | |
| <div class="flow-wrap"> | |
| <div class="flow-stage"><strong>Stage 1 · Specialist analysis</strong><small>Three independent tasks can begin without upstream work.</small><div class="start-stack"><span class="flow-card">🌐 Market</span><span class="flow-card">💹 Finance</span><span class="flow-card">⚠️ Risk</span></div></div> | |
| <div class="flow-stage"><strong>Stage 2 · Evidence verification</strong><small>✅ Veritas checks the evidence and lineage behind all three specialist outputs.</small></div> | |
| <div class="flow-stage"><strong>Stage 3 · Executive synthesis</strong><small>📝 Validated work is converted into the final next-stage diligence recommendation.</small></div> | |
| </div> | |
| """) | |
| with gr.Accordion("How each auction works", open=False): | |
| gr.Markdown( | |
| "**1. Announce** the task and constraints → **2. Peers choose BID or ABSTAIN** → " | |
| "**3. Valid bids are scored** → **4. Winner executes**. If an awarded peer explicitly fails, " | |
| "the protocol allows one bounded reauction before escalation.\n\n" | |
| "**Score:** 45% capability + 25% confidence + 20% availability + 10% cost efficiency. The LLM never selects the winner." | |
| ) | |
| gr.Markdown("### Run the marketplace") | |
| mode = gr.Radio( | |
| choices=["Deterministic", "LLM-assisted"], value="Deterministic", | |
| label="Work-product execution mode", | |
| info="Allocation is deterministic in both modes; this changes only how the winner drafts its work product.", | |
| ) | |
| gr.Markdown("**Live LLM runtime:** " + llm_runtime_status() + " \n**Core rule:** *Peers decide whether to compete. The protocol decides who wins.*") | |
| run_button = gr.Button("Run the diligence marketplace", variant="primary") | |
| live_activity = gr.HTML(_idle_activity_html()) | |
| mission_status = gr.Markdown(DEFAULT_OUTPUTS[1], elem_classes=["result-card"]) | |
| with gr.Accordion("Open executive diligence result", open=False): | |
| executive_summary = gr.Markdown(DEFAULT_OUTPUTS[2]) | |
| gr.HTML("<div class='tech-divider'><div class='section-kicker'>See the result</div><h2>Business story first. Engineering evidence underneath.</h2></div>") | |
| with gr.Tabs(): | |
| with gr.Tab("Business Walkthrough"): | |
| gr.Markdown("### Five auctions, one vertical reading path\nOpen **Why this peer won** only when you want the scoring detail.") | |
| auction_story = gr.HTML(DEFAULT_OUTPUTS[3]) | |
| with gr.Accordion("Show the compact allocation table", open=False): | |
| auction_table = gr.Dataframe(headers=AUCTION_HEADERS, value=DEFAULT_OUTPUTS[4], interactive=False, label="Five awarded work packages") | |
| with gr.Tab("Auction Room"): | |
| gr.Markdown("### Every BID / ABSTAIN decision\nFor the technical viewer: inspect the inputs, score, rank, and reason behind each peer decision.") | |
| bid_table = gr.Dataframe(headers=BID_HEADERS, value=DEFAULT_OUTPUTS[5], interactive=False, label="All peer decisions") | |
| with gr.Tab("Work Products"): | |
| gr.Markdown("### What the winning peers produced\nLLM-assisted mode changes the drafted content **after award**; it does not change allocation authority.") | |
| work_table = gr.Dataframe(headers=WORK_HEADERS, value=DEFAULT_OUTPUTS[6], interactive=False, label="Validated work products") | |
| with gr.Tab("Architecture Tradeoff"): | |
| gr.Markdown("### Central manager vs distributed marketplace\nSame peers, tasks, economics, utility, executor, and failure limit. Only allocation authority changes.") | |
| architecture_table = gr.Dataframe(headers=ARCHITECTURE_HEADERS, value=DEFAULT_OUTPUTS[7], interactive=False, label="Controlled comparison") | |
| with gr.Tab("Stress & Recovery"): | |
| gr.Markdown("### What happens under pressure?\nBudgets, capability floors, confidence, availability, ties, missing bids, and execution failures are varied deterministically.") | |
| stress_summary = gr.Markdown(DEFAULT_OUTPUTS[8], elem_classes=["result-card"]) | |
| stress_table = gr.Dataframe(headers=STRESS_HEADERS, value=DEFAULT_OUTPUTS[9], interactive=False, label="Nine stress scenarios") | |
| with gr.Tab("Engineering Audit"): | |
| gr.Markdown( | |
| "### Technical evidence\n" | |
| "**Model may draft:** title, summary, findings, approved evidence references. \n" | |
| "**Application owns:** identity, capability authority, admission, weights, tie-breaks, winner selection, award lineage, reauction, escalation, evidence allowlists, and publication." | |
| ) | |
| event_table = gr.Dataframe(headers=EVENT_HEADERS, value=DEFAULT_OUTPUTS[10], interactive=False, label="Append-only mission events") | |
| raw_snapshot = gr.JSON(value=DEFAULT_OUTPUTS[11], label="Compact mission snapshot") | |
| run_button.click( | |
| fn=_stream_run_from_ui, | |
| inputs=[mode], | |
| outputs=[live_activity, kpi_html, mission_status, executive_summary, auction_story, auction_table, bid_table, work_table, architecture_table, stress_summary, stress_table, event_table, raw_snapshot], | |
| show_progress="minimal", | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(css=APP_CSS) | |