返回 DeepSeek-Reasonix
assistantItems.ts
根目录 / desktop / frontend / src / lib / assistantItems.ts
1 import type { Item, LiveStream, State } from "./useController";
2
3 type AssistantItem = Extract<Item, { kind: "assistant" }>;
4
5 export function assistantHasContent(item: AssistantItem | undefined, live?: LiveStream): boolean {
6 return Boolean(
7 `${live?.text ?? ""}${live?.reasoning ?? ""}${item?.text ?? ""}${item?.reasoning ?? ""}`.trim()
8 || item?.memoryCitations?.length
9 || item?.searchSources?.length
10 );
11 }
12
13 export function removeEmptyAssistantItems(items: Item[]): Item[] {
14 return items.filter((item) => item.kind !== "assistant" || assistantHasContent(item));
15 }
16
17 /** Allocate one provider sampling segment without changing the backend turn identity. */
18 export function ensureAssistant(s: State, messageId?: string): State {
19 const canonicalId = messageId ? `m:${messageId}` : undefined;
20 if ((!canonicalId || canonicalId === s.currentAssistant) && s.currentAssistant && s.items.some((item) => item.kind === "assistant" && item.id === s.currentAssistant)) return s;
21 if (canonicalId && s.items.some((item) => item.kind === "assistant" && item.id === canonicalId)) {
22 return { ...s, currentAssistant: canonicalId };
23 }
24 const ordinal = s.assistantSegmentOrdinal;
25 const id = canonicalId ?? (s.activeTurnId ? `a:${s.activeTurnId}:${ordinal}` : `a${s.seq}`);
26 const item: AssistantItem = { kind: "assistant", id, text: "", reasoning: "", streaming: true, wasStreamed: true, searchSources: s.pendingSearchSources?.length ? s.pendingSearchSources : undefined };
27 return {
28 ...s,
29 items: [...s.items, item],
30 currentAssistant: id,
31 pendingSearchSources: undefined,
32 seq: s.seq + 1,
33 assistantSegmentOrdinal: ordinal + 1,
34 };
35 }
36
37 export function ensureActiveAssistant(s: State): State {
38 const active = ensureAssistant(s);
39 const id = active.currentAssistant!;
40 const item = active.items.find((item): item is AssistantItem => item.kind === "assistant" && item.id === id);
41 return active.live?.id === id ? active : { ...active, live: { id, text: item?.text ?? "", reasoning: item?.reasoning ?? "", reasoningComplete: item?.reasoningComplete ?? false } };
42 }
43
43 lines TYPESCRIPT