jarvis-ai-assistant 0.7.0__py3-none-any.whl → 0.7.8__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.
Files changed (159) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +243 -139
  3. jarvis/jarvis_agent/agent_manager.py +5 -10
  4. jarvis/jarvis_agent/builtin_input_handler.py +2 -6
  5. jarvis/jarvis_agent/config_editor.py +2 -7
  6. jarvis/jarvis_agent/event_bus.py +82 -12
  7. jarvis/jarvis_agent/file_context_handler.py +265 -15
  8. jarvis/jarvis_agent/file_methodology_manager.py +3 -4
  9. jarvis/jarvis_agent/jarvis.py +113 -98
  10. jarvis/jarvis_agent/language_extractors/__init__.py +57 -0
  11. jarvis/jarvis_agent/language_extractors/c_extractor.py +21 -0
  12. jarvis/jarvis_agent/language_extractors/cpp_extractor.py +21 -0
  13. jarvis/jarvis_agent/language_extractors/go_extractor.py +21 -0
  14. jarvis/jarvis_agent/language_extractors/java_extractor.py +84 -0
  15. jarvis/jarvis_agent/language_extractors/javascript_extractor.py +79 -0
  16. jarvis/jarvis_agent/language_extractors/python_extractor.py +21 -0
  17. jarvis/jarvis_agent/language_extractors/rust_extractor.py +21 -0
  18. jarvis/jarvis_agent/language_extractors/typescript_extractor.py +84 -0
  19. jarvis/jarvis_agent/language_support_info.py +486 -0
  20. jarvis/jarvis_agent/main.py +6 -12
  21. jarvis/jarvis_agent/memory_manager.py +7 -16
  22. jarvis/jarvis_agent/methodology_share_manager.py +10 -16
  23. jarvis/jarvis_agent/prompt_manager.py +1 -1
  24. jarvis/jarvis_agent/prompts.py +193 -171
  25. jarvis/jarvis_agent/protocols.py +8 -12
  26. jarvis/jarvis_agent/run_loop.py +77 -14
  27. jarvis/jarvis_agent/session_manager.py +2 -3
  28. jarvis/jarvis_agent/share_manager.py +12 -21
  29. jarvis/jarvis_agent/shell_input_handler.py +1 -2
  30. jarvis/jarvis_agent/task_analyzer.py +26 -4
  31. jarvis/jarvis_agent/task_manager.py +11 -27
  32. jarvis/jarvis_agent/tool_executor.py +2 -3
  33. jarvis/jarvis_agent/tool_share_manager.py +12 -24
  34. jarvis/jarvis_agent/web_server.py +55 -20
  35. jarvis/jarvis_c2rust/__init__.py +5 -5
  36. jarvis/jarvis_c2rust/cli.py +461 -499
  37. jarvis/jarvis_c2rust/collector.py +45 -53
  38. jarvis/jarvis_c2rust/constants.py +26 -0
  39. jarvis/jarvis_c2rust/library_replacer.py +264 -132
  40. jarvis/jarvis_c2rust/llm_module_agent.py +162 -190
  41. jarvis/jarvis_c2rust/loaders.py +207 -0
  42. jarvis/jarvis_c2rust/models.py +28 -0
  43. jarvis/jarvis_c2rust/optimizer.py +1592 -395
  44. jarvis/jarvis_c2rust/transpiler.py +1722 -1064
  45. jarvis/jarvis_c2rust/utils.py +385 -0
  46. jarvis/jarvis_code_agent/build_validation_config.py +2 -3
  47. jarvis/jarvis_code_agent/code_agent.py +394 -320
  48. jarvis/jarvis_code_agent/code_analyzer/__init__.py +3 -0
  49. jarvis/jarvis_code_agent/code_analyzer/build_validator/base.py +4 -0
  50. jarvis/jarvis_code_agent/code_analyzer/build_validator/cmake.py +17 -2
  51. jarvis/jarvis_code_agent/code_analyzer/build_validator/fallback.py +3 -0
  52. jarvis/jarvis_code_agent/code_analyzer/build_validator/go.py +36 -4
  53. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_gradle.py +9 -0
  54. jarvis/jarvis_code_agent/code_analyzer/build_validator/java_maven.py +9 -0
  55. jarvis/jarvis_code_agent/code_analyzer/build_validator/makefile.py +12 -1
  56. jarvis/jarvis_code_agent/code_analyzer/build_validator/nodejs.py +22 -5
  57. jarvis/jarvis_code_agent/code_analyzer/build_validator/python.py +57 -32
  58. jarvis/jarvis_code_agent/code_analyzer/build_validator/rust.py +62 -6
  59. jarvis/jarvis_code_agent/code_analyzer/build_validator/validator.py +8 -9
  60. jarvis/jarvis_code_agent/code_analyzer/context_manager.py +290 -5
  61. jarvis/jarvis_code_agent/code_analyzer/language_support.py +21 -0
  62. jarvis/jarvis_code_agent/code_analyzer/languages/__init__.py +21 -3
  63. jarvis/jarvis_code_agent/code_analyzer/languages/c_cpp_language.py +72 -4
  64. jarvis/jarvis_code_agent/code_analyzer/languages/go_language.py +35 -3
  65. jarvis/jarvis_code_agent/code_analyzer/languages/java_language.py +212 -0
  66. jarvis/jarvis_code_agent/code_analyzer/languages/javascript_language.py +254 -0
  67. jarvis/jarvis_code_agent/code_analyzer/languages/python_language.py +52 -2
  68. jarvis/jarvis_code_agent/code_analyzer/languages/rust_language.py +73 -1
  69. jarvis/jarvis_code_agent/code_analyzer/languages/typescript_language.py +280 -0
  70. jarvis/jarvis_code_agent/code_analyzer/llm_context_recommender.py +306 -152
  71. jarvis/jarvis_code_agent/code_analyzer/structured_code.py +556 -0
  72. jarvis/jarvis_code_agent/code_analyzer/symbol_extractor.py +193 -18
  73. jarvis/jarvis_code_agent/code_analyzer/tree_sitter_extractor.py +18 -8
  74. jarvis/jarvis_code_agent/lint.py +258 -27
  75. jarvis/jarvis_code_agent/utils.py +0 -1
  76. jarvis/jarvis_code_analysis/code_review.py +19 -24
  77. jarvis/jarvis_data/config_schema.json +53 -26
  78. jarvis/jarvis_git_squash/main.py +4 -5
  79. jarvis/jarvis_git_utils/git_commiter.py +44 -49
  80. jarvis/jarvis_mcp/sse_mcp_client.py +20 -27
  81. jarvis/jarvis_mcp/stdio_mcp_client.py +11 -12
  82. jarvis/jarvis_mcp/streamable_mcp_client.py +15 -14
  83. jarvis/jarvis_memory_organizer/memory_organizer.py +55 -74
  84. jarvis/jarvis_methodology/main.py +32 -48
  85. jarvis/jarvis_multi_agent/__init__.py +79 -61
  86. jarvis/jarvis_multi_agent/main.py +3 -7
  87. jarvis/jarvis_platform/base.py +469 -199
  88. jarvis/jarvis_platform/human.py +7 -8
  89. jarvis/jarvis_platform/kimi.py +30 -36
  90. jarvis/jarvis_platform/openai.py +65 -27
  91. jarvis/jarvis_platform/registry.py +26 -10
  92. jarvis/jarvis_platform/tongyi.py +24 -25
  93. jarvis/jarvis_platform/yuanbao.py +31 -42
  94. jarvis/jarvis_platform_manager/main.py +66 -77
  95. jarvis/jarvis_platform_manager/service.py +8 -13
  96. jarvis/jarvis_rag/cli.py +49 -51
  97. jarvis/jarvis_rag/embedding_manager.py +13 -18
  98. jarvis/jarvis_rag/llm_interface.py +8 -9
  99. jarvis/jarvis_rag/query_rewriter.py +10 -21
  100. jarvis/jarvis_rag/rag_pipeline.py +24 -27
  101. jarvis/jarvis_rag/reranker.py +4 -5
  102. jarvis/jarvis_rag/retriever.py +28 -30
  103. jarvis/jarvis_sec/__init__.py +220 -3520
  104. jarvis/jarvis_sec/agents.py +143 -0
  105. jarvis/jarvis_sec/analysis.py +276 -0
  106. jarvis/jarvis_sec/cli.py +29 -6
  107. jarvis/jarvis_sec/clustering.py +1439 -0
  108. jarvis/jarvis_sec/file_manager.py +427 -0
  109. jarvis/jarvis_sec/parsers.py +73 -0
  110. jarvis/jarvis_sec/prompts.py +268 -0
  111. jarvis/jarvis_sec/report.py +83 -4
  112. jarvis/jarvis_sec/review.py +453 -0
  113. jarvis/jarvis_sec/utils.py +499 -0
  114. jarvis/jarvis_sec/verification.py +848 -0
  115. jarvis/jarvis_sec/workflow.py +7 -0
  116. jarvis/jarvis_smart_shell/main.py +38 -87
  117. jarvis/jarvis_stats/cli.py +1 -1
  118. jarvis/jarvis_stats/stats.py +7 -7
  119. jarvis/jarvis_stats/storage.py +15 -21
  120. jarvis/jarvis_tools/clear_memory.py +3 -20
  121. jarvis/jarvis_tools/cli/main.py +20 -23
  122. jarvis/jarvis_tools/edit_file.py +1066 -0
  123. jarvis/jarvis_tools/execute_script.py +42 -21
  124. jarvis/jarvis_tools/file_analyzer.py +6 -9
  125. jarvis/jarvis_tools/generate_new_tool.py +11 -20
  126. jarvis/jarvis_tools/lsp_client.py +1552 -0
  127. jarvis/jarvis_tools/methodology.py +2 -3
  128. jarvis/jarvis_tools/read_code.py +1525 -87
  129. jarvis/jarvis_tools/read_symbols.py +2 -3
  130. jarvis/jarvis_tools/read_webpage.py +7 -10
  131. jarvis/jarvis_tools/registry.py +370 -181
  132. jarvis/jarvis_tools/retrieve_memory.py +20 -19
  133. jarvis/jarvis_tools/rewrite_file.py +105 -0
  134. jarvis/jarvis_tools/save_memory.py +3 -15
  135. jarvis/jarvis_tools/search_web.py +3 -7
  136. jarvis/jarvis_tools/sub_agent.py +17 -6
  137. jarvis/jarvis_tools/sub_code_agent.py +14 -16
  138. jarvis/jarvis_tools/virtual_tty.py +54 -32
  139. jarvis/jarvis_utils/clipboard.py +7 -10
  140. jarvis/jarvis_utils/config.py +98 -63
  141. jarvis/jarvis_utils/embedding.py +5 -5
  142. jarvis/jarvis_utils/fzf.py +8 -8
  143. jarvis/jarvis_utils/git_utils.py +81 -67
  144. jarvis/jarvis_utils/input.py +24 -49
  145. jarvis/jarvis_utils/jsonnet_compat.py +465 -0
  146. jarvis/jarvis_utils/methodology.py +33 -35
  147. jarvis/jarvis_utils/utils.py +245 -202
  148. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/METADATA +205 -70
  149. jarvis_ai_assistant-0.7.8.dist-info/RECORD +218 -0
  150. jarvis/jarvis_agent/edit_file_handler.py +0 -584
  151. jarvis/jarvis_agent/rewrite_file_handler.py +0 -141
  152. jarvis/jarvis_agent/task_planner.py +0 -496
  153. jarvis/jarvis_platform/ai8.py +0 -332
  154. jarvis/jarvis_tools/ask_user.py +0 -54
  155. jarvis_ai_assistant-0.7.0.dist-info/RECORD +0 -192
  156. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/WHEEL +0 -0
  157. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/entry_points.txt +0 -0
  158. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/licenses/LICENSE +0 -0
  159. {jarvis_ai_assistant-0.7.0.dist-info → jarvis_ai_assistant-0.7.8.dist-info}/top_level.txt +0 -0
