mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-12 09:12:40 +02:00
chat: switch dashboard chat page to slice and drop superseded aborted rows on resume.
This commit is contained in:
parent
d96f966c8f
commit
9c5a178468
2 changed files with 92 additions and 18 deletions
|
|
@ -43,13 +43,14 @@ import {
|
|||
type EditMessageDialogChoice,
|
||||
} from "@/components/assistant-ui/edit-message-dialog";
|
||||
import { StepSeparatorDataUI } from "@/components/assistant-ui/step-separator";
|
||||
import { ThinkingStepsDataUI } from "@/components/assistant-ui/thinking-steps";
|
||||
import { Thread } from "@/components/assistant-ui/thread";
|
||||
import {
|
||||
createTokenUsageStore,
|
||||
type TokenUsageData,
|
||||
TokenUsageProvider,
|
||||
} from "@/components/assistant-ui/token-usage-context";
|
||||
import { type BundleSubmit, HitlBundleProvider } from "@/features/chat-messages/hitl";
|
||||
import { TimelineDataUI } from "@/features/chat-messages/timeline";
|
||||
import {
|
||||
applyActionLogSse,
|
||||
applyActionLogUpdatedSse,
|
||||
|
|
@ -63,7 +64,7 @@ import { documentsApiService } from "@/lib/apis/documents-api.service";
|
|||
import { getBearerToken } from "@/lib/auth-utils";
|
||||
import { type ChatFlow, classifyChatError } from "@/lib/chat/chat-error-classifier";
|
||||
import { tagPreAcceptSendFailure, toHttpResponseError } from "@/lib/chat/chat-request-errors";
|
||||
import { convertToThreadMessage } from "@/lib/chat/message-utils";
|
||||
import { convertToThreadMessage, filterSupersededAbortedMessages } from "@/lib/chat/message-utils";
|
||||
import {
|
||||
isPodcastGenerating,
|
||||
looksLikePodcastRequest,
|
||||
|
|
@ -107,7 +108,6 @@ import {
|
|||
type NewChatUserImagePayload,
|
||||
} from "@/lib/chat/user-turn-api-parts";
|
||||
import { NotFoundError } from "@/lib/error";
|
||||
import { type BundleSubmit, HitlBundleProvider } from "@/lib/hitl";
|
||||
import {
|
||||
trackChatBlocked,
|
||||
trackChatCreated,
|
||||
|
|
@ -126,7 +126,7 @@ const MobileEditorPanel = dynamic(
|
|||
);
|
||||
const MobileHitlEditPanel = dynamic(
|
||||
() =>
|
||||
import("@/components/hitl-edit-panel/hitl-edit-panel").then((m) => ({
|
||||
import("@/features/chat-messages/hitl").then((m) => ({
|
||||
default: m.MobileHitlEditPanel,
|
||||
})),
|
||||
{ ssr: false }
|
||||
|
|
@ -395,7 +395,7 @@ export default function NewChatPage() {
|
|||
const memberById = new Map(membersData?.map((m) => [m.user_id, m]) ?? []);
|
||||
const prevById = new Map(prev.map((m) => [m.id, m]));
|
||||
|
||||
return syncedMessages.map((msg) => {
|
||||
return filterSupersededAbortedMessages(syncedMessages).map((msg) => {
|
||||
const member = msg.author_id ? (memberById.get(msg.author_id) ?? null) : null;
|
||||
|
||||
// Preserve existing author info if member lookup fails (e.g., cloned chats)
|
||||
|
|
@ -622,7 +622,9 @@ export default function NewChatPage() {
|
|||
setCurrentThread(threadData);
|
||||
|
||||
if (messagesResponse.messages && messagesResponse.messages.length > 0) {
|
||||
const loadedMessages = messagesResponse.messages.map(convertToThreadMessage);
|
||||
const loadedMessages = filterSupersededAbortedMessages(messagesResponse.messages).map(
|
||||
convertToThreadMessage
|
||||
);
|
||||
setMessages(loadedMessages);
|
||||
|
||||
for (const msg of messagesResponse.messages) {
|
||||
|
|
@ -1388,6 +1390,8 @@ export default function NewChatPage() {
|
|||
|
||||
const existingMsg = messages.find((m) => m.id === assistantMsgId);
|
||||
if (existingMsg && Array.isArray(existingMsg.content)) {
|
||||
// See ``ContentPartsState.suppressStepSeparators`` doc.
|
||||
contentPartsState.suppressStepSeparators = true;
|
||||
for (const part of existingMsg.content) {
|
||||
if (typeof part === "object" && part !== null) {
|
||||
const p = part as Record<string, unknown>;
|
||||
|
|
@ -1402,15 +1406,19 @@ export default function NewChatPage() {
|
|||
toolName: String(p.toolName),
|
||||
args: (p.args as Record<string, unknown>) ?? {},
|
||||
result: p.result as unknown,
|
||||
// Restore argsText so persisted pretty-printed
|
||||
// JSON survives reloads (assistant-ui prefers
|
||||
// supplied argsText over JSON.stringify(args)).
|
||||
// langchainToolCallId restoration also fixes a
|
||||
// pre-existing dropped-id bug on resume.
|
||||
// argsText: assistant-ui prefers it over
|
||||
// JSON.stringify(args), so restoring it keeps
|
||||
// pretty-printed JSON across reloads.
|
||||
...(typeof p.argsText === "string" ? { argsText: p.argsText } : {}),
|
||||
...(typeof p.langchainToolCallId === "string"
|
||||
? { langchainToolCallId: p.langchainToolCallId }
|
||||
: {}),
|
||||
// metadata: spanId / thinkingStepId drive the
|
||||
// timeline's step↔tool join. Dropping these
|
||||
// here orphans every rehydrated tool-call.
|
||||
...(p.metadata && typeof p.metadata === "object"
|
||||
? { metadata: p.metadata as Record<string, unknown> }
|
||||
: {}),
|
||||
});
|
||||
contentPartsState.currentTextPartIndex = -1;
|
||||
} else if (p.type === "data-thinking-steps") {
|
||||
|
|
@ -2353,7 +2361,7 @@ export default function NewChatPage() {
|
|||
return (
|
||||
<TokenUsageProvider store={tokenUsageStore}>
|
||||
<AssistantRuntimeProvider runtime={runtime}>
|
||||
<ThinkingStepsDataUI />
|
||||
<TimelineDataUI />
|
||||
<StepSeparatorDataUI />
|
||||
<HitlBundleProvider
|
||||
toolCallIds={pendingInterrupt?.bundleToolCallIds ?? null}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue