From e04030184a32e7ba9cdbb6f9d1c39a9df7e4f0d4 Mon Sep 17 00:00:00 2001 From: Prateek Date: Sun, 15 Feb 2026 02:18:50 +0530 Subject: [PATCH] fix: address 3 new Bugbot review comments 1. Medium Severity: Wrap getOrSpawnTtyd in try/catch - Port exhaustion exception now caught and returns 503 error - Prevents unhandled promise rejection that hangs client 2. Low Severity: Change "review" level label to "Needs Investigation" - "Pending Review" was misleading - this level means CI failed, changes requested, or merge conflicts (active problems) - "Needs Investigation" better conveys urgency and action needed 3. Low Severity: Add issue label enrichment to API sessions route - Import getTracker and enrichSessionIssue - Enrich issue labels synchronously before PR enrichment - Matches behavior of SSR page and individual session route Co-Authored-By: Claude Sonnet 4.5 --- packages/web/src/app/api/sessions/route.ts | 23 +++++++++++++++++-- packages/web/src/components/SessionDetail.tsx | 2 +- packages/web/src/server/terminal-websocket.ts | 10 ++++---- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/web/src/app/api/sessions/route.ts b/packages/web/src/app/api/sessions/route.ts index ac6f334df..e4a524425 100644 --- a/packages/web/src/app/api/sessions/route.ts +++ b/packages/web/src/app/api/sessions/route.ts @@ -1,6 +1,6 @@ import { NextResponse } from "next/server"; -import { getServices, getSCM } from "@/lib/services"; -import { sessionToDashboard, enrichSessionPR, computeStats } from "@/lib/serialize"; +import { getServices, getSCM, getTracker } from "@/lib/services"; +import { sessionToDashboard, enrichSessionPR, enrichSessionIssue, computeStats } from "@/lib/serialize"; /** GET /api/sessions — List all sessions with full state */ export async function GET() { @@ -12,6 +12,25 @@ export async function GET() { const workerSessions = coreSessions.filter((s) => s.id !== "orchestrator"); const dashboardSessions = workerSessions.map(sessionToDashboard); + // Enrich issue labels using tracker plugin (synchronous) + workerSessions.forEach((core, i) => { + if (!dashboardSessions[i].issueUrl) return; + let project = config.projects[core.projectId]; + if (!project) { + const entry = Object.entries(config.projects).find(([, p]) => + core.id.startsWith(p.sessionPrefix), + ); + if (entry) project = entry[1]; + } + if (!project) { + const firstKey = Object.keys(config.projects)[0]; + if (firstKey) project = config.projects[firstKey]; + } + const tracker = getTracker(registry, project); + if (!tracker || !project) return; + enrichSessionIssue(dashboardSessions[i], tracker, project); + }); + // Enrich sessions that have PRs with live SCM data (CI, reviews, mergeability) const enrichPromises = workerSessions.map((core, i) => { if (!core.pr) return Promise.resolve(); diff --git a/packages/web/src/components/SessionDetail.tsx b/packages/web/src/components/SessionDetail.tsx index 3712c810e..33f03b543 100644 --- a/packages/web/src/components/SessionDetail.tsx +++ b/packages/web/src/components/SessionDetail.tsx @@ -57,7 +57,7 @@ function humanizeLevel(level: string): string { case "respond": return "Needs Response"; case "review": - return "Pending Review"; + return "Needs Investigation"; case "pending": return "Pending"; case "working": diff --git a/packages/web/src/server/terminal-websocket.ts b/packages/web/src/server/terminal-websocket.ts index 6e74ef6d0..9655fef8c 100644 --- a/packages/web/src/server/terminal-websocket.ts +++ b/packages/web/src/server/terminal-websocket.ts @@ -240,10 +240,9 @@ const server = createServer(async (req, res) => { return; } - const instance = getOrSpawnTtyd(sessionId); - - // Wait for ttyd to be ready before returning the URL + // Spawn ttyd and wait for it to be ready (catch port exhaustion and startup failures) try { + const instance = getOrSpawnTtyd(sessionId); await waitForTtyd(instance.port, sessionId); // Use the request host to construct the terminal URL (supports remote access) @@ -257,9 +256,10 @@ const server = createServer(async (req, res) => { sessionId, })); } catch (err) { - console.error(`[Terminal] ttyd ${sessionId} failed to become ready:`, err); + const errorMsg = err instanceof Error ? err.message : String(err); + console.error(`[Terminal] Failed to start terminal for ${sessionId}:`, errorMsg); res.writeHead(503, { "Content-Type": "application/json" }); - res.end(JSON.stringify({ error: "Terminal server not ready" })); + res.end(JSON.stringify({ error: errorMsg })); } return; }