@@ -1,34 +1,155 @@
1
+ import json
2
+ import os
1
3
  from dataclasses import dataclass
2
-
3
4
  from typing import Dict, List, Optional
4
5
 
5
6
 
6
7
  @dataclass
7
8
  class Symbol:
8
- """Represents a single symbol in the code."""
9
+ """表示代码中的单个符号。"""
9
10
  name: str
10
- kind: str # e.g., 'function', 'class', 'variable', 'import'
11
+ kind: str # 例如:'function'(函数)、'class'(类)、'variable'(变量)、'import'(导入)
11
12
  file_path: str
12
13
  line_start: int
13
14
  line_end: int
14
15
  signature: Optional[str] = None
15
16
  docstring: Optional[str] = None
16
- # Add more fields as needed, e.g., parent scope
17
+ # 根据需要添加更多字段,例如父作用域
17
18
  parent: Optional[str] = None
19
+ # 定义位置(对于引用/调用,指向符号定义的位置)
20
+ definition_location: Optional['Symbol'] = None # 指向定义Symbol的引用
21
+ is_definition: bool = False # 如果此符号是定义则为True,如果是引用/调用则为False
18
22
 
19
23
 
20
24
  class SymbolTable:
21
- """Stores and provides access to symbols across a project."""
25
+ """存储并提供对项目中符号的访问。"""
22
26
 
