import type { AgentMessage } from "@earendil-works/pi-agent-core"; export function normalizeText(value: string, maxChars: number): string { const normalized = value.replace(/\s+/g, " ").trim(); if (normalized.length <= maxChars) return normalized; return `${normalized.slice(0, Math.max(1, maxChars - 1)).trimEnd()}…`; } export function assistantText(message: AgentMessage | undefined): string { if (!message || message.role !== "assistant" || !Array.isArray(message.content)) return ""; return message.content .filter((part): part is { type: "text"; text: string } => part.type === "text") .map((part) => part.text) .join("\n") .trim(); } export function latestAssistant(messages: AgentMessage[]): AgentMessage | undefined { for (let index = messages.length - 1; index >= 0; index -= 1) { if (messages[index]?.role === "assistant") return messages[index]; } return undefined; } export function formatDuration(milliseconds: number): string { const seconds = Math.max(0, Math.round(milliseconds / 1000)); if (seconds < 60) return `${seconds} 秒`; const minutes = Math.floor(seconds / 60); const rest = seconds % 60; if (minutes < 60) return rest ? `${minutes} 分 ${rest} 秒` : `${minutes} 分钟`; const hours = Math.floor(minutes / 60); const minuteRest = minutes % 60; return minuteRest ? `${hours} 小时 ${minuteRest} 分` : `${hours} 小时`; } export function sanitizeEventPart(value: string): string { return value.replace(/[^A-Za-z0-9._:-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "unknown"; }