The dock is visible in every view, so it needs every running process — sub-agent jobs across ALL chats (not just the open one) plus the global extraction runs — in one poll. /api/jobs stays chat-scoped and untouched: it is the transcript machinery's poll and carries turnInFlight for the re-attach seam (chat-transport), the seam we spent three live rounds stabilizing; making it polymorphic would fork its response shape by mode and put regression risk on exactly the wrong path. The dock is a different consumer with a different shape (cross-chat, running-only, cost-bearing), served by a thin route over server/observability.ts: - activityFeed(): running jobs from every chat (title-joined, oldest-first on last activity) + extraction runs + busyChats (chats with a teacher turn in flight — the biggest spender; data made available, rendering is a dock decision). - GET /api/activity — the dock's single poll everywhere. - Cost math stays client-side (core/prices.ts folds); raw usage rides the records and the transport stays thin. Decided with the user over the polymorphic-/api/jobs and separate-all-jobs-endpoint alternatives.
15 lines
478 B
TypeScript
15 lines
478 B
TypeScript
/**
|
|
* GET /api/activity — the dock's one poll: every running background
|
|
* process, every view (chat, home, everywhere). Composition only — the
|
|
* feed lives in server/observability.ts; cost folds client-side via
|
|
* core/prices.ts. See that module's header for why /api/jobs stays
|
|
* chat-scoped and untouched.
|
|
*/
|
|
import { activityFeed } from "@/src/server";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export async function GET() {
|
|
return Response.json(activityFeed());
|
|
}
|