Files
learnharness/app/api/jobs/route.ts
T
amosblomqvist 487f5d4cea wave 1 (platform stream): background-observability accuracy + owner-driven follow-ups
- observability: liveness-gated stale-job recovery, extraction run registry on globalThis with
  explicit 'embedding' phase, /api/jobs force-dynamic, client refresh nudges at every seam
- headless: providerSafePng canonicalizer (multi-IDAT Chrome PNGs → single-IDAT) fixing qwen 400s
- composer: Enter routes through pure enterAction — accepts a pending plan verdict (owner decision)
- markdown chrome: session-scoped mermaid overlay + md-blocks component set + pan-zoom math,
  corner-copy (clipboard grant in electron main), math/table/code block fixes, heading weight 900

543/543 tests; typecheck/lint/build clean
2026-09-19 13:16:34 +03:00

23 lines
946 B
TypeScript

import { isTurnRunning, listJobs } from "@/src/server";
export const dynamic = "force-dynamic";
/**
* Job status polling endpoint (contracts.ts "THE ASYNC PROTOCOL" §4): the
* client's ONE central poller fetches this while any job runs (and slowly
* otherwise) to drive the dispatch cards, the sub-agents panel, and the
* re-sync when a job settles. `turnInFlight` rides along so the client can
* adopt a server-side wake turn (busy state + composer gate) — the same
* machinery as returning to a session mid-turn.
*/
export async function GET(req: Request) {
const chatId = new URL(req.url).searchParams.get("chatId");
if (!chatId) {
return Response.json({ error: "chatId query parameter is required" }, { status: 400 });
}
if (!/^[A-Za-z0-9_-]+$/.test(chatId)) {
return Response.json({ error: "Invalid chatId" }, { status: 400 });
}
return Response.json({ jobs: listJobs(chatId), turnInFlight: isTurnRunning(chatId) });
}