@musnows/scriverse 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai.js +21 -4
- package/dist/ai.js.map +1 -1
- package/dist/app.js +68 -6
- package/dist/app.js.map +1 -1
- package/dist/public/ai-request-manager.js +10 -2
- package/dist/public/app.js +54 -19
- package/dist/public/index.html +2 -2
- package/dist/public/stream-typewriter.d.ts +1 -0
- package/dist/public/stream-typewriter.js +22 -3
- package/dist/public/styles.css +3 -0
- package/dist/public/text-count.d.ts +1 -0
- package/dist/public/text-count.js +7 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -3568,7 +3568,7 @@ export function createRuntime(options) {
|
|
|
3568
3568
|
app.get("/api/works/:workId/ai/questions/:questionId", (request, response) => {
|
|
3569
3569
|
data(response, aiWritePlanManager.getQuestion(request.params.questionId, request.params.workId, planViewer()));
|
|
3570
3570
|
});
|
|
3571
|
-
const resumeQuestionWorkflow = async (questionId, workId, viewer) => {
|
|
3571
|
+
const resumeQuestionWorkflow = async (questionId, workId, viewer, stream = {}) => {
|
|
3572
3572
|
const continuation = aiWritePlanManager.claimQuestionContinuation(questionId, workId, viewer);
|
|
3573
3573
|
if (!continuation)
|
|
3574
3574
|
return;
|
|
@@ -3599,26 +3599,88 @@ export function createRuntime(options) {
|
|
|
3599
3599
|
: {}),
|
|
3600
3600
|
...(typeof continuation.round === "number" ? { round: continuation.round } : {}),
|
|
3601
3601
|
...(Array.isArray(continuation.toolMessages) ? { toolMessages: continuation.toolMessages } : {})
|
|
3602
|
-
});
|
|
3602
|
+
}, stream);
|
|
3603
3603
|
aiWritePlanManager.finishQuestionContinuation(questionId, { callId: resumed.callId ?? null, completed: true });
|
|
3604
|
+
return resumed;
|
|
3604
3605
|
}
|
|
3605
3606
|
catch (error) {
|
|
3606
3607
|
aiWritePlanManager.finishQuestionContinuation(questionId, { message: error instanceof Error ? error.message : "恢复失败" }, true);
|
|
3607
3608
|
throw error;
|
|
3608
3609
|
}
|
|
3609
3610
|
};
|
|
3611
|
+
const respondWithQuestionContinuation = async (request, response, viewer) => {
|
|
3612
|
+
const { questionId, workId } = request.params;
|
|
3613
|
+
if (!request.get("Accept")?.includes("text/event-stream")) {
|
|
3614
|
+
await resumeQuestionWorkflow(questionId, workId, viewer);
|
|
3615
|
+
data(response, aiWritePlanManager.getQuestion(questionId, workId, viewer));
|
|
3616
|
+
return;
|
|
3617
|
+
}
|
|
3618
|
+
const controller = new AbortController();
|
|
3619
|
+
response.status(200);
|
|
3620
|
+
response.setHeader("Content-Type", "text/event-stream; charset=utf-8");
|
|
3621
|
+
response.setHeader("Cache-Control", "no-cache, no-transform");
|
|
3622
|
+
response.setHeader("Connection", "keep-alive");
|
|
3623
|
+
response.setHeader("X-Accel-Buffering", "no");
|
|
3624
|
+
response.flushHeaders();
|
|
3625
|
+
const sendEvent = (event, payload) => {
|
|
3626
|
+
if (!response.writableEnded && !response.destroyed)
|
|
3627
|
+
response.write(`event: ${event}\ndata: ${JSON.stringify(payload)}\n\n`);
|
|
3628
|
+
};
|
|
3629
|
+
const heartbeat = setInterval(() => {
|
|
3630
|
+
if (!response.writableEnded && !response.destroyed)
|
|
3631
|
+
response.write(": heartbeat\n\n");
|
|
3632
|
+
}, aiStreamHeartbeatIntervalMs);
|
|
3633
|
+
heartbeat.unref();
|
|
3634
|
+
response.on("close", () => {
|
|
3635
|
+
clearInterval(heartbeat);
|
|
3636
|
+
if (!response.writableEnded)
|
|
3637
|
+
controller.abort(new Error("浏览器已中断流式请求"));
|
|
3638
|
+
});
|
|
3639
|
+
try {
|
|
3640
|
+
const resumed = await resumeQuestionWorkflow(questionId, workId, viewer, {
|
|
3641
|
+
signal: controller.signal,
|
|
3642
|
+
onStart: (message) => sendEvent("continuation", message),
|
|
3643
|
+
onDelta: (delta) => sendEvent("delta", { delta }),
|
|
3644
|
+
onToolCall: (toolCall, round) => sendEvent("tool_call", { ...toolCall, round }),
|
|
3645
|
+
onProcessStep: (step) => sendEvent("process_step", step),
|
|
3646
|
+
onContextCompacted: (event) => sendEvent("context_compacted", event)
|
|
3647
|
+
});
|
|
3648
|
+
const message = resumed?.conversationMessage;
|
|
3649
|
+
const metadata = message?.metadata;
|
|
3650
|
+
sendEvent("complete", {
|
|
3651
|
+
warningOnly: !resumed,
|
|
3652
|
+
model: resumed?.model,
|
|
3653
|
+
outputTokens: metadata?.outputTokens ?? resumed?.outputTokens,
|
|
3654
|
+
cacheHitPercent: metadata?.cacheHitPercent ?? resumed?.cacheHitPercent,
|
|
3655
|
+
processDurationMs: metadata?.processDurationMs ?? resumed?.processDurationMs,
|
|
3656
|
+
toolCalls: metadata?.toolCalls ?? resumed?.toolCalls,
|
|
3657
|
+
processSteps: metadata?.processSteps ?? resumed?.processSteps,
|
|
3658
|
+
contextUsage: resumed?.contextUsage,
|
|
3659
|
+
messageId: message?.id,
|
|
3660
|
+
messageCreatedAt: message?.createdAt,
|
|
3661
|
+
question: aiWritePlanManager.getQuestion(questionId, workId, viewer)
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
catch (error) {
|
|
3665
|
+
if (!controller.signal.aborted)
|
|
3666
|
+
sendEvent("error", publicAiStreamError(error));
|
|
3667
|
+
}
|
|
3668
|
+
finally {
|
|
3669
|
+
clearInterval(heartbeat);
|
|
3670
|
+
if (!response.writableEnded && !response.destroyed)
|
|
3671
|
+
response.end();
|
|
3672
|
+
}
|
|
3673
|
+
};
|
|
3610
3674
|
app.post("/api/works/:workId/ai/questions/:questionId/answer", async (request, response) => {
|
|
3611
3675
|
const input = parse(answerAiUserQuestionSchema, request.body ?? {});
|
|
3612
3676
|
const viewer = planViewer();
|
|
3613
3677
|
aiWritePlanManager.answerQuestion(request.params.questionId, request.params.workId, viewer, input);
|
|
3614
|
-
await
|
|
3615
|
-
data(response, aiWritePlanManager.getQuestion(request.params.questionId, request.params.workId, viewer));
|
|
3678
|
+
await respondWithQuestionContinuation(request, response, viewer);
|
|
3616
3679
|
});
|
|
3617
3680
|
app.post("/api/works/:workId/ai/questions/:questionId/reject", async (request, response) => {
|
|
3618
3681
|
const viewer = planViewer();
|
|
3619
3682
|
aiWritePlanManager.rejectQuestion(request.params.questionId, request.params.workId, viewer);
|
|
3620
|
-
await
|
|
3621
|
-
data(response, aiWritePlanManager.getQuestion(request.params.questionId, request.params.workId, viewer));
|
|
3683
|
+
await respondWithQuestionContinuation(request, response, viewer);
|
|
3622
3684
|
});
|
|
3623
3685
|
app.get("/api/works/:workId/providers", (request, response) => {
|
|
3624
3686
|
store.getWork(request.params.workId);
|