jarvis-ai-assistant 0.1.130__py3-none-any.whl → 0.1.132__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 (72) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +71 -38
  3. jarvis/jarvis_agent/builtin_input_handler.py +73 -0
  4. jarvis/{jarvis_code_agent → jarvis_agent}/file_input_handler.py +1 -1
  5. jarvis/jarvis_agent/main.py +1 -1
  6. jarvis/{jarvis_code_agent → jarvis_agent}/patch.py +77 -55
  7. jarvis/{jarvis_code_agent → jarvis_agent}/shell_input_handler.py +1 -2
  8. jarvis/jarvis_code_agent/code_agent.py +93 -88
  9. jarvis/jarvis_dev/main.py +335 -626
  10. jarvis/jarvis_git_squash/main.py +11 -32
  11. jarvis/jarvis_lsp/base.py +2 -26
  12. jarvis/jarvis_lsp/cpp.py +2 -14
  13. jarvis/jarvis_lsp/go.py +0 -13
  14. jarvis/jarvis_lsp/python.py +1 -30
  15. jarvis/jarvis_lsp/registry.py +10 -14
  16. jarvis/jarvis_lsp/rust.py +0 -12
  17. jarvis/jarvis_multi_agent/__init__.py +20 -29
  18. jarvis/jarvis_platform/ai8.py +7 -32
  19. jarvis/jarvis_platform/base.py +2 -7
  20. jarvis/jarvis_platform/kimi.py +3 -144
  21. jarvis/jarvis_platform/ollama.py +54 -68
  22. jarvis/jarvis_platform/openai.py +0 -4
  23. jarvis/jarvis_platform/oyi.py +0 -75
  24. jarvis/jarvis_platform/registry.py +1 -1
  25. jarvis/jarvis_platform/yuanbao.py +264 -0
  26. jarvis/jarvis_platform_manager/main.py +3 -3
  27. jarvis/jarvis_rag/file_processors.py +138 -0
  28. jarvis/jarvis_rag/main.py +1305 -425
  29. jarvis/jarvis_tools/ask_codebase.py +227 -41
  30. jarvis/jarvis_tools/code_review.py +229 -166
  31. jarvis/jarvis_tools/create_code_agent.py +76 -72
  32. jarvis/jarvis_tools/create_sub_agent.py +32 -15
  33. jarvis/jarvis_tools/execute_python_script.py +58 -0
  34. jarvis/jarvis_tools/execute_shell.py +15 -28
  35. jarvis/jarvis_tools/execute_shell_script.py +2 -2
  36. jarvis/jarvis_tools/file_analyzer.py +271 -0
  37. jarvis/jarvis_tools/file_operation.py +3 -3
  38. jarvis/jarvis_tools/find_caller.py +213 -0
  39. jarvis/jarvis_tools/find_symbol.py +211 -0
  40. jarvis/jarvis_tools/function_analyzer.py +248 -0
  41. jarvis/jarvis_tools/git_commiter.py +89 -70
  42. jarvis/jarvis_tools/lsp_find_definition.py +83 -67
  43. jarvis/jarvis_tools/lsp_find_references.py +62 -46
  44. jarvis/jarvis_tools/lsp_get_diagnostics.py +90 -74
  45. jarvis/jarvis_tools/methodology.py +89 -48
  46. jarvis/jarvis_tools/project_analyzer.py +220 -0
  47. jarvis/jarvis_tools/read_code.py +24 -3
  48. jarvis/jarvis_tools/read_webpage.py +195 -81
  49. jarvis/jarvis_tools/registry.py +132 -11
  50. jarvis/jarvis_tools/search_web.py +73 -30
  51. jarvis/jarvis_tools/tool_generator.py +7 -9
  52. jarvis/jarvis_utils/__init__.py +1 -0
  53. jarvis/jarvis_utils/config.py +67 -3
  54. jarvis/jarvis_utils/embedding.py +344 -45
  55. jarvis/jarvis_utils/git_utils.py +18 -2
  56. jarvis/jarvis_utils/input.py +7 -4
  57. jarvis/jarvis_utils/methodology.py +379 -7
  58. jarvis/jarvis_utils/output.py +5 -3
  59. jarvis/jarvis_utils/utils.py +62 -10
  60. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/METADATA +3 -4
  61. jarvis_ai_assistant-0.1.132.dist-info/RECORD +82 -0
  62. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/entry_points.txt +2 -0
  63. jarvis/jarvis_c2rust/c2rust.yaml +0 -734
  64. jarvis/jarvis_code_agent/builtin_input_handler.py +0 -43
  65. jarvis/jarvis_codebase/__init__.py +0 -0
  66. jarvis/jarvis_codebase/main.py +0 -1011
  67. jarvis/jarvis_tools/lsp_get_document_symbols.py +0 -87
  68. jarvis/jarvis_tools/lsp_prepare_rename.py +0 -130
  69. jarvis_ai_assistant-0.1.130.dist-info/RECORD +0 -79
  70. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/LICENSE +0 -0
  71. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/WHEEL +0 -0
  72. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
