76 lines
1.5 KiB
TypeScript
76 lines
1.5 KiB
TypeScript
export interface RenderCache {
|
|
text: string
|
|
html: string
|
|
theme?: string
|
|
}
|
|
|
|
export interface MessageDisplayParts {
|
|
text: any[]
|
|
tool: any[]
|
|
reasoning: any[]
|
|
combined: any[]
|
|
showThinking: boolean
|
|
version: number
|
|
}
|
|
|
|
export interface Message {
|
|
id: string
|
|
sessionId: string
|
|
type: "user" | "assistant"
|
|
parts: any[]
|
|
timestamp: number
|
|
status: "sending" | "sent" | "streaming" | "complete" | "error"
|
|
version: number
|
|
displayParts?: MessageDisplayParts
|
|
}
|
|
|
|
export interface TextPart {
|
|
id?: string
|
|
type: "text"
|
|
text: string
|
|
version?: number
|
|
synthetic?: boolean
|
|
renderCache?: RenderCache
|
|
}
|
|
|
|
function hasTextSegment(segment: unknown): boolean {
|
|
if (typeof segment === "string") {
|
|
return segment.trim().length > 0
|
|
}
|
|
|
|
if (segment && typeof segment === "object") {
|
|
const maybeText = (segment as { text?: unknown }).text
|
|
if (typeof maybeText === "string") {
|
|
return maybeText.trim().length > 0
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
export function partHasRenderableText(part: any): boolean {
|
|
if (!part || typeof part !== "object") {
|
|
return false
|
|
}
|
|
|
|
if (hasTextSegment(part.text)) {
|
|
return true
|
|
}
|
|
|
|
const contentArray = Array.isArray(part?.content) ? part.content : []
|
|
for (const item of contentArray) {
|
|
if (hasTextSegment(item)) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
const thinkingContent = Array.isArray(part?.thinking?.content) ? part.thinking.content : []
|
|
for (const chunk of thinkingContent) {
|
|
if (hasTextSegment(chunk)) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|