jarvis-ai-assistant 0.1.132__py3-none-any.whl → 0.1.138__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 (82) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +330 -347
  3. jarvis/jarvis_agent/builtin_input_handler.py +16 -6
  4. jarvis/jarvis_agent/file_input_handler.py +9 -9
  5. jarvis/jarvis_agent/jarvis.py +143 -0
  6. jarvis/jarvis_agent/main.py +12 -13
  7. jarvis/jarvis_agent/output_handler.py +3 -3
  8. jarvis/jarvis_agent/patch.py +92 -64
  9. jarvis/jarvis_agent/shell_input_handler.py +5 -3
  10. jarvis/jarvis_code_agent/code_agent.py +263 -177
  11. jarvis/jarvis_code_agent/file_select.py +24 -24
  12. jarvis/jarvis_dev/main.py +45 -59
  13. jarvis/jarvis_git_details/__init__.py +0 -0
  14. jarvis/jarvis_git_details/main.py +179 -0
  15. jarvis/jarvis_git_squash/main.py +7 -7
  16. jarvis/jarvis_lsp/base.py +11 -53
  17. jarvis/jarvis_lsp/cpp.py +13 -28
  18. jarvis/jarvis_lsp/go.py +13 -28
  19. jarvis/jarvis_lsp/python.py +8 -27
  20. jarvis/jarvis_lsp/registry.py +21 -83
  21. jarvis/jarvis_lsp/rust.py +15 -30
  22. jarvis/jarvis_methodology/main.py +101 -0
  23. jarvis/jarvis_multi_agent/__init__.py +10 -51
  24. jarvis/jarvis_multi_agent/main.py +43 -0
  25. jarvis/jarvis_platform/__init__.py +1 -1
  26. jarvis/jarvis_platform/ai8.py +67 -89
  27. jarvis/jarvis_platform/base.py +14 -13
  28. jarvis/jarvis_platform/kimi.py +25 -28
  29. jarvis/jarvis_platform/ollama.py +24 -26
  30. jarvis/jarvis_platform/openai.py +15 -19
  31. jarvis/jarvis_platform/oyi.py +48 -50
  32. jarvis/jarvis_platform/registry.py +29 -44
  33. jarvis/jarvis_platform/yuanbao.py +39 -43
  34. jarvis/jarvis_platform_manager/main.py +81 -81
  35. jarvis/jarvis_platform_manager/openai_test.py +21 -21
  36. jarvis/jarvis_rag/file_processors.py +18 -18
  37. jarvis/jarvis_rag/main.py +262 -278
  38. jarvis/jarvis_smart_shell/main.py +12 -12
  39. jarvis/jarvis_tools/ask_codebase.py +85 -78
  40. jarvis/jarvis_tools/ask_user.py +8 -8
  41. jarvis/jarvis_tools/base.py +4 -4
  42. jarvis/jarvis_tools/chdir.py +9 -9
  43. jarvis/jarvis_tools/code_review.py +40 -21
  44. jarvis/jarvis_tools/create_code_agent.py +15 -15
  45. jarvis/jarvis_tools/create_sub_agent.py +0 -1
  46. jarvis/jarvis_tools/execute_python_script.py +3 -3
  47. jarvis/jarvis_tools/execute_shell.py +11 -11
  48. jarvis/jarvis_tools/execute_shell_script.py +3 -3
  49. jarvis/jarvis_tools/file_analyzer.py +116 -105
  50. jarvis/jarvis_tools/file_operation.py +22 -20
  51. jarvis/jarvis_tools/find_caller.py +105 -40
  52. jarvis/jarvis_tools/find_methodolopy.py +65 -0
  53. jarvis/jarvis_tools/find_symbol.py +123 -39
  54. jarvis/jarvis_tools/function_analyzer.py +140 -57
  55. jarvis/jarvis_tools/git_commiter.py +10 -10
  56. jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
  57. jarvis/jarvis_tools/methodology.py +22 -67
  58. jarvis/jarvis_tools/project_analyzer.py +137 -53
  59. jarvis/jarvis_tools/rag.py +15 -20
  60. jarvis/jarvis_tools/read_code.py +25 -23
  61. jarvis/jarvis_tools/read_webpage.py +31 -31
  62. jarvis/jarvis_tools/registry.py +72 -52
  63. jarvis/jarvis_tools/search_web.py +23 -353
  64. jarvis/jarvis_tools/tool_generator.py +19 -19
  65. jarvis/jarvis_utils/config.py +36 -96
  66. jarvis/jarvis_utils/embedding.py +83 -83
  67. jarvis/jarvis_utils/git_utils.py +20 -20
  68. jarvis/jarvis_utils/globals.py +18 -6
  69. jarvis/jarvis_utils/input.py +10 -9
  70. jarvis/jarvis_utils/methodology.py +141 -140
  71. jarvis/jarvis_utils/output.py +13 -13
  72. jarvis/jarvis_utils/utils.py +23 -71
  73. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +6 -15
  74. jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
  75. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +4 -3
  76. jarvis/jarvis_tools/lsp_find_definition.py +0 -150
  77. jarvis/jarvis_tools/lsp_find_references.py +0 -127
  78. jarvis/jarvis_tools/select_code_files.py +0 -62
  79. jarvis_ai_assistant-0.1.132.dist-info/RECORD +0 -82
  80. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
  81. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
  82. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/top_level.txt +0 -0