1
1
  from typing import Dict, Any, List
2
-
2
+ import concurrent.futures
3
3
  from regex import W
4
4
  from yaspin import yaspin
5
5
  from jarvis.jarvis_platform.registry import PlatformRegistry
@@ -7,7 +7,7 @@ from jarvis.jarvis_tools.read_webpage import WebpageTool
7
7
  from playwright.sync_api import sync_playwright
8
8
  from urllib.parse import quote
9
9
 
10
- from jarvis.jarvis_utils.config import get_max_token_count
10
+ from jarvis.jarvis_utils.config import get_max_token_count, get_thread_count
11
11
  from jarvis.jarvis_utils.embedding import get_context_token_count
12
12
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
13
13
 
@@ -104,7 +104,7 @@ class SearchTool:
104
104
  "max_results": {
105
105
  "type": "integer",
106
106
  "description": "最大搜索结果数量",
107
- "default": 3
107
+ "default": 10
108
108
  }
109
109
  },
110
110
  "required": ["query", "question"]
@@ -168,22 +168,20 @@ class SearchTool:
168
168
  # Process each batch
169
169
  batch_results = []
170
170
  for i, batch in enumerate(batches, 1):
171
- PrettyOutput.print(f"正在处理批次 {i}/{len(batches)}...", OutputType.PROGRESS)
172
-
173
- prompt = f"""Please analyze these search results to answer the question: {question}
171
+ prompt = f"""请根据以下搜索结果回答以下问题:{question}
174
172
 
175
- Search results content (Batch {i}/{len(batches)}):
173
+ 搜索结果内容 ( {i} 批/{len(batches)}):
176
174
  {'-' * 40}
177
175
  {''.join(batch)}
178
176
  {'-' * 40}
179
177
 
180
- Please extract key information related to the question. Focus on:
181
- 1. Relevant facts and details
182
- 2. Maintaining objectivity
183
- 3. Citing sources when appropriate
184
- 4. Noting any uncertainties
178
+ 请提取与问题相关的关键信息。重点关注:
179
+ 1. 相关事实和细节
180
+ 2. 保持客观性
181
+ 3. 在适当的时候引用来源
182
+ 4. 注明任何不确定性
185
183
 
186
- Format your response as a clear summary of findings from this batch."""
184
+ 请将您的回答格式化为对本批次搜索结果的清晰总结。"""
187
185
 
188
186
  response = self.model.chat_until_success(prompt)
189
187
  batch_results.append(response)
