jarvis-ai-assistant 0.1.104__py3-none-any.whl → 0.1.105__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (62) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +124 -67
  3. jarvis/jarvis_code_agent/code_agent.py +133 -22
  4. jarvis/jarvis_code_agent/patch.py +4 -7
  5. jarvis/jarvis_code_agent/relevant_files.py +163 -72
  6. jarvis/jarvis_codebase/main.py +36 -15
  7. jarvis/jarvis_lsp/base.py +143 -0
  8. jarvis/jarvis_lsp/cpp.py +134 -0
  9. jarvis/jarvis_lsp/go.py +140 -0
  10. jarvis/jarvis_lsp/python.py +135 -0
  11. jarvis/jarvis_lsp/registry.py +234 -0
  12. jarvis/jarvis_lsp/rust.py +142 -0
  13. jarvis/jarvis_platform/__init__.py +3 -0
  14. jarvis/{models → jarvis_platform}/ai8.py +1 -1
  15. jarvis/{models → jarvis_platform}/kimi.py +1 -1
  16. jarvis/{models → jarvis_platform}/ollama.py +1 -1
  17. jarvis/{models → jarvis_platform}/openai.py +1 -1
  18. jarvis/{models → jarvis_platform}/oyi.py +1 -1
  19. jarvis/{models → jarvis_platform}/registry.py +11 -11
  20. jarvis/{jarvis_platform → jarvis_platform_manager}/main.py +1 -1
  21. jarvis/jarvis_rag/main.py +6 -6
  22. jarvis/jarvis_smart_shell/main.py +3 -3
  23. jarvis/jarvis_tools/__init__.py +0 -0
  24. jarvis/{tools → jarvis_tools}/ask_user.py +1 -1
  25. jarvis/{tools → jarvis_tools}/code_review.py +34 -8
  26. jarvis/jarvis_tools/create_code_agent.py +115 -0
  27. jarvis/{tools → jarvis_tools}/create_sub_agent.py +1 -1
  28. jarvis/jarvis_tools/deep_thinking.py +160 -0
  29. jarvis/jarvis_tools/deep_thinking_agent.py +146 -0
  30. jarvis/{tools → jarvis_tools}/git_commiter.py +2 -2
  31. jarvis/jarvis_tools/lsp_find_definition.py +134 -0
  32. jarvis/jarvis_tools/lsp_find_references.py +111 -0
  33. jarvis/jarvis_tools/lsp_get_diagnostics.py +121 -0
  34. jarvis/jarvis_tools/lsp_get_document_symbols.py +87 -0
  35. jarvis/jarvis_tools/lsp_prepare_rename.py +130 -0
  36. jarvis/jarvis_tools/lsp_validate_edit.py +141 -0
  37. jarvis/{tools → jarvis_tools}/methodology.py +6 -1
  38. jarvis/{tools → jarvis_tools}/registry.py +6 -5
  39. jarvis/{tools → jarvis_tools}/search.py +2 -2
  40. jarvis/utils.py +68 -25
  41. {jarvis_ai_assistant-0.1.104.dist-info → jarvis_ai_assistant-0.1.105.dist-info}/METADATA +21 -10
  42. jarvis_ai_assistant-0.1.105.dist-info/RECORD +62 -0
  43. {jarvis_ai_assistant-0.1.104.dist-info → jarvis_ai_assistant-0.1.105.dist-info}/entry_points.txt +4 -4
  44. jarvis/models/__init__.py +0 -3
  45. jarvis/tools/create_code_test_agent.py +0 -115
  46. jarvis/tools/create_ctags_agent.py +0 -164
  47. jarvis/tools/find_in_codebase.py +0 -78
  48. jarvis_ai_assistant-0.1.104.dist-info/RECORD +0 -50
  49. /jarvis/{models → jarvis_platform}/base.py +0 -0
  50. /jarvis/{tools → jarvis_platform_manager}/__init__.py +0 -0
  51. /jarvis/{tools → jarvis_tools}/ask_codebase.py +0 -0
  52. /jarvis/{tools → jarvis_tools}/base.py +0 -0
  53. /jarvis/{tools → jarvis_tools}/chdir.py +0 -0
  54. /jarvis/{tools → jarvis_tools}/execute_shell.py +0 -0
  55. /jarvis/{tools → jarvis_tools}/file_operation.py +0 -0
  56. /jarvis/{tools → jarvis_tools}/rag.py +0 -0
  57. /jarvis/{tools → jarvis_tools}/read_code.py +0 -0
  58. /jarvis/{tools → jarvis_tools}/read_webpage.py +0 -0
  59. /jarvis/{tools → jarvis_tools}/select_code_files.py +0 -0
  60. {jarvis_ai_assistant-0.1.104.dist-info → jarvis_ai_assistant-0.1.105.dist-info}/LICENSE +0 -0
  61. {jarvis_ai_assistant-0.1.104.dist-info → jarvis_ai_assistant-0.1.105.dist-info}/WHEEL +0 -0
  62. {jarvis_ai_assistant-0.1.104.dist-info → jarvis_ai_assistant-0.1.105.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,146 @@
1
+ import os
2
+ from typing import Dict, Any
3
+ from jarvis.agent import Agent
4
+ from jarvis.jarvis_platform.registry import PlatformRegistry
5
+ from jarvis.jarvis_tools.registry import ToolRegistry
6
+ from jarvis.utils import OutputType, PrettyOutput
7
+
8
+ class DeepThinkingAgentTool:
9
+ """Tool for deep thinking using an agent with thinking platform."""
10
+
11
+ name = "deep_thinking_agent"
12
+ description = "Use an agent to think deeply about problems and solutions"
13
+ parameters = {
14
+ "question": "The question or problem to think about"
15
+ }
16
+
17
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
18
+ try:
19
+ question = args.get("question", "")
20
+ if not question:
21
+ return {
22
+ "success": False,
23
+ "stderr": "Question must be provided",
24
+ "stdout": ""
25
+ }
26
+
27
+ # Initialize tool registry
28
+ tool_registry = ToolRegistry()
29
+ tool_registry.dont_use_tools([
30
+ "deep_thinking_agent"
31
+ ])
32
+
33
+ # Define system prompt for thinking agent
34
+ system_prompt = """You are a deep thinking agent that carefully analyzes problems and proposes solutions.
35
+
36
+ THINKING PROCESS:
37
+ 1. Initial Analysis
38
+ ```
39
+ Thought: Let me first understand the core problem...
40
+ Action: Use deep_thinking with mode=analysis
41
+ Observation: The analysis shows...
42
+
43
+ Thought: I need more information about...
44
+ Action: Use appropriate tool (search/ask_user/ask_codebase)
45
+ Observation: Found that...
46
+ ```
47
+
48
+ 2. Solution Exploration
49
+ ```
50
+ Thought: Let me explore possible solutions...
51
+ Action: Use deep_thinking with mode=solution
52
+ Observation: The potential solutions are...
53
+
54
+ Thought: I should validate these approaches...
55
+ Action: Use appropriate tool to verify
56
+ Observation: Verification shows...
57
+ ```
58
+
59
+ 3. Critical Review
60
+ ```
61
+ Thought: Let me critique the proposed solution...
62
+ Action: Use deep_thinking with mode=critique
63
+ Observation: The critique reveals...
64
+
65
+ Thought: These points need addressing...
66
+ Action: Revise solution based on critique
67
+ Observation: The improved solution...
68
+ ```
69
+
70
+ 4. Final Recommendation
71
+ ```
72
+ Thought: Synthesize all findings...
73
+ Action: Compile final recommendation
74
+ Output: Detailed solution with rationale
75
+ ```
76
+
77
+ GUIDELINES:
78
+ - Use deep_thinking tool for structured analysis
79
+ - Validate assumptions with search/ask_user
80
+ - Consider multiple perspectives
81
+ - Provide evidence for conclusions
82
+ - Be thorough but practical
83
+ - Focus on actionable recommendations
84
+
85
+ Please proceed with the analysis and provide a comprehensive response."""
86
+
87
+ # Create agent with thinking platform
88
+ agent = Agent(
89
+ system_prompt=system_prompt,
90
+ name="DeepThinkingAgent",
91
+ tool_registry=tool_registry,
92
+ platform=PlatformRegistry().get_thinking_platform(),
93
+ auto_complete=True,
94
+ is_sub_agent=True,
95
+ summary_prompt="""Please provide a structured summary of your thinking process and conclusions:
96
+
97
+ <THINKING_SUMMARY>
98
+ Analysis:
99
+ [Key findings from analysis]
100
+
101
+ Solutions:
102
+ [Proposed solutions and rationale]
103
+
104
+ Critique:
105
+ [Critical considerations]
106
+
107
+ Recommendation:
108
+ [Final recommendation with justification]
109
+ </THINKING_SUMMARY>"""
110
+ )
111
+
112
+ # Run agent
113
+ result = agent.run(question)
114
+
115
+ return {
116
+ "success": True,
117
+ "stdout": result,
118
+ "stderr": ""
119
+ }
120
+
121
+ except Exception as e:
122
+ return {
123
+ "success": False,
124
+ "stderr": f"Deep thinking failed: {str(e)}",
125
+ "stdout": ""
126
+ }
127
+
128
+ def main():
129
+ """CLI entry point"""
130
+ import argparse
131
+
132
+ parser = argparse.ArgumentParser(description='Deep thinking agent')
133
+ parser.add_argument('question', help='Question or problem to think about')
134
+
135
+ args = parser.parse_args()
136
+
137
+ tool = DeepThinkingAgentTool()
138
+ result = tool.execute({"question": args.question})
139
+
140
+ if result["success"]:
141
+ PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
142
+ else:
143
+ PrettyOutput.print(result["stderr"], OutputType.ERROR)
144
+
145
+ if __name__ == "__main__":
146
+ main()
@@ -4,8 +4,8 @@ from typing import Dict, Any
4
4
 
5
5
  import yaml
6
6
  from jarvis.agent import Agent
7
- from jarvis.models.registry import PlatformRegistry
8
- from jarvis.tools.registry import ToolRegistry
7
+ from jarvis.jarvis_platform.registry import PlatformRegistry
8
+ from jarvis.jarvis_tools.registry import ToolRegistry
9
9
  from jarvis.utils import OutputType, PrettyOutput, init_env
10
10
  import sys
11
11
 
@@ -0,0 +1,134 @@
1
+ import os
2
+ from typing import Dict, Any
3
+ from jarvis.jarvis_lsp.registry import LSPRegistry
4
+
5
+ class LSPFindDefinitionTool:
6
+ """Tool for finding symbol definitions in code using LSP."""
7
+
8
+ name = "lsp_find_definition"
9
+ description = "Find the definition of a symbol in code"
10
+ parameters = {
11
+ "file_path": "Path to the file containing the symbol",
12
+ "line": "Line number (0-based) of the symbol",
13
+ "character": "Character position in the line",
14
+ "language": f"Programming language of the file ({', '.join(LSPRegistry.get_global_lsp_registry().get_supported_languages())})"
15
+ }
16
+
17
+ @staticmethod
18
+ def check() -> bool:
19
+ """Check if any LSP server is available."""
20
+ registry = LSPRegistry.get_global_lsp_registry()
21
+ return len(registry.get_supported_languages()) > 0
22
+
23
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
24
+ """Execute the tool."""
25
+ file_path = args.get("file_path", "")
26
+ line = args.get("line", None)
27
+ character = args.get("character", None)
28
+ language = args.get("language", "")
29
+
30
+ # Validate inputs
31
+ if not all([file_path, line is not None, character is not None, language]):
32
+ return {
33
+ "success": False,
34
+ "stderr": "All parameters (file_path, line, character, language) must be provided",
35
+ "stdout": ""
36
+ }
37
+
38
+ try:
39
+ line = int(line)
40
+ character = int(character)
41
+ except ValueError:
42
+ return {
43
+ "success": False,
44
+ "stderr": "Line and character must be integers",
45
+ "stdout": ""
46
+ }
47
+
48
+ if not os.path.exists(file_path):
49
+ return {
50
+ "success": False,
51
+ "stderr": f"File not found: {file_path}",
52
+ "stdout": ""
53
+ }
54
+
55
+ # Get LSP instance
56
+ registry = LSPRegistry.get_global_lsp_registry()
57
+ lsp = registry.create_lsp(language)
58
+
59
+ if not lsp:
60
+ return {
61
+ "success": False,
62
+ "stderr": f"No LSP support for language: {language}",
63
+ "stdout": ""
64
+ }
65
+
66
+ try:
67
+ # Initialize LSP
68
+ if not lsp.initialize(os.path.dirname(os.path.abspath(file_path))):
69
+ return {
70
+ "success": False,
71
+ "stderr": "LSP initialization failed",
72
+ "stdout": ""
73
+ }
74
+
75
+ # Get symbol at position
76
+ symbol = LSPRegistry.get_text_at_position(file_path, line, character)
77
+ if not symbol:
78
+ return {
79
+ "success": False,
80
+ "stderr": f"No symbol found at position {line}:{character}",
81
+ "stdout": ""
82
+ }
83
+
84
+ # Find definition
85
+ defn = lsp.find_definition(file_path, (line, character))
86
+
87
+ if not defn:
88
+ return {
89
+ "success": True,
90
+ "stdout": f"No definition found for '{symbol}'",
91
+ "stderr": ""
92
+ }
93
+
94
+ # Format output
95
+ def_line = defn["range"]["start"]["line"]
96
+ def_char = defn["range"]["start"]["character"]
97
+ context = LSPRegistry.get_line_at_position(defn["uri"], def_line).strip()
98
+
99
+ output = [
100
+ f"Definition of '{symbol}':",
101
+ f"File: {defn['uri']}",
102
+ f"Line {def_line + 1}, Col {def_char + 1}: {context}"
103
+ ]
104
+
105
+ # Get a few lines of context around the definition
106
+ try:
107
+ with open(defn["uri"], 'r') as f:
108
+ lines = f.readlines()
109
+ start = max(0, def_line - 2)
110
+ end = min(len(lines), def_line + 3)
111
+
112
+ if start < def_line:
113
+ output.append("\nContext:")
114
+ for i in range(start, end):
115
+ prefix = ">" if i == def_line else " "
116
+ output.append(f"{prefix} {i+1:4d} | {lines[i].rstrip()}")
117
+ except Exception:
118
+ pass
119
+
120
+ return {
121
+ "success": True,
122
+ "stdout": "\n".join(output),
123
+ "stderr": ""
124
+ }
125
+
126
+ except Exception as e:
127
+ return {
128
+ "success": False,
129
+ "stderr": f"Error finding definition: {str(e)}",
130
+ "stdout": ""
131
+ }
132
+ finally:
133
+ if lsp:
134
+ lsp.shutdown()
@@ -0,0 +1,111 @@
1
+ import os
2
+ from typing import Dict, Any
3
+ from jarvis.jarvis_lsp.registry import LSPRegistry
4
+
5
+ class LSPFindReferencesTool:
6
+ """Tool for finding references to symbols in code using LSP."""
7
+
8
+ name = "lsp_find_references"
9
+ description = "Find all references to a symbol in code"
10
+ parameters = {
11
+ "file_path": "Path to the file containing the symbol",
12
+ "line": "Line number (0-based) of the symbol",
13
+ "character": "Character position in the line",
14
+ "language": f"Programming language of the file ({', '.join(LSPRegistry.get_global_lsp_registry().get_supported_languages())})"
15
+ }
16
+
17
+ @staticmethod
18
+ def check() -> bool:
19
+ """Check if any LSP server is available."""
20
+ registry = LSPRegistry.get_global_lsp_registry()
21
+ return len(registry.get_supported_languages()) > 0
22
+
23
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
24
+ """Execute the tool."""
25
+ file_path = args.get("file_path", "")
26
+ line = args.get("line", None)
27
+ character = args.get("character", None)
28
+ language = args.get("language", "")
29
+
30
+ # Validate inputs
31
+ if not all([file_path, line is not None, character is not None, language]):
32
+ return {
33
+ "success": False,
34
+ "stderr": "All parameters (file_path, line, character, language) must be provided",
35
+ "stdout": ""
36
+ }
37
+
38
+ try:
39
+ line = int(line)
40
+ character = int(character)
41
+ except ValueError:
42
+ return {
43
+ "success": False,
44
+ "stderr": "Line and character must be integers",
45
+ "stdout": ""
46
+ }
47
+
48
+ if not os.path.exists(file_path):
49
+ return {
50
+ "success": False,
51
+ "stderr": f"File not found: {file_path}",
52
+ "stdout": ""
53
+ }
54
+
55
+ # Get LSP instance
56
+ registry = LSPRegistry.get_global_lsp_registry()
57
+ lsp = registry.create_lsp(language)
58
+
59
+ if not lsp:
60
+ return {
61
+ "success": False,
62
+ "stderr": f"No LSP support for language: {language}",
63
+ "stdout": ""
64
+ }
65
+
66
+ try:
67
+ # Initialize LSP
68
+ if not lsp.initialize(os.path.dirname(os.path.abspath(file_path))):
69
+ return {
70
+ "success": False,
71
+ "stderr": "LSP initialization failed",
72
+ "stdout": ""
73
+ }
74
+
75
+ # Get symbol at position
76
+ symbol = LSPRegistry.get_text_at_position(file_path, line, character)
77
+ if not symbol:
78
+ return {
79
+ "success": False,
80
+ "stderr": f"No symbol found at position {line}:{character}",
81
+ "stdout": ""
82
+ }
83
+
84
+ # Find references
85
+ refs = lsp.find_references(file_path, (line, character))
86
+
87
+ # Format output
88
+ output = [f"References to '{symbol}':\n"]
89
+ for ref in refs:
90
+ ref_line = ref["range"]["start"]["line"]
91
+ ref_char = ref["range"]["start"]["character"]
92
+ context = LSPRegistry.get_line_at_position(ref["uri"], ref_line).strip()
93
+ output.append(f"File: {ref['uri']}")
94
+ output.append(f"Line {ref_line + 1}, Col {ref_char + 1}: {context}")
95
+ output.append("-" * 40)
96
+
97
+ return {
98
+ "success": True,
99
+ "stdout": "\n".join(output) if len(refs) > 0 else f"No references found for '{symbol}'",
100
+ "stderr": ""
101
+ }
102
+
103
+ except Exception as e:
104
+ return {
105
+ "success": False,
106
+ "stderr": f"Error finding references: {str(e)}",
107
+ "stdout": ""
108
+ }
109
+ finally:
110
+ if lsp:
111
+ lsp.shutdown()
@@ -0,0 +1,121 @@
1
+ import os
2
+ from typing import Dict, Any
3
+ from jarvis.jarvis_lsp.registry import LSPRegistry
4
+
5
+ class LSPGetDiagnosticsTool:
6
+ """Tool for getting diagnostics (errors, warnings) from code using LSP."""
7
+
8
+ name = "lsp_get_diagnostics"
9
+ description = "Get diagnostic information (errors, warnings) from code files"
10
+ parameters = {
11
+ "file_path": "Path to the file to analyze",
12
+ "language": f"Programming language of the file ({', '.join(LSPRegistry.get_global_lsp_registry().get_supported_languages())})"
13
+ }
14
+
15
+ @staticmethod
16
+ def check() -> bool:
17
+ """Check if any LSP server is available."""
18
+ registry = LSPRegistry.get_global_lsp_registry()
19
+ return len(registry.get_supported_languages()) > 0
20
+
21
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
22
+ """Execute the tool."""
23
+ file_path = args.get("file_path", "")
24
+ language = args.get("language", "")
25
+
26
+ # Validate inputs
27
+ if not all([file_path, language]):
28
+ return {
29
+ "success": False,
30
+ "stderr": "Both file_path and language must be provided",
31
+ "stdout": ""
32
+ }
33
+
34
+ if not os.path.exists(file_path):
35
+ return {
36
+ "success": False,
37
+ "stderr": f"File not found: {file_path}",
38
+ "stdout": ""
39
+ }
40
+
41
+ # Get LSP instance
42
+ registry = LSPRegistry.get_global_lsp_registry()
43
+ lsp = registry.create_lsp(language)
44
+
45
+ if not lsp:
46
+ return {
47
+ "success": False,
48
+ "stderr": f"No LSP support for language: {language}",
49
+ "stdout": ""
50
+ }
51
+
52
+ try:
53
+ # Initialize LSP
54
+ if not lsp.initialize(os.path.dirname(os.path.abspath(file_path))):
55
+ return {
56
+ "success": False,
57
+ "stderr": "LSP initialization failed",
58
+ "stdout": ""
59
+ }
60
+
61
+ # Get diagnostics
62
+ diagnostics = lsp.get_diagnostics(file_path)
63
+
64
+ if not diagnostics:
65
+ return {
66
+ "success": True,
67
+ "stdout": "No issues found in the file",
68
+ "stderr": ""
69
+ }
70
+
71
+ # Format output
72
+ output = ["Diagnostics:"]
73
+ severity_map = {1: "Error", 2: "Warning", 3: "Info", 4: "Hint"}
74
+
75
+ # Sort diagnostics by severity and line number
76
+ sorted_diagnostics = sorted(
77
+ diagnostics,
78
+ key=lambda x: (x["severity"], x["range"]["start"]["line"])
79
+ )
80
+
81
+ for diag in sorted_diagnostics:
82
+ severity = severity_map.get(diag["severity"], "Unknown")
83
+ start = diag["range"]["start"]
84
+ line = LSPRegistry.get_line_at_position(file_path, start["line"]).strip()
85
+
86
+ output.extend([
87
+ f"\n{severity} at line {start['line'] + 1}, column {start['character'] + 1}:",
88
+ f"Message: {diag['message']}",
89
+ f"Code: {line}",
90
+ "-" * 60
91
+ ])
92
+
93
+ # Add related information if available
94
+ if diag.get("relatedInformation"):
95
+ output.append("Related information:")
96
+ for info in diag["relatedInformation"]:
97
+ info_line = LSPRegistry.get_line_at_position(
98
+ info["location"]["uri"],
99
+ info["location"]["range"]["start"]["line"]
100
+ ).strip()
101
+ output.extend([
102
+ f" - {info['message']}",
103
+ f" at {info['location']['uri']}:{info['location']['range']['start']['line'] + 1}",
104
+ f" {info_line}"
105
+ ])
106
+
107
+ return {
108
+ "success": True,
109
+ "stdout": "\n".join(output),
110
+ "stderr": ""
111
+ }
112
+
113
+ except Exception as e:
114
+ return {
115
+ "success": False,
116
+ "stderr": f"Error getting diagnostics: {str(e)}",
117
+ "stdout": ""
118
+ }
119
+ finally:
120
+ if lsp:
121
+ lsp.shutdown()
@@ -0,0 +1,87 @@
1
+ import os
2
+ from typing import Dict, Any
3
+ from jarvis.jarvis_lsp.registry import LSPRegistry
4
+
5
+ class LSPGetDocumentSymbolsTool:
6
+ """Tool for getting document symbols in code files using LSP."""
7
+
8
+ name = "lsp_get_document_symbols"
9
+ description = "Get document symbols (functions, classes, variables) in code files"
10
+ parameters = {
11
+ "file_path": "Path to the file to analyze",
12
+ "language": f"Programming language of the file ({', '.join(LSPRegistry.get_global_lsp_registry().get_supported_languages())})"
13
+ }
14
+
15
+ @staticmethod
16
+ def check() -> bool:
17
+ """Check if any LSP server is available."""
18
+ registry = LSPRegistry.get_global_lsp_registry()
19
+ return len(registry.get_supported_languages()) > 0
20
+
21
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
22
+ """Execute the tool."""
23
+ file_path = args.get("file_path", "")
24
+ language = args.get("language", "")
25
+
26
+ if not file_path or not language:
27
+ return {
28
+ "success": False,
29
+ "stderr": "Both file_path and language must be provided",
30
+ "stdout": ""
31
+ }
32
+
33
+ if not os.path.exists(file_path):
34
+ return {
35
+ "success": False,
36
+ "stderr": f"File not found: {file_path}",
37
+ "stdout": ""
38
+ }
39
+
40
+ # Get LSP instance
41
+ registry = LSPRegistry.get_global_lsp_registry()
42
+ lsp = registry.create_lsp(language)
43
+
44
+ if not lsp:
45
+ return {
46
+ "success": False,
47
+ "stderr": f"No LSP support for language: {language}",
48
+ "stdout": ""
49
+ }
50
+
51
+ try:
52
+ # Initialize LSP
53
+ if not lsp.initialize(os.path.dirname(os.path.abspath(file_path))):
54
+ return {
55
+ "success": False,
56
+ "stderr": "LSP initialization failed",
57
+ "stdout": ""
58
+ }
59
+
60
+ # Get symbols
61
+ symbols = lsp.get_document_symbols(file_path)
62
+
63
+ # Format output
64
+ output = []
65
+ for symbol in symbols:
66
+ start = symbol["range"]["start"]
67
+ name = LSPRegistry.get_text_at_position(file_path, start["line"], start["character"])
68
+ line = LSPRegistry.get_line_at_position(file_path, start["line"]).strip()
69
+ output.append(f"Symbol: {name}")
70
+ output.append(f"Line {start['line'] + 1}: {line}")
71
+ output.append("-" * 40)
72
+
73
+ return {
74
+ "success": True,
75
+ "stdout": "\n".join(output) if output else "No symbols found",
76
+ "stderr": ""
77
+ }
78
+
79
+ except Exception as e:
80
+ return {
81
+ "success": False,
82
+ "stderr": f"Error finding symbols: {str(e)}",
83
+ "stdout": ""
84
+ }
85
+ finally:
86
+ if lsp:
87
+ lsp.shutdown()