Jobs stream UI garden
Date: 2026-05-11
Goal#
Make the jobs detail stream easier to understand and easier to change. The current implementation renders events, but the transcript projection and HTML rendering live together in viewer/jobs-view.js, and tool calls do not read like first-class chat activity.
Also add instant page suggestions to the viewer search box using the same extracted-module pattern. Search suggestions are a reusable interaction surface and should not be embedded directly in the main router.
Inspiration reviewed#
../openalmanac/gui/src/surfaces/conversations/MessageBubble.tsx../openalmanac/gui/src/surfaces/conversations/ToolIndicator.tsx../openalmanac/gui/src/domains/tasks/conversationMessages.ts../openalmanac/frontend/src/components/quill/ToolCallCard.tsx
Useful patterns:
- Assistant text should stay as simple chat messages.
- Tool activity should be compact by default and expandable on demand.
- Tool calls and tool results should be paired by ID before rendering.
- Agent/subagent tool calls need a distinct visual treatment from file, shell, search, and web tools.
- Raw JSON is still valuable, but it should be supporting detail rather than the first thing the user sees.
- Search suggestions should debounce input, cancel stale requests, support keyboard navigation, and render page-shaped rows.
Decisions#
- Add
viewer/jobs-transcript.jsas a pure frontend projection module. It owns event grouping, text accumulation, tool/result pairing, and display model derivation. - Keep the viewer runtime build-free. The new module is plain ESM loaded by
viewer/jobs-view.js. - Render tool activity with native
<details>/<summary>controls. That gives accessible expansion without adding state plumbing. - Keep typed server-side run parsing in
src/viewer/jobs.ts; do not duplicate process-manager storage rules in the browser. - Test the projection module directly with Vitest so future UI changes can move markup without breaking stream semantics silently.
- Add
viewer/search-suggestions.jsas a shared browser module. The shell wires it once, while the module owns debounce, abort, keyboard selection, and dropdown rendering. - Add
/api/suggestas a bounded page-search endpoint over the same FTS path as/api/search, returning only the top suggestions.
Implementation log#
- Extracted transcript projection from
viewer/jobs-view.js. - Added pairing for
tool_useandtool_resultevents that share an ID. - Added compact tool display models for read/write/edit/search/shell/web/agent/mcp/unknown events.
- Updated job detail rendering to use expandable tool cards with input/result sections.
- Added direct unit tests for transcript accumulation, invalid-line preservation, done-result handling, and tool result pairing.
- Added a small declaration file for the JS transcript module so TypeScript tests can import it without weakening compiler checks.
- Added
/api/suggest, wired instant sidebar search suggestions, and added asset/server/API coverage.
Out of scope#
- Browser screenshot/UI regression testing. The user explicitly asked to leave UI testing for now.
- A React rewrite or build pipeline for the viewer.
- Changing provider log formats.