jarvis/jarvis_lsp/cpp.py CHANGED
@@ -8,19 +8,19 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
8
 
9
9
  class CPPLSP(BaseLSP):
10
10
  """C++ LSP implementation using clangd."""
11
-
11
+
12
12
  language = ["cpp", "c"]
13
13
 
14
14
  @staticmethod
15
15
  def check() -> bool:
16
16
  """Check if clangd is installed."""
17
17
  return shutil.which("clangd") is not None
18
-
18
+
19
19
  def __init__(self):
20
20
  self.workspace_path = ""
21
21
  self.clangd_process = None
22
22
  self.request_id = 0
23
-
23
+
24
24
  def initialize(self, workspace_path: str) -> bool:
25
25
  try:
26
26
  self.workspace_path = workspace_path
@@ -31,24 +31,24 @@ class CPPLSP(BaseLSP):
31
31
  stdout=subprocess.PIPE,
32
32
  stderr=subprocess.PIPE
33
33
  )
34
-
34
+
35
35
  # Send initialize request
36
36
  self._send_request("initialize", {
37
37
  "processId": os.getpid(),
38
38
  "rootUri": f"file://{workspace_path}",
39
39
  "capabilities": {}
40
40
  })
41
-
41
+
42
42
  return True
43
43
  except Exception as e:
44
44
  PrettyOutput.print(f"C++ LSP 初始化失败: {str(e)}", OutputType.ERROR)
45
45
  return False
46
-
46
+
47
47
  def _send_request(self, method: str, params: Dict) -> Optional[Dict]:
48
48
  """Send JSON-RPC request to clangd."""
49
49
  if not self.clangd_process:
50
50
  return None
51
-
51
+
52
52
  try:
53
53
  self.request_id += 1
54
54
  request = {
@@ -57,31 +57,16 @@ class CPPLSP(BaseLSP):
57
57
  "method": method,
58
58
  "params": params
59
59
  }
60
-
60
+
61
61
  self.clangd_process.stdin.write(json.dumps(request).encode() + b"\n") # type: ignore
62
62
  self.clangd_process.stdin.flush() # type: ignore
63
-
63
+
64
64
  response = json.loads(self.clangd_process.stdout.readline().decode()) # type: ignore
65
65
  return response.get("result")
66
66
  except Exception:
67
67
  return None
