demo
This commit is contained in:
60
src/app/api/skills/builder/route.ts
Normal file
60
src/app/api/skills/builder/route.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { apiError } from "@/lib/api";
|
||||
import {
|
||||
getBuilderRunEvents,
|
||||
getOrStartBuilderRun,
|
||||
} from "@/lib/builder-runs";
|
||||
import { encodeSse, sseResponse } from "@/lib/sse";
|
||||
import { builderRequestSchema } from "@/lib/validation";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const maxDuration = 120;
|
||||
|
||||
const terminalStatuses = new Set(["complete", "stopped", "error"]);
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const input = builderRequestSchema.parse(await request.json());
|
||||
const run = getOrStartBuilderRun(input);
|
||||
let cursor = input.afterSeq;
|
||||
|
||||
const stream = new ReadableStream<Uint8Array>({
|
||||
async start(controller) {
|
||||
try {
|
||||
while (!request.signal.aborted) {
|
||||
const snapshot = getBuilderRunEvents(run.id, cursor);
|
||||
if (!snapshot) {
|
||||
controller.enqueue(
|
||||
encodeSse({ type: "error", message: "节点任务已过期" }),
|
||||
);
|
||||
controller.close();
|
||||
return;
|
||||
}
|
||||
|
||||
for (const event of snapshot.events) {
|
||||
controller.enqueue(encodeSse(event));
|
||||
cursor = Math.max(cursor, event.seq ?? cursor);
|
||||
}
|
||||
|
||||
if (terminalStatuses.has(snapshot.status)) {
|
||||
controller.close();
|
||||
return;
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
} catch {
|
||||
try {
|
||||
controller.close();
|
||||
} catch {
|
||||
// A disconnected editor can reconnect with the last event seq.
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return sseResponse(stream);
|
||||
} catch (error) {
|
||||
return apiError(error, "无法处理 Skill 对话");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user