@@ -196,27 +194,27 @@ Format your response as a clear summary of findings from this batch."""
196
194
  batch_findings = '\n\n'.join(f'Batch {i+1}:\n{result}' for i, result in enumerate(batch_results))
197
195
  separator = '-' * 40
198
196
 
199
- synthesis_prompt = f"""Please provide a comprehensive answer to the original question by synthesizing the findings from multiple batches of search results.
197
+ synthesis_prompt = f"""请通过综合多个批次的搜索结果,为原始问题提供一个全面的回答。
200
198
 
201
- Original Question: {question}
199
+ 原始问题: {question}
202
200
 
203
- Findings from each batch:
201
+ 各批次的发现:
204
202
  {separator}
205
203
  {batch_findings}
206
204
  {separator}
207
205
 
208
- Please synthesize a final answer that:
209
- 1. Combines key insights from all batches
210
- 2. Resolves any contradictions between sources
211
- 3. Maintains clear source attribution
212
- 4. Acknowledges any remaining uncertainties
213
- 5. Provides a coherent and complete response to the original question"""
206
+ 请综合出一个最终答案,要求:
207
+ 1. 整合所有批次的关键见解
208
+ 2. 解决不同来源之间的矛盾
209
+ 3. 保持清晰的来源归属
210
+ 4. 承认任何剩余的不确定性
211
+ 5. 提供对原始问题的连贯完整的回答"""
214
212
 
215
213
  final_response = self.model.chat_until_success(synthesis_prompt)
216
214
  return final_response
217
215
 
218
216
  except Exception as e:
219
- return f"Information extraction failed: {str(e)}"
217
+ return f"信息提取失败:{str(e)}"
220
218
 
221
219
  def execute(self, args: Dict) -> Dict[str, Any]:
222
220
  """Execute search and extract information"""
@@ -238,18 +236,60 @@ Please synthesize a final answer that:
238
236
  "stderr": "No search results found"
239
237
  }
240
238
 
239
+ # Read webpages in parallel using ThreadPoolExecutor
241
240
  contents = []
242
- for i, result in enumerate(results, 1):
241
+
242
+ # Print starting message
243
+ PrettyOutput.print(f"开始并行读取 {len(results)} 个网页结果...", OutputType.INFO)
244
+
245
+ def fetch_webpage(result_info):
246
+ """Function to fetch a single webpage in a separate thread"""
247
+ idx, result = result_info
243
248
  try:
244
- PrettyOutput.print(f"正在读取结果 {i}/{len(results)}... {result['title']} - {result['href']}", OutputType.PROGRESS)
249
+ # Removed progress print here to avoid mixed output
245
250
  webpage_result = self.webpage_tool.execute({"url": result["href"]})
246
251
  if webpage_result["success"]:
247
- contents.append(f"\nSource {i}: {result['href']}\n")
248
- contents.append(webpage_result["stdout"])
252
+ return idx, result, webpage_result["stdout"], True
253
+ return idx, result, None, False
249
254
  except Exception as e:
250
- PrettyOutput.print(f"读取结果失败 {i}: {str(e)}", OutputType.WARNING)
251
- continue
255
+ return idx, result, str(e), False
256
+
257
+ # Use ThreadPoolExecutor for parallel processing
258
+ processed_results = []
259
+ with yaspin(text="正在并行读取网页内容...", color="cyan") as spinner:
260
+ with concurrent.futures.ThreadPoolExecutor(max_workers=get_thread_count()) as executor:
261
+ # Submit all webpage fetch tasks
262
+ future_to_result = {
263
+ executor.submit(fetch_webpage, (i, result)): i
264
+ for i, result in enumerate(results)
265
+ }
266
+
267
+ # Collect results as they complete
268
+ for future in concurrent.futures.as_completed(future_to_result):
269
+ processed_results.append(future.result())
270
+ # Update spinner with current progress
271
+ spinner.text = f"正在并行读取网页内容... ({len(processed_results)}/{len(results)})"
272
+
273
+ spinner.text = "网页内容读取完成"
274
+ spinner.ok("✅")
252
275
 
276
+ # Sort results by original index to maintain ordering
277
+ processed_results.sort(key=lambda x: x[0])
278
+
279
+ # Print results in order and add to contents
280
+ PrettyOutput.section("搜索结果概览", OutputType.INFO)
281
+
282
+ output = []
283
+ for idx, result, content, success in processed_results:
284
+ if success:
285
+ output.append(f"✅ 读取结果 {idx+1}/{len(results)} 完成: {result['title']} - {result['href']}")
286
+ contents.append(f"\nSource {idx+1}: {result['href']}\n")
287
+ contents.append(content)
288
+ else:
289
+ output.append(f"❌ 读取结果 {idx+1}/{len(results)} 失败: {result['title']} - {result['href']}")
290
+
291
+ PrettyOutput.print("\n".join(output), OutputType.INFO)
292
+
253
293
  if not contents:
254
294
  return {
255
295
  "success": False,
@@ -262,10 +302,13 @@ Please synthesize a final answer that:
262
302
  analysis = self._extract_info(contents, question)
263
303
  spinner.text = "信息提取完成"
264
304
  spinner.ok("✅")
305
+
306
+ output = f"分析结果:\n\n{analysis}"
307
+ PrettyOutput.print(output, OutputType.SUCCESS)
265
308
 
266
309
  return {
267
310
  "success": True,
268
- "stdout": f"Search analysis results:\n\n{analysis}",
311
+ "stdout": output,
269
312
  "stderr": ""
270
313
  }
271
314
 
@@ -7,6 +7,7 @@ from typing import Dict, Any
7
7
 
8
8
  from yaspin import yaspin
9
9
  from jarvis.jarvis_platform.registry import PlatformRegistry
10
+ from jarvis.jarvis_utils.utils import ct, ot
10
11
 
11
12
  class ToolGenerator:
12
13
  """工具生成器类,用于自动创建与Jarvis系统集成的新工具"""
@@ -84,7 +85,7 @@ class ToolGenerator:
84
85
  tools_dir.mkdir(parents=True, exist_ok=True)
85
86
  tool_file = tools_dir / f"{tool_name}.py"
86
87
 
87
- with open(tool_file, "w") as f:
88
+ with open(tool_file, "w", errors="ignore") as f:
88
89
  f.write(implementation)
89
90
  spinner.text = "工具保存完成"
90
91
  spinner.ok("✅")
@@ -112,8 +113,7 @@ class ToolGenerator:
112
113
  Returns:
113
114
  格式化后的提示字符串
114
115
  """