68
-
69
- def find_references(self, file_path: str, position: Tuple[int, int]) -> List[Dict[str, Any]]:
70
- result = self._send_request("textDocument/references", {
71
- "textDocument": {"uri": f"file://{file_path}"},
72
- "position": {"line": position[0], "character": position[1]},
73
- "context": {"includeDeclaration": True}
74
- })
75
- return result or [] # type: ignore
76
-
77
- def find_definition(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
78
- result = self._send_request("textDocument/definition", {
79
- "textDocument": {"uri": f"file://{file_path}"},
80
- "position": {"line": position[0], "character": position[1]}
81
- })
82
- return result[0] if result else None
83
68
 
84
-
69
+
85
70
  def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
86
71
  # Send didOpen notification to trigger diagnostics
87
72
  self._send_request("textDocument/didOpen", {
@@ -92,7 +77,7 @@ class CPPLSP(BaseLSP):
92
77
  "text": open(file_path).read()
93
78
  }
94
79
  })
95
-
80
+
96
81
  # Wait for diagnostic notification
97
82
  try:
98
83
  response = json.loads(self.clangd_process.stdout.readline().decode()) # type: ignore
@@ -101,8 +86,8 @@ class CPPLSP(BaseLSP):
101
86
  except Exception:
102
87
  pass
103
88
  return []
104
-
105
-
89
+
90
+
106
91
  def shutdown(self):
107
92
  if self.clangd_process:
108
93
  try:
jarvis/jarvis_lsp/go.py CHANGED
@@ -8,19 +8,19 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
8
 
9
9
  class GoLSP(BaseLSP):
10
10
  """Go LSP implementation using gopls."""
11
-
11
+
12
12
  language = "go"
13
13
 
14
14
  @staticmethod
15
15
  def check() -> bool:
16
16
  """Check if gopls is installed."""
17
17
  return shutil.which("gopls") is not None
18
-
18
+
19
19
  def __init__(self):
20
20
  self.workspace_path = ""
21
21
  self.gopls_process = None
22
22
  self.request_id = 0
23
-
23
+
24
24
  def initialize(self, workspace_path: str) -> bool:
25
25
  try:
26
26
  self.workspace_path = workspace_path
@@ -31,7 +31,7 @@ class GoLSP(BaseLSP):
31
31
  stdout=subprocess.PIPE,
32
32
  stderr=subprocess.PIPE
33
33
  )
34
-
34
+
35
35
  # Send initialize request
36
36
  self._send_request("initialize", {
37
37
  "processId": os.getpid(),
@@ -44,17 +44,17 @@ class GoLSP(BaseLSP):
44
44
  }
45
45
  }
46
46
  })
47
-
47
+
48
48
  return True
49
49
  except Exception as e:
50
50
  PrettyOutput.print(f"Go LSP 初始化失败: {str(e)}", OutputType.ERROR)
51
51
  return False
52
-
52
+
53
53
  def _send_request(self, method: str, params: Dict) -> Optional[Dict]:
54
54
  """Send JSON-RPC request to gopls."""
55
55
  if not self.gopls_process:
56
56
  return None
57
-
57
+
58
58
  try:
59
59
  self.request_id += 1
60
60
  request = {
@@ -63,30 +63,15 @@ class GoLSP(BaseLSP):
63
63
  "method": method,
64
64
  "params": params
65
65
  }
66
-
66
+
67
67
  self.gopls_process.stdin.write(json.dumps(request).encode() + b"\n") # type: ignore
68
68
  self.gopls_process.stdin.flush() # type: ignore
69
-
69
+
70
70
  response = json.loads(self.gopls_process.stdout.readline().decode()) # type: ignore
71
71
  return response.get("result")
72
72
  except Exception:
73
73
  return None
74
-
75
- def find_references(self, file_path: str, position: Tuple[int, int]) -> List[Dict[str, Any]]:
76
- result = self._send_request("textDocument/references", {
77
- "textDocument": {"uri": f"file://{file_path}"},
78
- "position": {"line": position[0], "character": position[1]},
79
- "context": {"includeDeclaration": True}
80
- })
81
- return result or [] # type: ignore
82
-
83
- def find_definition(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
84
- result = self._send_request("textDocument/definition", {
85
- "textDocument": {"uri": f"file://{file_path}"},
86
- "position": {"line": position[0], "character": position[1]}
87
- })
88
- return result[0] if result else None
89
-
74
+
90
75
  def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
91
76
  # Send didOpen notification to trigger diagnostics
92
77
  self._send_request("textDocument/didOpen", {
@@ -97,7 +82,7 @@ class GoLSP(BaseLSP):
97
82
  "text": open(file_path).read()
98
83
  }
99
84
  })
