Knowledge Pack Files
SideButton Dashboard Knowledge Pack Files
Browse the source files that power the SideButton Dashboard MCP server knowledge pack.
sidebutton install sidebutton.local What This Is
The Agents page manages autonomous AI agent jobs that run in terminal processes. Users can start new agents by selecting a role and providing a prompt, monitor running agents with real-time metrics (actions, tokens, cost), view completed agent results, stop running agents, and re-queue completed agents. Agents are autonomous workflows that pick up issues and work on them (SE, QA, PM roles). The page splits into two live sections: "Running ({count})" and "Completed Today ({count})". A waiting (queued) state exists between start and active execution.
URL Patterns
| View | URL | Notes |
|---|---|---|
| Agents List | /agents | Shows running + completed agents |
| Agent Detail | /agents/{run_id} | Single agent run log detail (navigated via navigateToRunLogDetail(agent.run_id)) |
Page Structure
+--[Header: "Agents" + Refresh icon + "+ Start Agent" button]--+
| |
| === Running ({count}) === |
| [Agent Card (.agent-card.waiting)] ← queued, not started |
| Status dot (.status-dot.waiting, amber) |
| Title (agent.workflow_title) + role badge (UPPERCASED) |
| "Queued {time}" |
| Prompt (.agent-prompt block, if initial_prompt present) |
| [View Log] [Stop] buttons |
| |
| [Agent Card (.agent-card.running)] ← actively executing |
| Status dot (.status-dot.running, green pulse) |
| Title (agent.workflow_title) + role badge (UPPERCASED) |
| Started time + duration |
| Prompt (.agent-prompt block, if initial_prompt present) |
| Metrics (.agent-metrics): Actions | Tokens | Cost |
| Current task (.agent-output, monospace #1e1e2e bg) |
| [View Log] [Stop] buttons |
| |
| === Completed Today ({count}) === |
| [Agent Card (.agent-card)] |
| Status dot (.status-dot.success or .status-dot.failed) |
| Title (agent.workflow_title) + role badge (UPPERCASED) |
| Duration + completion time |
| Result (.agent-result): "Result: ..." or "Error: ..." |
| [View Log] [Resend / Resending...] buttons |
| |
| [Empty State (.empty-card): "No Agents Running"] |
| Description + "+ Start Agent" button |
| |
| [Loading (.loading div): "Loading agents..."] |
| |
+--[Start Agent Modal]------------------------------------+
| .modal-overlay (click to close) |
| .modal (click stops propagation) |
| "Start Agent" heading |
| Role: native <select> with role options |
| Prompt: textarea with placeholder |
| [Cancel] [Start Agent / Starting...] buttons |
+---------------------------------------------------------+
Key Elements
Header
| Element | Selector | Notes |
|---|---|---|
| Page title | heading "Agents" | H1 in banner |
| Refresh button | button "Refresh agents" (title attr) | Icon button; disabled + SVG spins while isRefreshing. Reloads agents list |
| Start Agent button | button "+ Start Agent" | Opens Start Agent modal |
Waiting Agent Card (queued, not yet started)
| Element | Selector | Notes |
|---|---|---|
| Card container | .agent-card.waiting | Amber left border: border-left: 3px solid var(--color-warning, #f59e0b) |
| Status dot | .status-dot.waiting | Solid amber — not animated |
| Agent title | .agent-title span | Sourced from agent.workflow_title |
| Role badge | .role-badge | Uppercased role slug (e.g., SE, SOFTWARE-ENGINEER) |
| Queued time | text "Queued {time}" | Shown instead of "Started" for waiting agents |
| Prompt block | .agent-prompt | Shows agent.initial_prompt if present |
| View Log button | button "View Log" | Available on waiting agents |
| Stop button | button "Stop" | Available on waiting agents |
Running Agent Card
| Element | Selector | Notes |
|---|---|---|
| Card container | .agent-card.running | Green left border: border-left: 3px solid var(--color-success) |
| Status dot | .status-dot.running | Animated green pulse — indicates agent is active |
| Agent title | .agent-title span | Sourced from agent.workflow_title |
| Role badge | .role-badge | Uppercased role slug — agent.role.toUpperCase() (e.g., SOFTWARE-ENGINEER, QA-AGENT-—-UNIVERSAL-WEB-APP-TESTING) |
| Prompt block | .agent-prompt | Shows agent.initial_prompt — conditionally rendered, omitted if field absent |
| Metrics row | .agent-metrics | Three spans: "Actions: {count}", "Tokens: {formatted}", "Cost: ${amount}" |
| Current task output | .agent-output | Monospace font, dark background #1e1e2e |
| View Log button | button "View Log" | Calls navigateToRunLogDetail(agent.run_id) |
| Stop button | button "Stop" | Triggers confirm("Stop this agent?") then POST /api/agents/{run_id}/stop |
Completed Agent Card
| Element | Selector | Notes |
|---|---|---|
| Card container | .agent-card | No extra class for base completed state |
| Failed card | .agent-card.failed | Red left border: border-left: 3px solid var(--color-error) |
| Status dot (success) | .status-dot.success | Solid green — not animated |
| Status dot (failed) | .status-dot.failed | Solid red |
| Agent title | .agent-title span | Sourced from agent.workflow_title |
| Role badge | .role-badge | Uppercased role slug (same as running card) |
| Result block | .agent-result | Prefixed with "Result:" (success) or "Error:" (failure). Sourced from agent.result_summary. Conditionally rendered |
| View Log button | button "View Log" | Calls navigateToRunLogDetail(agent.run_id) |
| Resend button | button "Resend" | Re-queues completed/failed agent. Shows "Resending..." while in progress (disabled). Toast "Job re-queued" on success |
Start Agent Modal
| Element | Selector | Notes |
|---|---|---|
| Overlay | .modal-overlay | Click anywhere on overlay closes modal (showStartModal = false) |
| Modal container | .modal | Click inside stops propagation — overlay click does not bleed through |
| Modal heading | heading "Start Agent" | Modal title |
| Role label | label "Role" | Above dropdown |
| Role dropdown | native <select> (combobox) | Options sourced from enabled roles (enabled !== false). Option value: role.name.toLowerCase().replace(/\s+/g, '-') — em-dashes in names are preserved, not stripped. Default selectedRole = 'se' but renders blank if no enabled role has slug 'se' |
| Prompt label | label "Prompt" | Above textarea |
| Prompt textarea | textbox with placeholder | Placeholder: "e.g., Pick issue SCRUM-142 from backlog, implement fix..." |
| Cancel button | button "Cancel" | Closes modal |
| Start Agent button | button "Start Agent" | Default state. Submits POST /api/agents/start |
| Starting button | button "Starting..." | Shown during isStarting state — button is disabled |
Empty State
| Element | Selector | Notes |
|---|---|---|
| Empty card | .empty-card | Shown when no running or completed agents |
| Empty heading | heading "No Agents Running" | H3, centered |
| Description | "Agents are autonomous workflows..." | Subtitle text |
| Start Agent button | button "+ Start Agent" | Duplicate CTA inside the empty card |
Loading State
| Element | Selector | Notes |
|---|---|---|
| Loading container | .loading | Centered div |
| Loading text | "Loading agents..." | Visible during initial data fetch |
Data Model
Agent Job (from API response)
| Field | Type | Notes |
|---|---|---|
run_id | string | Primary identifier — used as the agent key and for navigation/stop calls |
workflow_title | string | Display title shown in the card heading |
role | string | Role identifier (e.g., "se", "qa-engineer") |
initial_prompt | string | User-provided task description (shown in .agent-prompt block) |
status | enum | waiting, running, completed, failed, stopped |
started_at | datetime | Job start time (ISO string) |
completed_at | datetime | Job end time — null while running |
duration_ms | number | Elapsed milliseconds (used for duration display) |
metrics.action_count | number | Count of actions taken (running agents only) |
metrics.token_count | number | Total tokens consumed (displayed formatted, e.g., "12.5K") |
metrics.cost_estimate | number | Estimated cost (displayed as "$X.XX") |
current_task | string | Latest terminal output (present for running agents) |
result_summary | string | Final result message (for completed agents — displayed as "Result: ...") |
Role Object (from getRoles() API)
| Field | Type | Notes |
|---|---|---|
name | string | Display name (e.g., "Software Engineer") |
enabled | boolean | Roles with enabled === false are excluded from the dropdown |
Role dropdown <option> value is derived: role.name.toLowerCase().replace(/\s+/g, '-')
(e.g., "Software Engineer" → "software-engineer", "PM — Portal Chat" → "pm-—-portal-chat")
Note: only whitespace is replaced — em-dashes (—) are preserved in the value slug.
States
| State | Trigger | Visual Indicator |
|---|---|---|
| Loading | Initial page load | .loading div with "Loading agents..." |
| Empty | No running or completed agents | .empty-card with "No Agents Running" heading + CTA button |
| Has running agents | running.length > 0 | "Running ({count})" section visible |
| Has completed agents | completed.length > 0 | "Completed Today ({count})" section visible |
| Waiting agent | Agent status is waiting | .agent-card.waiting (amber border), .status-dot.waiting (amber solid), "Queued {time}" |
| Running agent | Agent status is running | .agent-card.running (green border), .status-dot.running (green pulse), metrics visible |
| Completed agent (success) | Agent status is completed | .agent-card, .status-dot.success (solid green), "Result:" prefix in result block |
| Failed agent | Agent status is failed | .agent-card.failed (red border), .status-dot.failed (solid red), "Error:" prefix |
| Modal open | Click "+ Start Agent" | [role="dialog"] visible (.modal-overlay > .modal) with role + prompt form |
| isStarting | Click "Start Agent" in modal | Button text changes to "Starting..." and is disabled |
| Resending | Click "Resend" on completed card | Button shows "Resending..." and is disabled |
| Refreshing | Click Refresh icon | SVG icon gains .spinning class, button is disabled |
| Polling | Always on mount | Background setInterval at 5000ms — unconditional, runs regardless of running count |
Common Tasks
- Start an agent: Click "+ Start Agent" → select Role from dropdown (explicitly — default may be blank) → enter Prompt → click "Start Agent" (button becomes "Starting..." while submitting)
- Monitor running agent: View
.agent-card.running— shows live metrics in.agent-metricsand current terminal output in.agent-output. Agent may show.waitingstate first - Stop running/waiting agent: Click "Stop" → confirm native dialog "Stop this agent?" → toast "Agent stopped" → agent moves to Completed section
- View agent run log: Click "View Log" → navigates to run log detail for
agent.run_id(available on running and completed agents) - Check completed agents: Scroll to "Completed Today ({count})" section — shows result or error for each finished agent
- Read agent result: Look for result block — "Result: ..." for success (
result_summary), "Error: ..." for failure - Re-queue completed agent: Click "Resend" on any completed card → toast "Job re-queued" → agent re-appears in Running section
- Manually refresh: Click Refresh icon button → page data reloads immediately (outside the 5s poll cycle)
Tips
- Auto-polls every 5 seconds unconditionally: Previously gated on
running.length > 0but now polls always — page is never fully static - Role dropdown uses derived values: Option value is
role.name.toLowerCase().replace(/\s+/g, '-'). Em-dashes in role names are preserved (e.g.,pm-—-portal-chat). To select "Software Engineer", use value"software-engineer" - Default role may render blank:
selectedRoleinitializes to'se'in code, but if no enabled role has slug'se', the native<select>renders blank — always explicitly select a role before submitting - Metrics only visible during
runningstatus:.agent-metricsblock is conditionally rendered — absent forwaitingagents - Role badge is always UPPERCASED:
agent.role.toUpperCase()— the badge never shows lowercase - Metrics are formatted on display:
token_countrenders as "12.5K";cost_estimaterenders as "$0.04";$0shown if no cost - Section headings include live count: "Running (3)" and "Completed Today (5)" — count updates with each poll
- ESC key closes modal:
press_key('Escape')on the modal overlay closes it
Gotchas
- Agent identifier is
run_id, notid: All API calls (stop, view log) useagent.run_id. Do not useagent.id - Title field is
workflow_title: The card heading comes fromagent.workflow_title— not a generic "name" or "title" field - Metrics are nested:
agent.metrics.action_count,agent.metrics.token_count,agent.metrics.cost_estimate— not flat top-level fields - Role dropdown is native
<select>: Useselect_option()for automation — click-based interaction does not work on native selects - Modal closes on backdrop click OR ESC: Click
.modal-overlay(outside the white box) or press Escape. Clicking inside.modalstops propagation and does NOT close the modal. No X button - Stop uses
confirm():confirm("Stop this agent?")— native browser dialog. Cannot be intercepted by snapshot/click. Needs browser dialog event handling (Known Blocker) - Stop is irreversible: Killing the agent terminates the terminal process — cannot resume. Use Resend to re-queue from scratch
waitingis a real state, not a loading state: Agents can sit inwaitingfor several seconds before transitioning torunning. Test for this intermediate state — do not assume green dot immediately after startresult_summarynotresult: The data field for completed agent output isresult_summary. The fielderrordoes NOT exist separately — failures also useresult_summarywith "Error:" prefixduration_msnotduration: Duration field is in milliseconds. Formatted display usesformatDuration(started_at, duration_ms)- Completed agents are today-only: Historical agent jobs beyond today's date are not shown
- Polling stops when idle: If the last running agent finishes, the 5s interval is cleared and no further background requests are made until a new agent is started
isStartinglocks the button: During submission, the "Start Agent" button shows "Starting..." and is disabled — prevents double-submit- SPA 404 on direct navigation:
/agentsreturns 404 JSON if accessed directly via address bar — must navigate via the in-app SPA router