Keep chat stream alive during long runs
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
} from "@/lib/claw-auth";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
export const maxDuration = 300;
|
||||
|
||||
type ClawChatResponse = {
|
||||
final_output?: string;
|
||||
@@ -92,55 +93,68 @@ export async function POST(req: Request) {
|
||||
const stream = createUIMessageStream({
|
||||
execute: async ({ writer }) => {
|
||||
const streamState = { textStarted: false, textStreamed: false };
|
||||
let heartbeatCount = 0;
|
||||
const heartbeat = setInterval(() => {
|
||||
heartbeatCount += 1;
|
||||
writer.write({
|
||||
type: "reasoning-delta",
|
||||
id: "reasoning-1",
|
||||
delta: `\n仍在处理请求,已等待 ${formatDuration(heartbeatCount * 15000)}。`,
|
||||
});
|
||||
}, 15000);
|
||||
writer.write({ type: "start" });
|
||||
writer.write({ type: "start-step" });
|
||||
|
||||
const startedAt = Date.now();
|
||||
writer.write({ type: "reasoning-start", id: "reasoning-1" });
|
||||
writer.write({
|
||||
type: "reasoning-delta",
|
||||
id: "reasoning-1",
|
||||
delta: "思考中,正在判断是否需要调用工具。",
|
||||
});
|
||||
const payload = await callClawBackendStream(
|
||||
userPrompt,
|
||||
runtimeContext,
|
||||
account.id,
|
||||
sessionId,
|
||||
resumeId,
|
||||
writer,
|
||||
streamState,
|
||||
);
|
||||
const elapsedMs = payload.elapsed_ms ?? Date.now() - startedAt;
|
||||
const text = formatClawResponse(payload);
|
||||
try {
|
||||
const startedAt = Date.now();
|
||||
writer.write({ type: "reasoning-start", id: "reasoning-1" });
|
||||
writer.write({
|
||||
type: "reasoning-delta",
|
||||
id: "reasoning-1",
|
||||
delta: "思考中,正在判断是否需要调用工具。",
|
||||
});
|
||||
const payload = await callClawBackendStream(
|
||||
userPrompt,
|
||||
runtimeContext,
|
||||
account.id,
|
||||
sessionId,
|
||||
resumeId,
|
||||
writer,
|
||||
streamState,
|
||||
);
|
||||
const elapsedMs = payload.elapsed_ms ?? Date.now() - startedAt;
|
||||
const text = formatClawResponse(payload);
|
||||
|
||||
writer.write({
|
||||
type: "reasoning-delta",
|
||||
id: "reasoning-1",
|
||||
delta: `\n思考并执行完成,用时 ${formatDuration(elapsedMs)}。`,
|
||||
});
|
||||
writer.write({ type: "reasoning-end", id: "reasoning-1" });
|
||||
writeToolTrace(writer, payload.transcript);
|
||||
if (!streamState.textStreamed) {
|
||||
writer.write({ type: "text-start", id: "text-1" });
|
||||
writer.write({ type: "text-delta", id: "text-1", delta: text });
|
||||
writer.write({ type: "text-end", id: "text-1" });
|
||||
} else if (streamState.textStarted) {
|
||||
writer.write({ type: "text-end", id: "text-1" });
|
||||
streamState.textStarted = false;
|
||||
writer.write({
|
||||
type: "reasoning-delta",
|
||||
id: "reasoning-1",
|
||||
delta: `\n思考并执行完成,用时 ${formatDuration(elapsedMs)}。`,
|
||||
});
|
||||
writer.write({ type: "reasoning-end", id: "reasoning-1" });
|
||||
writeToolTrace(writer, payload.transcript);
|
||||
if (!streamState.textStreamed) {
|
||||
writer.write({ type: "text-start", id: "text-1" });
|
||||
writer.write({ type: "text-delta", id: "text-1", delta: text });
|
||||
writer.write({ type: "text-end", id: "text-1" });
|
||||
} else if (streamState.textStarted) {
|
||||
writer.write({ type: "text-end", id: "text-1" });
|
||||
streamState.textStarted = false;
|
||||
}
|
||||
writer.write({ type: "finish-step" });
|
||||
writer.write({
|
||||
type: "finish",
|
||||
finishReason: payload.error ? "error" : "stop",
|
||||
messageMetadata: {
|
||||
sessionId: payload.session_id,
|
||||
toolCalls: payload.tool_calls,
|
||||
stopReason: payload.stop_reason,
|
||||
elapsedMs,
|
||||
usage: payload.usage,
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
clearInterval(heartbeat);
|
||||
}
|
||||
writer.write({ type: "finish-step" });
|
||||
writer.write({
|
||||
type: "finish",
|
||||
finishReason: payload.error ? "error" : "stop",
|
||||
messageMetadata: {
|
||||
sessionId: payload.session_id,
|
||||
toolCalls: payload.tool_calls,
|
||||
stopReason: payload.stop_reason,
|
||||
elapsedMs,
|
||||
usage: payload.usage,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user