100
-
85
+
101
86
  # Wait for diagnostic notification
102
87
  try:
103
88
  response = json.loads(self.gopls_process.stdout.readline().decode()) # type: ignore
@@ -106,8 +91,8 @@ class GoLSP(BaseLSP):
106
91
  except Exception:
107
92
  pass
108
93
  return []
109
-
110
-
94
+
95
+
111
96
  def shutdown(self):
112
97
  if self.gopls_process:
113
98
  try:
@@ -4,17 +4,17 @@ from jarvis.jarvis_lsp.base import BaseLSP
4
4
 
5
5
  class PythonLSP(BaseLSP):
6
6
  """Python LSP implementation using jedi."""
7
-
7
+
8
8
  language = "python"
9
-
9
+
10
10
  def __init__(self):
11
11
  self.workspace_path = ""
12
12
  self.script_cache = {}
13
-
13
+
14
14
  def initialize(self, workspace_path: str) -> bool:
15
15
  self.workspace_path = workspace_path
16
16
  return True
17
-
17
+
18
18
  def _get_script(self, file_path: str):
19
19
  if file_path not in self.script_cache:
20
20
  try:
@@ -24,27 +24,8 @@ class PythonLSP(BaseLSP):
24
24
  except Exception:
25
25
  return None
26
26
  return self.script_cache[file_path]
27
-
28
- def find_references(self, file_path: str, position: Tuple[int, int]) -> List[Dict[str, Any]]:
29
- script = self._get_script(file_path)
30
- if not script:
31
- return []
32
- try:
33
- refs = script.get_references(line=position[0] + 1, column=position[1])
34
- return [self._location_to_dict(ref) for ref in refs]
35
- except Exception:
36
- return []
37
-
38
- def find_definition(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
39
- script = self._get_script(file_path)
40
- if not script:
41
- return None
42
- try:
43
- defs = script.goto(line=position[0] + 1, column=position[1])
44
- return self._location_to_dict(defs[0]) if defs else None
45
- except Exception:
46
- return None
47
-
27
+
28
+
48
29
  def _location_to_dict(self, location) -> Dict[str, Any]:
49
30
  return {
50
31
  "uri": location.module_path,
@@ -53,7 +34,7 @@ class PythonLSP(BaseLSP):
53
34
  "end": {"line": location.line - 1, "character": location.column + len(location.name)}
54
35
  }
55
36
  }
56
-
37
+
57
38
  def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
58
39
  script = self._get_script(file_path)
59
40
  if not script:
@@ -71,6 +52,6 @@ class PythonLSP(BaseLSP):
71
52
  } for e in errors]
72
53
  except Exception:
73
54
  return []
74
-
55
+
75
56
  def shutdown(self):
76
57
  self.script_cache.clear()
@@ -9,8 +9,6 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
9
 
10
10
  REQUIRED_METHODS = [
11
11
  ('initialize', ['workspace_path']),
12
- ('find_references', ['file_path', 'position']),
13
- ('find_definition', ['file_path', 'position']),
14
12
  ('get_diagnostics', ['file_path']),
15
13
  ('shutdown', [])
16
14
  ]
@@ -38,47 +36,47 @@ class LSPRegistry:
38
36
  def check_lsp_implementation(lsp_class: Type[BaseLSP]) -> bool:
39
37
  """Check if the LSP class implements all necessary methods."""
40
38
  missing_methods = []
41
-
39
+
42
40
  for method_name, params in REQUIRED_METHODS:
43
41
  if not hasattr(lsp_class, method_name):
44
42
  missing_methods.append(method_name)
45
43
  continue
46
-
44
+
47
45
  method = getattr(lsp_class, method_name)
