import { getMessageById } from "../../persistence/conversation-crud.js"; import { listConversations, searchConversations, } from "../../persistence/conversation-queries.js"; import { extractTextFromStoredMessageContent } from "../../persistence/message-content.js"; import { renderHistoryContent } from "./shared.js"; // --------------------------------------------------------------------------- // Shared business logic (transport-agnostic) // --------------------------------------------------------------------------- export interface ConversationSearchParams { query: string; limit?: number; maxMessagesPerConversation?: number; } /** Search conversations and return results (no transport dependency). */ export async function performConversationSearch( params: ConversationSearchParams, ) { // Treat "*" as a list-all wildcard — FTS treats it as a literal character. if (params.query.trim() === "*") { const rows = listConversations({ limit: params.limit }); return rows.map((r) => ({ conversationId: r.id, conversationTitle: r.title, conversationUpdatedAt: r.updatedAt, matchingMessages: [], })); } return searchConversations(params.query, { limit: params.limit, maxMessagesPerConversation: params.maxMessagesPerConversation, }); } export interface MessageContentResult { conversationId?: string; messageId: string; text?: string; toolCalls?: Array<{ name: string; result?: string; input?: Record; }>; } /** * Get the full content of a single message by ID. * Returns null if the message is not found. */ export function getMessageContent( messageId: string, conversationId?: string, ): MessageContentResult | null { const dbMessage = getMessageById(messageId, conversationId); if (!dbMessage) { return null; } let text: string | undefined; let toolCalls: | Array<{ name: string; result?: string; input?: Record }> | undefined; try { const content = dbMessage.content; const rendered = renderHistoryContent(content); text = rendered.text || undefined; const parsedToolCalls = rendered.toolCalls; if (parsedToolCalls.length > 0) { toolCalls = parsedToolCalls.map((tc) => ({ name: tc.name, input: tc.input, ...(tc.result !== undefined ? { result: tc.result } : {}), })); } } catch { text = extractTextFromStoredMessageContent(dbMessage.content) || undefined; } return { conversationId, messageId, ...(text !== undefined ? { text } : {}), ...(toolCalls ? { toolCalls } : {}), }; }