Status: approved for implementation
Date: 2026-07-14
Refactor the existing static Agent Lab page into a clearer professional debugging console while preserving its current FastAPI, WebSocket, session, tool, prompt, audit, and usage contracts.
The same change fixes EventPrompt state drift:
dual_agent mode, EventPrompt is visible, read-only, unique, and derived from the currently selected tools;chat_agent_tools mode, EventPrompt is hidden and excluded from outbound system_prompts;The work is limited to the existing static frontend and focused regression tests. It does not introduce a frontend framework, bundler, backend protocol revision, or new runtime capability.
Keep the current server-rendered static entrypoint and refactor index.html, styles.css, and app.js in place.
This is preferred over introducing React/Vue because the page is an experimental service console rather than a product frontend. A framework migration would add build tooling, dependency cost, and regression surface without improving the core experiment. A CSS-only reskin is also insufficient because the requested behavior needs layout state, drawer state, collapsible controls, and one authoritative EventPrompt synchronization path.
The top bar contains:
Connection and mode information remain visible without consuming the chat workspace.
The left rail groups controls into collapsible sections:
Collapse state is persisted in browser storage. Existing control IDs and request behavior are preserved where practical so the change remains presentation-focused.
Tools are rendered as compact selectable rows/cards with a selected count and clear All/None actions. Tool selection remains available in both invocation modes because the selected set controls either the EventAgent catalog or ChatAgent provider tools.
The center column is the primary workspace:
Round metrics are placed directly above the composer as a compact strip. They remain secondary to the conversation and do not move into the debug drawer.
Audit Replay and usage summaries move from an always-visible fixed column into a collapsible right drawer.
On narrow screens, the page becomes a stacked layout. Controls, chat, metrics/composer, and the opened debug drawer must remain usable without horizontal page scrolling.
Use a light professional console palette with neutral surfaces, subtle borders, restrained shadows, and a small accent color for active states. The design should feel operational rather than decorative.
Define shared CSS variables for color, spacing, radii, control height, and typography. Buttons have explicit primary, secondary, and danger treatments. Status badges communicate connection, invocation mode, and active selections. Keyboard focus remains visible and color is not the only indicator of state.
The UI keeps the existing browser-native implementation and does not add icon libraries or external assets.
EventPrompt is generated state, not a normal user-authored prompt item. One frontend refresh function owns all derived tool/mode presentation and performs these steps in a fixed order:
dual_agent, generate and insert exactly one read-only EventPrompt from the selected tools;chat_agent_tools, leave EventPrompt absent and mark EventAgent-only model controls unavailable;Every relevant mutation calls this same function:
This replaces the current scattered update calls that can update mode help without updating EventPrompt.
Persisted system_prompts are currently flat text values and do not preserve whether a value was generated EventPrompt content. Legacy restores can therefore treat an old EventPrompt as a custom prompt and append a newly generated EventPrompt, producing duplicates.
During restore, prompt entries matching the generated EventPrompt marker/shape are discarded before normal custom prompts are rebuilt. The derived-state refresh then inserts at most one current EventPrompt when required. User-authored prompts keep their order and content.
No storage schema migration is required for this UI repair. New saves continue to serialize only prompts that are valid for the current invocation mode.
collectSystemPrompts() must obey mode semantics rather than blindly serializing every visible prompt-list item:
dual_agent: include user-authored prompts and the one current generated EventPrompt;chat_agent_tools: include user-authored prompts only, even if stale DOM or legacy persisted data contains EventPrompt-like content.The request builder remains compatible with existing backend contracts. This filtering is a defensive boundary in addition to hiding/removing the generated item in the UI.
In chat_agent_tools mode, EventAgent model configuration is visually unavailable because EventAgent does not perform the invocation decision. Shared runtime controls such as concurrency and timeout remain editable because direct tool execution still uses the shared event kernel and policies.
Switching back to dual_agent restores EventAgent model configuration availability and regenerates EventPrompt from the current tool selection.
src/agent_lab/presentation/static/index.html: semantic layout, collapsible groups, top status, drawer toggle, and accessible labels.src/agent_lab/presentation/static/styles.css: design tokens, responsive shell, control groups, tool rows, message roles, metrics/composer, and drawer styling.src/agent_lab/presentation/static/app.js: drawer/collapse persistence, unified derived-state refresh, restore deduplication, mode-aware prompt collection, and configuration availability.tests/: focused static/WebSocket contract regressions using the repository's existing test style.Backend runtime, event-kernel, persistence, and WebSocket contracts are not changed unless a failing regression proves that a minimal compatibility adjustment is required. Any such adjustment becomes a separate follow-up todo rather than silently expanding Todo 53.
Focused regressions must prove:
chat_agent_tools hides EventPrompt and excludes it from system_prompts;dual_agent restores exactly one current EventPrompt;Implementation verification will include:
node --check src/agent_lab/presentation/static/app.js;uv run pytest;git diff --check;After this design is approved:
53.x rows beneath Todo 53 instead of rewriting completed todo history;