You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.4 KiB
89 lines
2.4 KiB
import { defineEventHandler, getQuery } from "h3";
|
|
import { R } from "#server/utils/response";
|
|
import { getCurrentUser } from "#server/utils/context";
|
|
import { getTempTokenFromCookie } from "#server/service/agent/temp-token";
|
|
import { getSessionByIdAndUser } from "#server/service/agent/session";
|
|
import { getStreamBuffer, subscribeToBuffer } from "#server/service/agent/stream-buffer";
|
|
import log4js from "logger";
|
|
|
|
const logger = log4js.getLogger("APP");
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const user = await getCurrentUser(event);
|
|
const tempToken = getTempTokenFromCookie(event);
|
|
|
|
if (!user && !tempToken) {
|
|
throw createError({ statusCode: 401, statusMessage: "请先登录或创建临时会话" });
|
|
}
|
|
|
|
const query = getQuery(event);
|
|
const sessionId = query.sessionId as string | undefined;
|
|
|
|
if (!sessionId) {
|
|
throw createError({ statusCode: 400, statusMessage: "缺少 sessionId 参数" });
|
|
}
|
|
|
|
const session = await getSessionByIdAndUser(sessionId, user?.id ?? null, tempToken);
|
|
if (!session) {
|
|
throw createError({ statusCode: 404, statusMessage: "会话不存在" });
|
|
}
|
|
|
|
const buf = getStreamBuffer(sessionId);
|
|
|
|
if (!buf) {
|
|
return R.success({ active: false, reason: "no-buffer" });
|
|
}
|
|
|
|
if (buf.done) {
|
|
return R.success({ active: false, reason: "already-done", modelId: buf.modelId });
|
|
}
|
|
|
|
const stream = new ReadableStream<Uint8Array>({
|
|
start(controller) {
|
|
for (const chunk of buf.chunks) {
|
|
controller.enqueue(chunk);
|
|
}
|
|
|
|
if (buf.done) {
|
|
controller.close();
|
|
return;
|
|
}
|
|
|
|
const unsubscribe = subscribeToBuffer(
|
|
sessionId,
|
|
(chunk) => {
|
|
try {
|
|
controller.enqueue(chunk);
|
|
} catch (e) {
|
|
logger.error("[STREAM-RESUME] enqueue error: %s", e instanceof Error ? e.message : String(e));
|
|
}
|
|
},
|
|
() => {
|
|
try {
|
|
controller.close();
|
|
} catch {
|
|
}
|
|
},
|
|
);
|
|
|
|
event.node.req.on("close", () => {
|
|
unsubscribe();
|
|
try {
|
|
controller.close();
|
|
} catch {
|
|
}
|
|
});
|
|
},
|
|
});
|
|
|
|
return new Response(stream, {
|
|
headers: {
|
|
"Content-Type": "text/event-stream; charset=utf-8",
|
|
"Cache-Control": "no-cache",
|
|
"Connection": "keep-alive",
|
|
"X-Stream-Resume": "true",
|
|
"X-Stream-Model-Id": String(buf.modelId ?? ""),
|
|
"X-Stream-User-Message-Id": buf.userMessageId ?? "",
|
|
},
|
|
});
|
|
});
|
|
|