23
- def __init__(self):
24
- # A dictionary to store symbols by their name for quick lookups.
25
- # A symbol name can appear in multiple files, so it's a list.
27
+ def __init__(self, cache_dir: Optional[str] = None):
28
+ # 按名称存储符号的字典,用于快速查找
29
+ # 一个符号名可能出现在多个文件中,因此使用列表存储
26
30
  self.symbols_by_name: Dict[str, List[Symbol]] = {}
27
- # A dictionary to store symbols on a per-file basis.
31
+ # 按文件存储符号的字典
28
32
  self.symbols_by_file: Dict[str, List[Symbol]] = {}
33
+ # 跟踪文件修改时间用于缓存失效
34
+ self._file_mtimes: Dict[str, float] = {}
35
+ # 持久化存储的缓存目录
36
+ self.cache_dir = cache_dir or ".jarvis/symbol_cache"
37
+ # 如果可用则加载缓存数据
38
+ self._load_from_cache()
39
+
40
+ def _get_cache_file(self) -> str:
41
+ """获取缓存文件路径。"""
42
+ return os.path.join(self.cache_dir, "symbol_table.json")
43
+
44
+ def _load_from_cache(self):
45
+ """从缓存文件加载符号表数据。"""
46
+ cache_file = self._get_cache_file()
47
+ if os.path.exists(cache_file):
48
+ try:
49
+ with open(cache_file, 'r', encoding='utf-8') as f:
50
+ data = json.load(f)
51
+ # 将JSON数据转换回Symbol对象
52
+ self.symbols_by_name = self._deserialize_symbols(data.get('symbols_by_name', {}))
53
+ self.symbols_by_file = self._deserialize_symbols(data.get('symbols_by_file', {}))
54
+ # 加载文件修改时间
55
+ self._file_mtimes = data.get('file_mtimes', {})
56
+ except Exception:
57
+ # 如果缓存加载失败,则从空表开始
58
+ pass
59
+
60
+ def _save_to_cache(self):
61
+ """将符号表数据保存到缓存文件。"""
62
+ try:
63
+ # 确保缓存目录存在
64
+ os.makedirs(self.cache_dir, exist_ok=True)
65
+ cache_file = self._get_cache_file()
66
+
67
+ # 保存前更新文件修改时间
68
+ self._update_file_mtimes()
69
+
70
+ # 序列化符号以便JSON存储
71
+ data = {
72
+ 'symbols_by_name': self._serialize_symbols(self.symbols_by_name),
73
+ 'symbols_by_file': self._serialize_symbols(self.symbols_by_file),
74
+ 'file_mtimes': self._file_mtimes
75
+ }
76
+
77
+ with open(cache_file, 'w', encoding='utf-8') as f:
78
+ json.dump(data, f, indent=2, ensure_ascii=False)
79
+ except Exception:
80
+ # 如果缓存保存失败,则继续而不缓存
81
+ pass
82
+
83
+ def _serialize_symbols(self, symbol_dict: Dict[str, List[Symbol]]) -> Dict[str, List[dict]]:
84
+ """将Symbol对象转换为可序列化的字典。"""
85
+ serialized = {}
86
+ for key, symbols in symbol_dict.items():
87
+ serialized[key] = [self._symbol_to_dict(symbol) for symbol in symbols]
88
+ return serialized
29
89
 
