feat: enhance replay and fast-forward replay

This commit is contained in:
Li Xin
2025-04-24 22:15:17 +08:00
parent cb4b7b7495
commit cb9201bd34
5 changed files with 68 additions and 28 deletions

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT
import type { MCPServerMetadata } from "../mcp";
import { extractReplayIdFromURL } from "../replay/get-replay-id";
import { extractReplayIdFromSearchParams } from "../replay/get-replay-id";
import { fetchStream } from "../sse";
import { sleep } from "../utils";
@@ -66,7 +66,7 @@ async function* chatReplayStream(
? "/mock/before-interrupt.txt"
: "/mock/after-interrupt.txt";
} else {
const replayId = extractReplayIdFromURL();
const replayId = extractReplayIdFromSearchParams(window.location.search);
if (replayId) {
replayFilePath = `/replay/${replayId}.txt`;
} else {
@@ -90,17 +90,17 @@ async function* chatReplayStream(
} as ChatEvent;
if (chatEvent.type === "message_chunk") {
if (!chatEvent.data.finish_reason) {
await sleep(250 + Math.random() * 250);
await sleepInReplay(250 + Math.random() * 250);
}
} else if (chatEvent.type === "tool_call_result") {
await sleep(1500);
await sleepInReplay(1500);
}
yield chatEvent;
if (chatEvent.type === "tool_call_result") {
await sleep(800);
await sleepInReplay(800);
} else if (chatEvent.type === "message_chunk") {
if (chatEvent.data.role === "user") {
await sleep(1000);
await sleepInReplay(1000);
}
}
} catch (e) {
@@ -108,3 +108,16 @@ async function* chatReplayStream(
}
}
}
export async function sleepInReplay(ms: number) {
if (fastForwardReplaying) {
await sleep(0);
} else {
await sleep(ms);
}
}
let fastForwardReplaying = false;
export function fastForwardReplay(value: boolean) {
fastForwardReplaying = value;
}

View File

@@ -1,11 +1,8 @@
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
// SPDX-License-Identifier: MIT
export function extractReplayIdFromURL() {
if (typeof window === "undefined") {
return null;
}
const urlParams = new URLSearchParams(window.location.search);
export function extractReplayIdFromSearchParams(params: string) {
const urlParams = new URLSearchParams(params);
if (urlParams.has("replay")) {
return urlParams.get("replay");
}

View File

@@ -1,13 +1,16 @@
// Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
// SPDX-License-Identifier: MIT
import { useSearchParams } from "next/navigation";
import { useMemo } from "react";
import { extractReplayIdFromURL } from "./get-replay-id";
import { extractReplayIdFromSearchParams } from "./get-replay-id";
export function useReplay() {
const replayId = useMemo(() => {
return extractReplayIdFromURL();
}, []);
const searchParams = useSearchParams();
const replayId = useMemo(
() => extractReplayIdFromSearchParams(searchParams.toString()),
[searchParams],
);
return { isReplay: replayId != null, replayId };
}