115
- example_code = '''
116
- <TOOL>
116
+ example_code = ot("TOOL")+'''
117
117
  from typing import Dict, Any
118
118
  from jarvis.utils import OutputType, PrettyOutput
119
119
  from jarvis.jarvis_platform.registry import PlatformRegistry
@@ -163,8 +163,7 @@ class CustomTool:
163
163
  "stdout": "",
164
164
  "stderr": str(e)
165
165
  }
166
- </TOOL>
167
- '''
166
+ ''' + ct("TOOL")
168
167
 
169
168
  return f'''创建一个与Jarvis系统集成的Python工具类。请遵循以下要求:
170
169
  1. 类名: {tool_name.capitalize()}Tool
@@ -183,9 +182,9 @@ class CustomTool:
183
182
  8. 仅返回Python实现代码
184
183
  9. 代码应该是完整且可直接使用的
185
184
  10. 按照以下格式输出代码:
186
- <TOOL>
185
+ {ot("TOOL")}
187
186
  {example_code}
188
- </TOOL>
187
+ {ct("TOOL")}
189
188
 
190
189
  示例:
191
190
  {example_code}
@@ -199,8 +198,7 @@ class CustomTool:
199
198
  Returns:
200
199
  提取到的Python代码字符串
201
200
  """
202
- # 查找第一个<TOOL>和</TOOL>标签之间的内容
203
- sm = re.search(r'<TOOL>(.*?)</TOOL>', response, re.DOTALL)
201
+ sm = re.search(ot("TOOL")+r'(.*?)'+ct("TOOL"), response, re.DOTALL)
204
202
  if sm:
205
203
  return sm.group(1)
206
204
  return ""
@@ -22,3 +22,4 @@ colorama.init()
22
22
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
23
23
  # 安装rich traceback处理器以获得更好的错误信息
24
24
  install_rich_traceback()
25
+
@@ -11,10 +11,10 @@ import os
11
11
  """
12
12
  def get_max_token_count() -> int:
13
13
  """
14
- 获取API请求的最大token数量。
14
+ 获取模型允许的最大token数量。
15
15
 
16
- 返回:
17
- int: 最大token数量,默认为131072(128k)
16
+ 返回:
17
+ int: 模型能处理的最大token数量。
18
18
  """
19
19
  return int(os.getenv('JARVIS_MAX_TOKEN_COUNT', '131072')) # 默认128k
20
20
 
@@ -172,3 +172,67 @@ def is_confirm_before_apply_patch() -> bool:
172
172
  bool: 如果需要确认则返回True,默认为False
173
173
  """
174
174
  return os.getenv('JARVIS_CONFIRM_BEFORE_APPLY_PATCH', 'false') == 'true'
175
+
176
+ def get_rag_ignored_paths() -> list:
177
+ """
178
+ 获取RAG索引时需要忽略的路径列表。
179
+
180
+ 首先尝试从.jarvis/rag_ignore.txt文件中读取,
181
+ 如果该文件不存在,则返回默认忽略列表。
182
+
183
+ 返回:
184
+ list: 忽略路径的列表,默认包含常见忽略路径
185
+ """
186
+ # 默认忽略路径
187
+ default_ignored = [
188
+ '.git',
189
+ '__pycache__',
190
+ 'node_modules',
191
+ '.jarvis',
192
+ '.jarvis-*',
193
+ 'target',
194
+ 'venv',
195
+ 'env',
196
+ '.env',
197
+ '.venv',
198
+ '.idea',
199
+ '.vscode',
200
+ 'dist',
201
+ 'build',
202
+ '*.pyc',
203
+ '*.pyo',
204
+ '*.so',
205
+ '*.o',
206
+ '*.a',
207
+ '*.pyd',
208
+ '*.dll',
209
+ '*.exe',
210
+ '*.bin',
211
+ '*.obj',
212
+ '*.out',
213
+ '*.jpg',
214
+ '*.jpeg',
215
+ '*.png',
216
+ '*.gif',
217
+ '*.tiff',
218
+ '*.pdf',
219
+ '*.zip',
220
+ '*.tar',
221
+ '*.tar.gz',
222
+ '*.gz',
223
+ '*.bz2',
224
+ '*.xz',
225
+ '*.rar'
226
+ ]
227
+
228
+ # 尝试从配置文件中读取
229
+ try:
230
+ config_path = os.path.join('.jarvis', 'rag_ignore.txt')
231
+ if os.path.exists(config_path):
232
+ with open(config_path, 'r') as f:
233
+ custom_ignored = [line.strip() for line in f if line.strip() and not line.startswith('#')]
234
+ return custom_ignored
235
+ except Exception:
236
+ pass
237
+
238
+ return default_ignored