- src/store/jobs.ts: per-job JSON store in data/jobs (create/get/update/list, dedup by toolCallId) - src/agent/tools/jobs.ts: research tool — client-side (no execute), turn ends at the call; input per contracts ResearchToolInput - src/agent/tools/web.ts: server-side web_search (Google CSE) + web_fetch (Readability/Turndown/linkedom, Jina fallback) — errors return as strings, never thrown into the agent loop. Deps: @mozilla/readability, linkedom, turndown (+@types/turndown dev) - src/agent/subagents/researcher.ts: isolated ToolLoopAgent (web tools only, 12-step cap), researcher prompt ported from pi - src/agent/subagents/runner.ts: spawnPendingJobs hook + runResearchJob — fire-and-forget, activity line per tool call, fulfills the part in the LATEST chat record (output-available) before flipping job status; failure still fulfills the part so the teacher learns the outcome - src/server/chat-handler.ts: onFinish spawn hook after saveMessages - app/api/jobs/route.ts: GET ?chatId= polling endpoint - components/artifacts/job-card.tsx + registry entry: polling activity card (2s) → syncFromServer on finish; research-brief card (markdown + sources) - src/agent/prompts/20-jobs.md: research doctrine for the teacher - tests/jobs.test.ts: store CRUD, spawn hook via scripted mock teacher, runner completion/failure with fake model + stubbed fetch
19 lines
704 B
TypeScript
19 lines
704 B
TypeScript
import { listJobs } from "@/src/store/jobs";
|
|
|
|
/**
|
|
* Job status polling endpoint (contracts.ts "THE ASYNC PROTOCOL" §4): the
|
|
* client polls GET /api/jobs?chatId=… while any job tool part is pending,
|
|
* finds the job by toolCallId, renders its activity line, and re-syncs the
|
|
* chat when the job flips to done/error.
|
|
*/
|
|
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) });
|
|
}
|