48
46
  if not callable(method):
49
47
  missing_methods.append(method_name)
50
48
  continue
51
-
49
+
52
50
  sig = inspect.signature(method)
53
51
  method_params = [p for p in sig.parameters if p != 'self']
54
52
  if len(method_params) != len(params):
55
53
  missing_methods.append(f"{method_name}(parameter mismatch)")
56
-
54
+
57
55
  if missing_methods:
58
56
  PrettyOutput.print(
59
- f"LSP {lsp_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
57
+ f"LSP {lsp_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
60
58
  OutputType.WARNING
61
59
  )
62
60
  return False
63
-
61
+
64
62
  return True
65
63
 
66
64
  @staticmethod
67
65
  def load_lsp_from_dir(directory: str) -> Dict[str, Type[BaseLSP]]:
68
66
  """Load LSP implementations from specified directory."""
69
67
  lsp_servers = {}
70
-
68
+
71
69
  if not os.path.exists(directory):
72
70
  PrettyOutput.print(f"LSP 目录不存在: {directory}", OutputType.WARNING)
73
71
  return lsp_servers
74
-
72
+
75
73
  package_name = None
76
74
  if directory == os.path.dirname(__file__):
77
75
  package_name = "jarvis.jarvis_lsp"
78
-
76
+
79
77
  if directory not in sys.path:
80
78
  sys.path.append(directory)
81
-
79
+
82
80
  for filename in os.listdir(directory):
83
81
  if filename.endswith('.py') and not filename.startswith('__'):
84
82
  module_name = filename[:-3]
@@ -87,10 +85,10 @@ class LSPRegistry:
87
85
  module = importlib.import_module(f"{package_name}.{module_name}")
88
86
  else:
89
87
  module = importlib.import_module(module_name)
90
-
88
+
91
89
  for _, obj in inspect.getmembers(module):
