Files
pi-agent-integrated/pi-web/lib/message-display.ts

48 lines
1.7 KiB
TypeScript

import type { AssistantContentBlock, AssistantMessage, ThinkingContent, ToolCallContent } from "./types";
interface DisplayOptions {
isStreaming?: boolean;
}
export function isEmptyThinkingBlock(block: AssistantContentBlock, options: DisplayOptions = {}): block is ThinkingContent {
return block.type === "thinking" && !block.deferred && !options.isStreaming && block.thinking.trim() === "";
}
export function getDisplayableAssistantBlocks(
message: AssistantMessage,
options: DisplayOptions = {},
): AssistantContentBlock[] {
return (message.content ?? []).filter((block) => !isEmptyThinkingBlock(block, options));
}
export function getAssistantErrorMessage(
message: AssistantMessage,
options: DisplayOptions = {},
): string | null {
if (options.isStreaming || message.stopReason !== "error") return null;
return message.errorMessage?.trim() || "Unknown provider error";
}
function isFinalAnswerBlock(block: AssistantContentBlock): boolean {
return block.type === "text" || block.type === "image";
}
export function splitFinalAssistantBlocks(
message: AssistantMessage,
options: DisplayOptions = {},
): { answerBlocks: AssistantContentBlock[]; processBlocks: AssistantContentBlock[] } {
const blocks = getDisplayableAssistantBlocks(message, options);
const lastProcessIndex = blocks.findLastIndex((block) => !isFinalAnswerBlock(block));
if (lastProcessIndex === -1) {
return { answerBlocks: blocks, processBlocks: [] };
}
return {
answerBlocks: blocks.slice(lastProcessIndex + 1),
processBlocks: blocks.slice(0, lastProcessIndex + 1),
};
}
export function countToolCallBlocks(blocks: AssistantContentBlock[]): number {
return blocks.filter((block): block is ToolCallContent => block.type === "toolCall").length;
}