Coverage for src/qdrant_loader_mcp_server/mcp/formatters/basic.py: 100%
61 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-08 06:06 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-08 06:06 +0000
1"""
2Basic Result Formatters - Core Search Result Formatting.
4This module handles basic formatting of search results, attachments,
5and hierarchical results for display in the MCP interface.
6"""
8from ...search.components.search_result_models import HybridSearchResult
11class BasicResultFormatters:
12 """Handles basic result formatting operations."""
14 @staticmethod
15 def _format_common_fields(
16 result: HybridSearchResult, is_attachment_view: bool = False
17 ) -> str:
18 """Build the base formatted string for a search result.
20 This consolidates shared formatting between standard search results and
21 attachment-focused views while preserving the original output order and
22 conditional branches.
23 """
24 formatted_result = f"Score: {result.score}\n"
25 formatted_result += f"Text: {result.text}\n"
26 formatted_result += f"Source: {result.source_type}"
28 if result.source_title:
29 formatted_result += f" - {result.source_title}"
31 # Project information (only shown in non-attachment view to preserve behavior)
32 if not is_attachment_view:
33 project_info = result.get_project_info()
34 if project_info:
35 formatted_result += f"\n🏗️ {project_info}"
37 # Attachment info (shown if viewing attachments or the result itself is an attachment)
38 if is_attachment_view or result.is_attachment:
39 formatted_result += "\n📎 Attachment"
40 if result.original_filename:
41 formatted_result += f": {result.original_filename}"
42 if result.attachment_context:
43 formatted_result += f"\n📋 {result.attachment_context}"
44 if result.parent_document_title:
45 formatted_result += f"\n📄 Attached to: {result.parent_document_title}"
47 # Confluence breadcrumb path
48 if result.source_type == "confluence" and result.breadcrumb_text:
49 formatted_result += f"\n📍 Path: {result.breadcrumb_text}"
51 # Source URL appended inline
52 if result.source_url:
53 formatted_result += f" ({result.source_url})"
55 if result.file_path:
56 formatted_result += f"\nFile: {result.file_path}"
58 if result.repo_name:
59 formatted_result += f"\nRepo: {result.repo_name}"
61 # Additional hierarchy info for Confluence
62 hierarchy_context = getattr(result, "hierarchy_context", None)
63 if result.source_type == "confluence" and hierarchy_context:
64 formatted_result += f"\n🏗️ {hierarchy_context}"
66 # Parent info (for hierarchy, not for attachment items themselves)
67 if result.parent_title and not result.is_attachment:
68 formatted_result += f"\n⬆️ Parent: {result.parent_title}"
70 # Children count
71 if result.has_children():
72 formatted_result += f"\n⬇️ Children: {result.children_count}"
74 return formatted_result
76 @staticmethod
77 def format_search_result(result: HybridSearchResult) -> str:
78 """Format a search result for display."""
79 return BasicResultFormatters._format_common_fields(
80 result, is_attachment_view=False
81 )
83 @staticmethod
84 def format_attachment_search_result(result: HybridSearchResult) -> str:
85 """Format an attachment search result for display."""
86 return BasicResultFormatters._format_common_fields(
87 result, is_attachment_view=True
88 )
90 @staticmethod
91 def format_hierarchical_results(
92 organized_results: dict[str, list[HybridSearchResult]],
93 ) -> str:
94 """Format hierarchically organized results for display."""
95 formatted_sections = []
97 for root_title, results in organized_results.items():
98 section = f"📁 **{root_title}** ({len(results)} results)\n"
100 for result in results:
101 indent = " " * (getattr(result, "depth", 0) or 0)
102 section += f"{indent}📄 {result.source_title}"
103 if hasattr(result, "hierarchy_context") and result.hierarchy_context:
104 section += f" | {result.hierarchy_context}"
105 section += f" (Score: {result.score:.3f})\n"
107 # Add a snippet of the content
108 content_snippet = (
109 result.text[:150] + "..." if len(result.text) > 150 else result.text
110 )
111 section += f"{indent} {content_snippet}\n"
113 if result.source_url:
114 section += f"{indent} 🔗 {result.source_url}\n"
115 section += "\n"
117 formatted_sections.append(section)
119 return (
120 f"Found {sum(len(results) for results in organized_results.values())} results organized by hierarchy:\n\n"
121 + "\n".join(formatted_sections)
122 )