92
- if (inspect.isclass(obj) and
93
- issubclass(obj, BaseLSP) and
90
+ if (inspect.isclass(obj) and
91
+ issubclass(obj, BaseLSP) and
94
92
  obj != BaseLSP and
95
93
  hasattr(obj, 'language')):
96
94
  if not LSPRegistry.check_lsp_implementation(obj):
@@ -106,7 +104,7 @@ class LSPRegistry:
106
104
  break
107
105
  except Exception as e:
108
106
  PrettyOutput.print(f"加载 LSP {module_name} 失败: {str(e)}", OutputType.ERROR)
109
-
107
+
110
108
  return lsp_servers
111
109
 
112
110
  @staticmethod
@@ -115,17 +113,17 @@ class LSPRegistry:
115
113
  if LSPRegistry.global_lsp_registry is None:
116
114
  LSPRegistry.global_lsp_registry = LSPRegistry()
117
115
  return LSPRegistry.global_lsp_registry
118
-
116
+
119
117
  def __init__(self):
120
118
  """Initialize LSP registry."""
121
119
  self.lsp_servers: Dict[str, Type[BaseLSP]] = {}
122
-
120
+
123
121
  # Load from user LSP directory
124
122
  lsp_dir = LSPRegistry.get_lsp_dir()
125
123
  if lsp_dir and os.path.exists(lsp_dir):
126
124
  for language, lsp_class in LSPRegistry.load_lsp_from_dir(lsp_dir).items():
127
125
  self.register_lsp(language, lsp_class)
128
-
126
+
129
127
  # Load from built-in LSP directory
130
128
  lsp_dir = os.path.dirname(__file__)
131
129
  if lsp_dir and os.path.exists(lsp_dir):
@@ -135,13 +133,13 @@ class LSPRegistry:
135
133
  def register_lsp(self, language: str, lsp_class: Type[BaseLSP]):
136
134
  """Register LSP implementation for a language."""
137
135
  self.lsp_servers[language] = lsp_class
138
-
136
+
139
137
  def create_lsp(self, language: str) -> Optional[BaseLSP]:
140
138
  """Create LSP instance for specified language."""
141
139
  if language not in self.lsp_servers:
142
140
  PrettyOutput.print(f"没有找到 LSP 支持的语言: {language}", OutputType.WARNING)
143
141
  return None
144
-
142
+
145
143
  try:
146
144
  lsp = self.lsp_servers[language]()
147
145
  return lsp
@@ -152,7 +150,7 @@ class LSPRegistry:
152
150
  def get_supported_languages(self) -> List[str]:
153
151
  """Get list of supported languages."""
154
152
  return list(self.lsp_servers.keys())
155
-
153
+
156
154
  @staticmethod
157
155
  def get_text_at_position(file_path: str, line: int, start_character: int) -> str:
158
156
  """Get text at position."""
@@ -160,70 +158,10 @@ class LSPRegistry:
160
158
  lines = file.readlines()
161
159
  symbol = re.search(r'\b\w+\b', lines[line][start_character:])
162
160
  return symbol.group() if symbol else ""
163
-
161
+
164
162
  @staticmethod
165
163
  def get_line_at_position(file_path: str, line: int) -> str:
166
164
  """Get line at position."""
167
165
  with open(file_path, 'r', errors="ignore") as file:
168
166
  lines = file.readlines()
169
167
  return lines[line]
170
-
171
- def main():
172
- """CLI entry point for LSP testing."""
173
- import argparse
174
-
175
- parser = argparse.ArgumentParser(description='LSP functionality testing')
176
- parser.add_argument('--language', type=str, required=True, help='Programming language')
177
- parser.add_argument('--file', type=str, required=True, help='File to analyze')
178
- parser.add_argument('--action', choices=['symbols', 'diagnostics', 'references', 'definition'],
179
- required=True, help='Action to perform')
180
- parser.add_argument('--line', type=int, help='Line number (0-based) for references/definition')
181
- parser.add_argument('--character', type=int, help='Character position for references/definition')
182
-
183
- args = parser.parse_args()
184
-
185
- # Initialize LSP
186
- registry = LSPRegistry.get_global_lsp_registry()
187
- lsp = registry.create_lsp(args.language)
188
-
189
- if not lsp:
190
- PrettyOutput.print(f"没有 LSP 支持的语言: {args.language}", OutputType.WARNING)
191
- return 1
192
-
193
- if not lsp.initialize(os.path.abspath(os.getcwd())):
194
- PrettyOutput.print("LSP 初始化失败", OutputType.WARNING)
195
- return 1
196
-
197
- try:
198
- if args.action == 'diagnostics':
199
- diagnostics = lsp.get_diagnostics(args.file)
200
- for diag in diagnostics:
201
- severity = ['Error', 'Warning', 'Info', 'Hint'][diag['severity'] - 1]
202
- PrettyOutput.print(f"{severity} 在 {diag['range']['start']['line']}:{diag['range']['start']['character']}: {diag['message']}", OutputType.INFO)
203
-
204
- elif args.action in ('references', 'definition'):
205
- if args.line is None or args.character is None:
206
- PrettyOutput.print("需要行和字符位置用于 references/definition", OutputType.WARNING)
207
- return 1
208
-
209
- if args.action == 'references':
210
- refs = lsp.find_references(args.file, (args.line, args.character))
211
- for ref in refs:
212
- PrettyOutput.print(f"引用在 {ref['uri']} 在 {ref['range']['start']['line']}:{ref['range']['start']['character']}\n行: {LSPRegistry.get_line_at_position(ref['uri'], ref['range']['start']['line'])}", OutputType.INFO)
213
- else:
214
- defn = lsp.find_definition(args.file, (args.line, args.character))
215
- if defn:
216
- PrettyOutput.print(f"定义在 {defn['uri']} 在 {defn['range']['start']['line']}:{defn['range']['start']['character']}\n行: {LSPRegistry.get_line_at_position(defn['uri'], defn['range']['start']['line'])}", OutputType.INFO)
217
- else:
218
- PrettyOutput.print("没有找到定义", OutputType.WARNING)
219
-
220
- except Exception as e:
221
- PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
222
- return 1
223
- finally:
224
- lsp.shutdown()
225
-
226
- return 0
227
-
228
- if __name__ == "__main__":
229
- exit(main())
jarvis/jarvis_lsp/rust.py CHANGED
@@ -8,19 +8,19 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
8
 
9
9
  class RustLSP(BaseLSP):
10
10
  """Rust LSP implementation using rust-analyzer."""
11
-
11
+
12
12
  language = "rust"
13
-
13
+
14
14
  @staticmethod
15
15
  def check() -> bool:
16
16
  """Check if rust-analyzer is installed."""
17
17
  return shutil.which("rust-analyzer") is not None
18
-
18
+
19
19
  def __init__(self):
20
20
  self.workspace_path = ""
21
21
  self.analyzer_process = None
22
22
  self.request_id = 0
23
-
23
+
24
24
  def initialize(self, workspace_path: str) -> bool:
25
25
  try:
26
26
  self.workspace_path = workspace_path
@@ -31,7 +31,7 @@ class RustLSP(BaseLSP):
31
31
  stdout=subprocess.PIPE,
32
32
  stderr=subprocess.PIPE
33
33
  )
