Compare commits
3 Commits
df95190d70
...
19b888f69a
| Author | SHA1 | Date |
|---|---|---|
|
|
19b888f69a | |
|
|
0a619f6603 | |
|
|
883dd58275 |
|
|
@ -135,10 +135,16 @@ export default function ChatPage() {
|
|||
setHistoryCutoff(null);
|
||||
return;
|
||||
}
|
||||
if (historyCutoff === null && !thread.isThreadLoading) {
|
||||
setHistoryCutoff(thread.messages.length);
|
||||
}
|
||||
if (hasSubmitted) return;
|
||||
// Welcome 态下、未提交前,把当前已有消息都当作“历史”切掉。
|
||||
// 这样即使历史消息是后续异步补齐,也不会重新露出。
|
||||
setHistoryCutoff((prev) => {
|
||||
const next = thread.messages.length;
|
||||
if (prev === null) return next;
|
||||
return next > prev ? next : prev;
|
||||
});
|
||||
}, [
|
||||
hasSubmitted,
|
||||
historyCutoff,
|
||||
shouldRenderHistory,
|
||||
thread.isThreadLoading,
|
||||
|
|
@ -200,9 +206,9 @@ export default function ChatPage() {
|
|||
return;
|
||||
}
|
||||
setHasSubmitted(true);
|
||||
void sendMessage(threadId, message);
|
||||
void sendMessage(safeThreadId, message);
|
||||
},
|
||||
[isSelectedSkillBootstrapping, sendMessage, threadId],
|
||||
[isSelectedSkillBootstrapping, safeThreadId, sendMessage],
|
||||
);
|
||||
const handleStop = useCallback(async () => {
|
||||
await thread.stop();
|
||||
|
|
@ -331,9 +337,11 @@ export default function ChatPage() {
|
|||
threadId={threadId}
|
||||
thread={thread}
|
||||
messagesOverride={
|
||||
shouldRenderHistory || historyCutoff === null
|
||||
shouldRenderHistory
|
||||
? undefined
|
||||
: thread.messages.slice(historyCutoff)
|
||||
: historyCutoff === null
|
||||
? []
|
||||
: thread.messages.slice(historyCutoff)
|
||||
}
|
||||
paddingBottom={todoListCollapsed ? 160 : 280}
|
||||
showScrollToBottomButton={!showWelcomeStyle}
|
||||
|
|
|
|||
|
|
@ -691,13 +691,13 @@ function IframeSkillDialogButton({
|
|||
<Tag key={`${skill.skill_id}-${skill.title}-${index}`} className="shrink-0">
|
||||
{skill.title}
|
||||
{/* TODO: 因为后端接口不支持取消选择skill,所以暂时禁用取消选择按钮 */}
|
||||
{/* <button
|
||||
<button
|
||||
onClick={() => clearSkill(skill.skill_id)}
|
||||
className="hover:bg-muted-foreground/20 ml-1 rounded-full"
|
||||
type="button"
|
||||
>
|
||||
<XIcon className="size-3" />
|
||||
</button> */}
|
||||
</button>
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -69,6 +69,15 @@ function getStreamErrorMessage(error: unknown): string {
|
|||
return "Request failed.";
|
||||
}
|
||||
|
||||
function normalizeThreadId(
|
||||
value: string | null | undefined,
|
||||
): string | undefined {
|
||||
if (!value) return undefined;
|
||||
const normalized = value.trim();
|
||||
if (!normalized || normalized === "new") return undefined;
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function useThreadStreamLegacy({
|
||||
threadId,
|
||||
isNewThread,
|
||||
|
|
@ -155,12 +164,14 @@ export function useThreadStream({
|
|||
}, [onStart, onFinish, onToolEnd]);
|
||||
|
||||
useEffect(() => {
|
||||
const normalizedThreadId = threadId ?? null;
|
||||
const normalizedThreadId = normalizeThreadId(threadId) ?? null;
|
||||
if (!normalizedThreadId) {
|
||||
// Just reset for new thread creation when threadId becomes null/undefined
|
||||
startedRef.current = false;
|
||||
setOnStreamThreadId(normalizedThreadId);
|
||||
}
|
||||
setOnStreamThreadId((prev) =>
|
||||
prev === normalizedThreadId ? prev : normalizedThreadId,
|
||||
);
|
||||
threadIdRef.current = normalizedThreadId;
|
||||
}, [threadId]);
|
||||
|
||||
|
|
@ -288,7 +299,9 @@ export function useThreadStream({
|
|||
|
||||
const text = message.text.trim();
|
||||
const resolvedThreadId =
|
||||
threadId ?? threadIdRef.current ?? undefined;
|
||||
normalizeThreadId(threadId) ??
|
||||
normalizeThreadId(threadIdRef.current) ??
|
||||
undefined;
|
||||
if (resolvedThreadId === "new") {
|
||||
toast.error("Invalid thread id 'new'. Please refresh and retry.");
|
||||
sendInFlightRef.current = false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue