Coverage for src / qdrant_loader_mcp_server / mcp / formatters / basic.py: 96%
67 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-10 09:41 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-10 09:41 +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"Source: {result.source_type}"
27 text = result.text
28 contextual_content = getattr(result, "contextual_content", None)
29 if isinstance(contextual_content, str) and contextual_content:
30 formatted_result += f"\nContext: {contextual_content}\n"
31 if isinstance(text, str) and text.startswith(contextual_content):
32 text = text[len(contextual_content) :].lstrip()
34 formatted_result += f"\nText: {text}"
36 if result.source_title:
37 formatted_result += f" - {result.source_title}"
39 # Project information (only shown in non-attachment view to preserve behavior)
40 if not is_attachment_view:
41 project_info = result.get_project_info()
42 if project_info:
43 formatted_result += f"\n🏗️ {project_info}"
45 # Attachment info (shown if viewing attachments or the result itself is an attachment)
46 if is_attachment_view or result.is_attachment:
47 formatted_result += "\n📎 Attachment"
48 if result.original_filename:
49 formatted_result += f": {result.original_filename}"
50 if result.attachment_context:
51 formatted_result += f"\n📋 {result.attachment_context}"
52 if result.parent_document_title:
53 formatted_result += f"\n📄 Attached to: {result.parent_document_title}"
55 # Confluence breadcrumb path
56 if result.source_type == "confluence" and result.breadcrumb_text:
57 formatted_result += f"\n📍 Path: {result.breadcrumb_text}"
59 # Source URL appended inline
60 if result.source_url:
61 formatted_result += f" ({result.source_url})"
63 if result.file_path:
64 formatted_result += f"\nFile: {result.file_path}"
66 if result.repo_name:
67 formatted_result += f"\nRepo: {result.repo_name}"
69 # Additional hierarchy info for Confluence
70 hierarchy_context = getattr(result, "hierarchy_context", None)
71 if result.source_type == "confluence" and hierarchy_context:
72 formatted_result += f"\n🏗️ {hierarchy_context}"
74 # Parent info (for hierarchy, not for attachment items themselves)
75 if result.parent_title and not result.is_attachment:
76 formatted_result += f"\n⬆️ Parent: {result.parent_title}"
78 # Children count
79 if result.has_children():
80 formatted_result += f"\n⬇️ Children: {result.children_count}"
82 return formatted_result
84 @staticmethod
85 def format_search_result(result: HybridSearchResult) -> str:
86 """Format a search result for display."""
87 return BasicResultFormatters._format_common_fields(
88 result, is_attachment_view=False
89 )
91 @staticmethod
92 def format_attachment_search_result(result: HybridSearchResult) -> str:
93 """Format an attachment search result for display."""
94 return BasicResultFormatters._format_common_fields(
95 result, is_attachment_view=True
96 )
98 @staticmethod
99 def format_hierarchical_results(
100 organized_results: dict[str, list[HybridSearchResult]],
101 ) -> str:
102 """Format hierarchically organized results for display."""
103 formatted_sections = []
105 for root_title, results in organized_results.items():
106 section = f"📁 **{root_title}** ({len(results)} results)\n"
108 for result in results:
109 indent = " " * (getattr(result, "depth", 0) or 0)
110 section += f"{indent}📄 {result.source_title}"
111 if hasattr(result, "hierarchy_context") and result.hierarchy_context:
112 section += f" | {result.hierarchy_context}"
113 section += f" (Score: {result.score:.3f})\n"
115 # Add a snippet of the content
116 content_snippet = (
117 result.text[:150] + "..." if len(result.text) > 150 else result.text
118 )
119 section += f"{indent} {content_snippet}\n"
121 if result.source_url:
122 section += f"{indent} 🔗 {result.source_url}\n"
123 section += "\n"
125 formatted_sections.append(section)
127 return (
128 f"Found {sum(len(results) for results in organized_results.values())} results organized by hierarchy:\n\n"
129 + "\n".join(formatted_sections)
130 )