34
-
34
+
35
35
  # Send initialize request
36
36
  self._send_request("initialize", {
37
37
  "processId": os.getpid(),
@@ -46,17 +46,17 @@ class RustLSP(BaseLSP):
46
46
  },
47
47
  "workspaceFolders": [{"uri": f"file://{workspace_path}", "name": "workspace"}]
48
48
  })
49
-
49
+
50
50
  return True
51
51
  except Exception as e:
52
52
  PrettyOutput.print(f"Rust LSP 初始化失败: {str(e)}", OutputType.ERROR)
53
53
  return False
54
-
54
+
55
55
  def _send_request(self, method: str, params: Dict) -> Optional[Dict]:
56
56
  """Send JSON-RPC request to rust-analyzer."""
57
57
  if not self.analyzer_process:
58
58
  return None
59
-
59
+
60
60
  try:
61
61
  self.request_id += 1
62
62
  request = {
@@ -65,31 +65,16 @@ class RustLSP(BaseLSP):
65
65
  "method": method,
66
66
  "params": params
67
67
  }
68
-
68
+
69
69
  self.analyzer_process.stdin.write(json.dumps(request).encode() + b"\n") # type: ignore
70
70
  self.analyzer_process.stdin.flush() # type: ignore
71
-
71
+
72
72
  response = json.loads(self.analyzer_process.stdout.readline().decode()) # type: ignore
73
73
  return response.get("result")
74
74
  except Exception:
75
75
  return None
76
-
77
- def find_references(self, file_path: str, position: Tuple[int, int]) -> List[Dict[str, Any]]:
78
- result = self._send_request("textDocument/references", {
79
- "textDocument": {"uri": f"file://{file_path}"},
80
- "position": {"line": position[0], "character": position[1]},
81
- "context": {"includeDeclaration": True}
82
- })
83
- return result or [] # type: ignore
84
-
85
- def find_definition(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
86
- result = self._send_request("textDocument/definition", {
87
- "textDocument": {"uri": f"file://{file_path}"},
88
- "position": {"line": position[0], "character": position[1]}
89
- })
90
- return result[0] if result else None
91
-
92
-
76
+
77
+
93
78
  def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
94
79
  # Send didOpen notification to trigger diagnostics
95
80
  self._send_request("textDocument/didOpen", {
@@ -100,7 +85,7 @@ class RustLSP(BaseLSP):
100
85
  "text": open(file_path).read()
101
86
  }
102
87
  })
103
-
88
+
104
89
  # Wait for diagnostic notification
105
90
  try:
106
91
  response = json.loads(self.analyzer_process.stdout.readline().decode()) # type: ignore
@@ -109,8 +94,8 @@ class RustLSP(BaseLSP):
109
94
  except Exception:
110
95
  pass
111
96
  return []
112
-
113
-
97
+
98
+
114
99
  def shutdown(self):
115
100
  if self.analyzer_process:
116
101
  try: