From 15f139429ec8da4f26c3db68ea26f4d47d81cba0 Mon Sep 17 00:00:00 2001 From: chahinebrini Date: Mon, 29 Jun 2026 00:55:55 +0200 Subject: [PATCH] Polish AgentHub board UI --- src/server/board.ts | 630 +++++++++++++++++++++++++++++++++---------- src/server/routes.ts | 2 +- 2 files changed, 488 insertions(+), 144 deletions(-) diff --git a/src/server/board.ts b/src/server/board.ts index 90edd99..652aea1 100644 --- a/src/server/board.ts +++ b/src/server/board.ts @@ -1,13 +1,11 @@ /** - * Self-contained Trello-like task board, served at `GET /board`. + * Self-contained AgentHub task board, served at `GET /board`. * - * Design constraints (MVP — maximum simplicity): - * - One static HTML page: inline CSS + JS, no build step, no framework, no npm deps. - * - Reads only the existing same-origin endpoints (`/tasks`, `/handoffs`, - * `/decisions`, `/tasks/:id/activity`). It never mutates state. - * - Auto-refreshes on a small interval via `setInterval` + `fetch`. - * - Each task card is clickable: expanding it fetches and renders the - * per-task activity timeline (created → handoff → result → status). + * Constraints: + * - One static HTML page: inline CSS + JS, no framework and no runtime deps. + * - Reads only same-origin endpoints (`/tasks`, `/handoffs`, `/decisions`, + * `/tasks/:id/activity`, `/events` and `/status`). + * - Never mutates state. */ export interface BoardColumn { @@ -36,7 +34,17 @@ function columnSkeleton(): string { ).join('\n'); } -export function renderBoardHtml(): string { +function escapeHtml(value: string): string { + return value + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); +} + +export function renderBoardHtml(projectName = 'AgentHub Project'): string { + const initialProjectName = JSON.stringify(projectName).replace(/ @@ -46,37 +54,132 @@ export function renderBoardHtml(): string { AgentHub Board -
- -

AgentHub Board

- - loading… -
+
+
+ +
+ AgentHub + ${projectNameHtml} +
+
+ + + + + connecting + +
${columnSkeleton()} @@ -212,36 +450,100 @@ ${columnSkeleton()} diff --git a/src/server/routes.ts b/src/server/routes.ts index 91506f4..7bbd40a 100644 --- a/src/server/routes.ts +++ b/src/server/routes.ts @@ -25,7 +25,7 @@ export async function registerRoutes(app: FastifyInstance, cwd: string): Promise // Static, self-contained Trello-like board. Polls /tasks, /handoffs and // /decisions on the same origin; no build step, no deps. Cached once — the // markup is constant, only the data it fetches changes. - const boardHtml = renderBoardHtml(); + const boardHtml = renderBoardHtml(loadConfig(cwd).projectName); app.get('/board', async (_request, reply) => reply.type('text/html; charset=utf-8').send(boardHtml)); // Team hierarchy page: roles tree with per-agent free/busy state.