export type StoredToolValue = Readonly<{ type: string; value: string }> | null | undefined; export const parseToolValue = (stored: StoredToolValue): unknown => { if (!stored) { return null; } if (stored.type !== "json") { return stored.value; } try { return JSON.parse(stored.value); } catch { // Tool arguments may still be streaming, or come from older records. return stored.value; } }; export const formatToolValue = (stored: StoredToolValue): string => { const value = parseToolValue(stored); return typeof value === "string" ? value : JSON.stringify(value, null, 2) ?? ""; }; export interface SearchSource { title: string; url: string; hostname: string; snippet: string; } export const readSearchSources = (value: unknown): SearchSource[] | null => { if (!Array.isArray(value)) { return null; } const sources: SearchSource[] = []; const seen = new Set(); for (const item of value) { if (typeof item !== "object" || item === null || !("link" in item) || typeof item.link !== "string") { continue; } let url: URL; try { url = new URL(item.link); } catch { continue; } if (url.protocol !== "https:" && url.protocol !== "http:") { continue; } url.hash = ""; if (seen.has(url.href)) { continue; } seen.add(url.href); sources.push({ title: "title" in item && typeof item.title === "string" ? item.title : url.hostname, url: url.href, hostname: url.hostname, snippet: "snippet" in item && typeof item.snippet === "string" ? item.snippet : "", }); } return sources; }; export interface ToolDisplayInfo { icon: string; verb: string; target: string; } export const formatDuration = (start?: Date | string | number | null, end?: Date | string | number | null): string | null => { if (!start || !end) { return null; } const startTime = typeof start === "number" ? start : new Date(start).getTime(); const endTime = typeof end === "number" ? end : new Date(end).getTime(); if (Number.isNaN(startTime) || Number.isNaN(endTime) || endTime <= startTime) { return null; } const seconds = (endTime - startTime) / 1000; if (seconds < 0.05) { return null; } return `${seconds.toFixed(1)}s`; }; const extractField = (obj: unknown, fields: string[]): string => { if (typeof obj !== "object" || obj === null) { return typeof obj === "string" ? obj : ""; } for (const field of fields) { if (field in obj) { const val = (obj as Record)[field]; if (typeof val === "string" && val.length > 0) { return val; } } } return ""; }; export const DOMAIN_COLORS = [ "#eab308", // amber / yellow "#16a34a", // emerald / green "#0284c7", // sky / blue "#ea580c", // orange "#dc2626", // red "#7c3aed", // violet "#0d9488", // teal "#db2777", // pink "#4f46e5", // indigo ]; export const getDomainColor = (domain: string): string => { const clean = domain.replace(/^www\./, "").toLowerCase(); let hash = 0; for (let i = 0; i < clean.length; i++) { hash = (hash << 5) - hash + clean.charCodeAt(i); hash |= 0; } const index = Math.abs(hash) % DOMAIN_COLORS.length; return DOMAIN_COLORS[index] ?? "#eab308"; }; export const domainInitial = (domain: string): string => { const clean = domain.replace(/^www\./, "").trim(); return clean ? clean.charAt(0).toUpperCase() : "?"; }; export const getFaviconUrl = (hostname: string): string => { const clean = hostname.replace(/^www\./, "").trim(); return `https://icons.duckduckgo.com/ip3/${clean}.ico`; }; export const getToolDisplayInfo = (toolCall: { toolName: string; status: string; input?: StoredToolValue; output?: StoredToolValue; error?: StoredToolValue; }): ToolDisplayInfo => { const rawInput = parseToolValue(toolCall.input); const rawOutput = parseToolValue(toolCall.output); const rawError = parseToolValue(toolCall.error); const isPending = toolCall.status === "pending"; const isFailed = toolCall.status === "failed"; const isCancelled = toolCall.status === "cancelled"; const name = toolCall.toolName.toLowerCase(); const errorSummary = typeof rawError === "string" ? (rawError.trim().split("\n")[0] ?? "") : extractField(rawError, ["message", "error"]); if (name === "search" || name.includes("search")) { const query = extractField(rawInput, ["query", "q"]); const target = query ? `"${query}"` : ""; const icon = "i-mynaui-search"; if (isPending) { return { icon, verb: "Searching the web", target }; } if (isFailed) { return { icon: "i-mynaui-danger-triangle", verb: "Search failed", target: target || errorSummary }; } if (isCancelled) { return { icon, verb: "Search cancelled", target }; } const sources = readSearchSources(rawOutput); const count = sources?.length ?? 0; const verb = count > 0 ? `Searched ${count} ${count === 1 ? "site" : "sites"}` : "Searched the web"; return { icon, verb, target }; } if (name === "fetchurl" || name === "fetch_url" || name.includes("fetch") || name.includes("scrape")) { const url = extractField(rawInput, ["url", "link", "uri", "href"]); const icon = "i-mynaui-link"; if (isPending) { return { icon, verb: "Fetching URL", target: url }; } if (isFailed) { return { icon: "i-mynaui-danger-triangle", verb: "Fetch failed", target: url || errorSummary }; } if (isCancelled) { return { icon, verb: "Fetch cancelled", target: url }; } return { icon, verb: "Fetched URL", target: url }; } if (name === "python" || name.includes("python") || name.includes("pyeval")) { const code = extractField(rawInput, ["code", "script", "command"]); const firstLine = code.trim().split("\n")[0] ?? ""; const icon = "i-mynaui-terminal"; if (isPending) { return { icon, verb: "Running Python", target: firstLine }; } if (isFailed) { return { icon: "i-mynaui-danger-triangle", verb: "Python failed", target: firstLine || errorSummary }; } if (isCancelled) { return { icon, verb: "Python cancelled", target: firstLine }; } return { icon, verb: "Ran Python", target: firstLine }; } if (name.includes("read") || name.includes("cat") || name.includes("view")) { const path = extractField(rawInput, ["path", "file", "filePath", "filename"]); const icon = "i-mynaui-file"; if (isPending) { return { icon, verb: "Reading", target: path }; } if (isFailed) { return { icon: "i-mynaui-danger-triangle", verb: "Read failed", target: path || errorSummary }; } if (isCancelled) { return { icon, verb: "Read cancelled", target: path }; } return { icon, verb: "Read", target: path }; } if (name.includes("edit") || name.includes("write") || name.includes("modify") || name.includes("patch") || name.includes("save")) { const path = extractField(rawInput, ["path", "file", "filePath", "filename"]); const icon = "i-mynaui-edit"; if (isPending) { return { icon, verb: "Editing", target: path }; } if (isFailed) { return { icon: "i-mynaui-danger-triangle", verb: "Edit failed", target: path || errorSummary }; } if (isCancelled) { return { icon, verb: "Edit cancelled", target: path }; } return { icon, verb: "Edited", target: path }; } if (name.includes("query") || name.includes("sql") || name.includes("database") || name.includes("db")) { const query = extractField(rawInput, ["query", "sql", "statement", "command"]); const icon = "i-mynaui-database"; if (isPending) { return { icon, verb: "Querying", target: query }; } if (isFailed) { const target = query || errorSummary; return { icon: "i-mynaui-database", verb: "Query failed", target }; } if (isCancelled) { return { icon, verb: "Query cancelled", target: query }; } return { icon, verb: "Queried", target: query }; } const formattedName = toolCall.toolName .replace(/([A-Z])/g, " $1") .replace(/[-_]/g, " ") .trim(); const capitalized = formattedName.charAt(0).toUpperCase() + formattedName.slice(1); const genericTarget = extractField(rawInput, ["query", "path", "command", "prompt", "url"]) || (isFailed ? errorSummary : ""); if (isPending) { return { icon: "i-mynaui-tool", verb: `Running ${capitalized}`, target: genericTarget }; } if (isFailed) { return { icon: "i-mynaui-danger-triangle", verb: `${capitalized} failed`, target: genericTarget || errorSummary }; } if (isCancelled) { return { icon: "i-mynaui-tool", verb: `${capitalized} cancelled`, target: genericTarget }; } return { icon: "i-mynaui-tool", verb: capitalized, target: genericTarget }; };