feat: RHS panel — persistent Agent Status sidebar

Added a Right-Hand Sidebar (RHS) panel to the Mattermost plugin that
shows live agent activity in a dedicated, always-visible panel.

- New RHSPanel component with SessionCard views per active session
- registerAppBarComponent adds 'Agent Status' icon to toolbar
- Subscribes to WebSocket updates via global listener
- Shows active sessions with live elapsed time, tool calls, token count
- Shows recent completed sessions below active ones
- Responsive CSS matching Mattermost design system

The RHS panel solves the scroll-out-of-view problem: the status
dashboard stays visible regardless of chat scroll position.
This commit is contained in:
sol
2026-03-08 19:55:44 +00:00
parent c36a048dbb
commit f0a51ce411
7 changed files with 363 additions and 4 deletions

View File

@@ -195,3 +195,113 @@
.ls-terminal::-webkit-scrollbar-thumb:hover {
background: var(--center-channel-color-32, rgba(0, 0, 0, 0.32));
}
/* ========= RHS Panel Styles ========= */
.ls-rhs-panel {
display: flex;
flex-direction: column;
height: 100%;
overflow-y: auto;
background: var(--center-channel-bg, #fff);
}
.ls-rhs-summary {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 16px;
border-bottom: 1px solid var(--center-channel-color-08, rgba(0, 0, 0, 0.08));
font-size: 13px;
font-weight: 600;
color: var(--center-channel-color, #3d3c40);
}
.ls-rhs-count {
display: flex;
align-items: center;
gap: 6px;
}
.ls-rhs-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 48px 24px;
text-align: center;
}
.ls-rhs-empty-icon {
font-size: 32px;
margin-bottom: 12px;
}
.ls-rhs-empty-text {
color: var(--center-channel-color-48, rgba(0, 0, 0, 0.48));
font-size: 13px;
line-height: 1.5;
}
.ls-rhs-card {
margin: 8px 12px;
border: 1px solid var(--center-channel-color-08, rgba(0, 0, 0, 0.08));
border-radius: 6px;
overflow: hidden;
}
.ls-rhs-card.ls-status-active {
border-color: rgba(76, 175, 80, 0.3);
}
.ls-rhs-card-header {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
background: var(--center-channel-color-04, rgba(0, 0, 0, 0.04));
border-bottom: 1px solid var(--center-channel-color-08, rgba(0, 0, 0, 0.08));
}
.ls-rhs-card .ls-terminal {
max-height: 250px;
font-size: 11px;
padding: 6px 10px;
}
.ls-rhs-card-footer {
padding: 4px 10px 6px;
font-size: 11px;
color: var(--center-channel-color-48, rgba(0, 0, 0, 0.48));
font-family: 'SFMono-Regular', Consolas, monospace;
border-top: 1px solid var(--center-channel-color-08, rgba(0, 0, 0, 0.08));
}
.ls-rhs-children {
padding: 4px 10px;
border-top: 1px solid var(--center-channel-color-08, rgba(0, 0, 0, 0.08));
}
.ls-rhs-child {
padding: 4px 0;
}
.ls-rhs-child-header {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
}
.ls-rhs-section {
margin-top: 4px;
}
.ls-rhs-section-title {
padding: 8px 16px 4px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--center-channel-color-48, rgba(0, 0, 0, 0.48));
}