diff --git a/app/api/server.py b/app/api/server.py
index 531ca2e..b1e14b3 100644
--- a/app/api/server.py
+++ b/app/api/server.py
@@ -67,6 +67,17 @@ def health() -> dict[str, str]:
return {"status": "ok"}
+@app.get("/events")
+def list_events(limit: int = 500) -> dict[str, object]:
+ safe_limit = max(1, min(limit, 2000))
+ return {
+ "events": [
+ event.model_dump(mode="json")
+ for event in runtime.event_bus.list_recent(limit=safe_limit)
+ ]
+ }
+
+
@app.post("/chat")
def chat(task: UserTask) -> dict[str, object]:
return runtime.handle_task(task)
diff --git a/app/api/static/index.html b/app/api/static/index.html
index 330f8b6..0eb333f 100644
--- a/app/api/static/index.html
+++ b/app/api/static/index.html
@@ -76,7 +76,7 @@
button.danger {
background: #b42318;
}
- .messages, .events {
+ .messages, .runtime-log, .events {
display: grid;
gap: 12px;
max-height: 520px;
@@ -86,10 +86,13 @@
.messages {
width: 100%;
}
- .events {
- width: 100%;
+ .runtime-log {
+ margin-top: 12px;
}
- .bubble, .event {
+ .events {
+ max-height: 70vh;
+ }
+ .bubble, .event, .runtime-entry {
border: 1px solid var(--border);
border-radius: 14px;
padding: 12px;
@@ -109,6 +112,15 @@
flex-wrap: wrap;
margin-top: 10px;
}
+ .panel-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ }
+ .panel-header button {
+ margin-top: 0;
+ }
dialog {
border: 1px solid var(--border);
border-radius: 8px;
@@ -119,6 +131,9 @@
dialog::backdrop {
background: rgba(20, 18, 15, 0.4);
}
+ dialog.wide {
+ width: min(920px, calc(100vw - 32px));
+ }
.modal-body {
display: grid;
gap: 12px;
@@ -163,10 +178,25 @@
+