30
- def add_symbol(self, symbol: Symbol):
31
- """Adds a symbol to the table."""
90
+ def _deserialize_symbols(self, symbol_dict: Dict[str, List[dict]]) -> Dict[str, List[Symbol]]:
91
+ """将序列化的字典转换回Symbol对象。"""
92
+ deserialized = {}
93
+ for key, symbol_data_list in symbol_dict.items():
94
+ deserialized[key] = [self._dict_to_symbol(data) for data in symbol_data_list]
95
+ return deserialized
96
+
97
+ def _symbol_to_dict(self, symbol: Symbol) -> dict:
98
+ """将Symbol对象转换为字典。"""
99
+ result = {
100
+ 'name': symbol.name,
101
+ 'kind': symbol.kind,
102
+ 'file_path': symbol.file_path,
103
+ 'line_start': symbol.line_start,
104
+ 'line_end': symbol.line_end,
105
+ 'signature': symbol.signature,
106
+ 'docstring': symbol.docstring,
107
+ 'parent': symbol.parent,
108
+ 'is_definition': getattr(symbol, 'is_definition', False),
109
+ }
110
+ # 序列化定义位置(只保存基本信息,避免循环引用)
111
+ if hasattr(symbol, 'definition_location') and symbol.definition_location:
112
+ result['definition_location'] = {
113
+ 'file_path': symbol.definition_location.file_path,
114
+ 'line_start': symbol.definition_location.line_start,
115
+ 'line_end': symbol.definition_location.line_end,
116
+ 'name': symbol.definition_location.name,
117
+ }
118
+ return result
119
+
120
+ def _dict_to_symbol(self, data: dict) -> Symbol:
121
+ """将字典转换回Symbol对象。"""
122
+ symbol = Symbol(
123
+ name=data['name'],
124
+ kind=data['kind'],
125
+ file_path=data['file_path'],
126
+ line_start=data['line_start'],
127
+ line_end=data['line_end'],
128
+ signature=data.get('signature'),
129
+ docstring=data.get('docstring'),
130
+ parent=data.get('parent'),
131
+ is_definition=data.get('is_definition', False),
132
+ )
133
+ # 恢复定义位置(创建临时 Symbol 对象)
134
+ if 'definition_location' in data and data['definition_location']:
135
+ def_loc = data['definition_location']
136
+ symbol.definition_location = Symbol(
137
+ name=def_loc['name'],
138
+ kind='', # 未知类型
139
+ file_path=def_loc['file_path'],
140
+ line_start=def_loc['line_start'],
141
+ line_end=def_loc['line_end'],
142
+ )
143
+ return symbol
144
+
145
+ def add_symbol(self, symbol: Symbol, save_to_cache: bool = False):
146
+ """向表中添加符号。
147
+
148
+ 参数:
149
+ symbol: 要添加的符号
150
+ save_to_cache: 如果为True,立即保存到缓存。默认为False以提高性能。
151
+ 批量操作后使用save_cache()一次性保存所有符号。
152
+ """
32
153
  if symbol.name not in self.symbols_by_name:
