agent ui: input lives in terminal section, banner shimmer on activity

agent page restructure:
- send form moves into the terminal panel as a prompt-style row beneath
  the live tail (status line stays above so it still reads as a header).
- live panel + prompt share a single bordered 'terminal-wrap' box.
- harness-alive / login-state status lines drop their decorative ascii
  bookends; just a leading dot/glyph remains.
- banner gradient is now a real css gradient with a shimmer animation
  toggled by an .active class. turn_start adds it, turn_end removes it.
  dashboard side mirrors this: each broker sse event nudges a 4s
  shimmer window.
- dashboard container rows drop their static ▓█▓▒░ / ▒░▒░░ glyph
  prefixes; the role chips already disambiguate m1nd vs ag3nt.
- empty-state placeholders drop the ▓ bookends.

terminal pre-fill: hive-ag3nt::events::Bus grows a 500-event ring
buffer; new GET /events/history endpoint returns it. The agent JS
fetches history before opening the SSE stream so opening the page mid-
turn shows the last N events instead of a blank panel. The replay
walks turn_start/turn_end pairs to seed the banner-active state
correctly if a turn was still open.
This commit is contained in:
müde 2026-05-15 18:54:19 +02:00
parent 2770630f33
commit d943bddd9e
7 changed files with 227 additions and 58 deletions

View file

@ -21,12 +21,29 @@ body {
line-height: 1.6;
}
.banner {
color: var(--purple);
text-align: center;
margin: 0 0 1em 0;
font-size: 0.95em;
text-shadow: 0 0 6px rgba(203, 166, 247, 0.55), 0 0 14px rgba(203, 166, 247, 0.25);
overflow-x: auto;
background: linear-gradient(
90deg,
var(--purple-dim) 0%,
var(--purple) 50%,
var(--purple-dim) 100%
);
background-size: 200% 100%;
background-position: 50% 0;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
filter: drop-shadow(0 0 6px rgba(203, 166, 247, 0.45));
}
.banner.active {
animation: banner-shimmer 1.8s linear infinite;
}
@keyframes banner-shimmer {
from { background-position: 200% 0; }
to { background-position: -100% 0; }
}
h2, h3 {
color: var(--purple);
@ -34,12 +51,6 @@ h2, h3 {
letter-spacing: 0.15em;
text-shadow: 0 0 8px rgba(203, 166, 247, 0.4);
}
.divider {
color: var(--purple-dim);
overflow: hidden;
white-space: nowrap;
margin-bottom: 0.5em;
}
.meta { color: var(--muted); font-size: 0.85em; }
.status-online { color: var(--green); text-shadow: 0 0 6px rgba(166, 227, 161, 0.55); }
.status-needs-login { color: var(--amber); text-shadow: 0 0 6px rgba(250, 179, 135, 0.55); }
@ -113,20 +124,59 @@ pre.diff {
word-break: break-all;
max-height: 30em;
}
/* Terminal-ish look for the live panel. Crust as bg (almost-black),
slightly inset, mauve phosphor glow. */
.live.terminal {
/* Terminal-ish wrapper holding the live output + prompt input as one
unit. Crust as bg (almost-black), slightly inset, mauve phosphor glow. */
.terminal-wrap {
background: #11111b;
border: 1px solid var(--purple-dim);
box-shadow: inset 0 0 24px rgba(0, 0, 0, 0.7);
border-radius: 4px;
padding: 0.8em 1em;
overflow-y: auto;
max-height: 32em;
font-family: "JetBrains Mono", "Fira Code", "Cascadia Code", "Source Code Pro", monospace;
font-size: 0.92em;
color: #cdd6f4;
margin-top: 0.6em;
}
.live.terminal {
background: transparent;
border: 0;
box-shadow: none;
border-radius: 0;
padding: 0.8em 1em 0.4em;
overflow-y: auto;
max-height: 32em;
font-family: inherit;
font-size: inherit;
color: inherit;
}
.term-input { padding: 0.4em 1em 0.8em; }
.term-input .sendform-term {
display: flex;
align-items: center;
gap: 0.5em;
border-top: 1px dashed var(--purple-dim);
padding-top: 0.5em;
}
.term-input .prompt {
color: var(--green);
text-shadow: 0 0 6px rgba(166, 227, 161, 0.6);
user-select: none;
flex: 0 0 auto;
}
.term-input input {
flex: 1;
background: transparent;
border: 0;
outline: 0;
color: var(--fg);
font-family: inherit;
font-size: 1em;
padding: 0.2em 0;
caret-color: var(--green);
}
.term-input input::placeholder { color: var(--muted); }
.term-input .submit-hint { color: var(--muted); font-size: 0.8em; flex: 0 0 auto; }
.term-input.disabled .prompt { color: var(--muted); text-shadow: none; }
.term-input.disabled input { color: var(--muted); }
.live {
background: rgba(255, 255, 255, 0.02);
border: 1px solid var(--purple-dim);