33
154
  self.symbols_by_name[symbol.name] = []
34
155
  self.symbols_by_name[symbol.name].append(symbol)
@@ -36,11 +157,19 @@ class SymbolTable:
36
157
  if symbol.file_path not in self.symbols_by_file:
37
158
  self.symbols_by_file[symbol.file_path] = []
38
159
  self.symbols_by_file[symbol.file_path].append(symbol)
160
+
161
+ # 仅在明确请求时保存到缓存(出于性能考虑)
162
+ if save_to_cache:
163
+ self._save_to_cache()
164
+
165
+ def save_cache(self):
166
+ """将整个符号表保存到缓存。批量操作后调用此方法。"""
167
+ self._save_to_cache()
39
168
 
40
169
  def find_symbol(self, name: str, file_path: Optional[str] = None) -> List[Symbol]:
41
170
  """
42
- Finds a symbol by name.
43
- If file_path is provided, the search is limited to that file.
171
+ 通过名称查找符号。
172
+ 如果提供了file_path,则搜索仅限于该文件。
44
173
  """
45
174
  if file_path:
46
175
  return [
@@ -49,11 +178,11 @@ class SymbolTable:
49
178
  return self.symbols_by_name.get(name, [])
50
179
 
51
180
  def get_file_symbols(self, file_path: str) -> List[Symbol]:
52
- """Gets all symbols within a specific file."""
181
+ """获取特定文件中的所有符号。"""
53
182
  return self.symbols_by_file.get(file_path, [])
54
183
 
55
184
  def clear_file_symbols(self, file_path: str):
56
- """Removes all symbols associated with a specific file."""
185
+ """移除与特定文件关联的所有符号。"""
57
186
  if file_path in self.symbols_by_file:
58
187
  symbols_to_remove = self.symbols_by_file.pop(file_path)
59
188
  for symbol in symbols_to_remove:
@@ -64,14 +193,60 @@ class SymbolTable:
64
193
  ]
65
194
  if not self.symbols_by_name[symbol.name]:
66
195
  del self.symbols_by_name[symbol.name]
196
+
197
+ # 移除文件修改时间跟踪
198
+ if file_path in self._file_mtimes:
199
+ del self._file_mtimes[file_path]
200
+
201
+ # 清除后保存到缓存
202
+ self._save_to_cache()
203
+
204
+ def _update_file_mtimes(self):
205
+ """更新所有跟踪文件的修改时间。"""
206
+ for file_path in list(self.symbols_by_file.keys()):
207
+ if os.path.exists(file_path):
208
+ try:
209
+ self._file_mtimes[file_path] = os.path.getmtime(file_path)
210
+ except Exception:
211
+ # 如果无法获取修改时间,则从跟踪中移除
212
+ self._file_mtimes.pop(file_path, None)
213
+
214
+ def is_file_stale(self, file_path: str) -> bool:
215
+ """检查文件自缓存后是否已被修改。
216
+
217
+ 参数:
218
+ file_path: 要检查的文件路径
219
+
220
+ 返回:
221
+ 如果文件比缓存新则为True,否则为False
222
+ """
223
+ if file_path not in self.symbols_by_file:
224
+ # 文件不在缓存中,视为已过期(需要加载)
225
+ return True
226
+
227
+ if file_path not in self._file_mtimes:
228
+ # 没有记录修改时间,视为已过期
229
+ return True
230
+
231
+ if not os.path.exists(file_path):
232
+ # 文件不存在,不算过期(将由clear_file_symbols处理)
233
+ return False
234
+
235
+ try:
236
+ current_mtime = os.path.getmtime(file_path)
237
+ cached_mtime = self._file_mtimes.get(file_path, 0)
238
+ return current_mtime > cached_mtime
239
+ except Exception:
240
+ # 如果无法获取修改时间,则假定未过期
241
+ return False
67
242
 
68
243
 
69
244
  class SymbolExtractor:
70
- """Extracts symbols from a source code file."""
245
+ """从源代码文件中提取符号。"""
71
246
 
72
247
  def extract_symbols(self, file_path: str, content: str) -> List[Symbol]:
73
248
  """
74
- Extracts symbols (functions, classes, variables, etc.) from the code.
75
- This method should be implemented by language-specific subclasses.
249
+ 从代码中提取符号(函数、类、变量等)。
250
+ 此方法应由特定语言的子类实现。
76
251
  """
77
252
  raise NotImplementedError("Subclasses must implement this method.")
@@ -1,7 +1,7 @@
1
1
  from abc import abstractmethod
2
2
  from typing import List, Optional
3
3
 
4
- from tree_sitter import Language, Parser, Node
4
+ from tree_sitter import Language, Parser, Node, Query, QueryCursor
5
5
 
6
6
  from .symbol_extractor import Symbol, SymbolExtractor
7
7
 
@@ -14,9 +14,13 @@ class TreeSitterExtractor(SymbolExtractor):
14
14
  """
15
15
 
16
16
  def __init__(self, language: Language, symbol_query: str):
17
+ # 如果传入的是 PyCapsule,需要转换为 Language 对象
18
+ if not isinstance(language, Language):
19
+ language = Language(language)
17
20
  self.language = language
18
21
  self.parser = Parser()
19
- self.parser.set_language(self.language)
22
+ # 使用 language 属性而不是 set_language 方法
23
+ self.parser.language = self.language
20
24
  self.symbol_query = symbol_query
21
25
 
22
26
  def extract_symbols(self, file_path: str, content: str) -> List[Symbol]:
@@ -25,14 +29,20 @@ class TreeSitterExtractor(SymbolExtractor):
25
29
  """
26
30
  try:
27
31
  tree = self.parser.parse(bytes(content, "utf8"))
28
- query = self.language.query(self.symbol_query)
29
- captures = query.captures(tree.root_node)
32
+ # 使用 Query 构造函数(新 API)
33
+ query = Query(self.language, self.symbol_query)
34
+ # 使用 QueryCursor 执行查询
35
+ cursor = QueryCursor(query)
36
+ matches = cursor.matches(tree.root_node)
30
37
 
31
38
  symbols = []
32
- for node, name in captures:
33
- symbol = self._create_symbol_from_capture(node, name, file_path)
34
- if symbol:
35
- symbols.append(symbol)
39
+ # matches 返回格式: [(pattern_index, {capture_name: [nodes]})]
40
+ for pattern_index, captures_dict in matches:
41
+ for capture_name, nodes in captures_dict.items():
42
+ for node in nodes:
43
+ symbol = self._create_symbol_from_capture(node, capture_name, file_path)
44
+ if symbol:
45
+ symbols.append(symbol)
36
46
  return symbols
37
47
  except Exception as e:
38
48
  print(f"Error extracting symbols from {file_path} with tree-sitter: {e}")