jarvis-ai-assistant 0.1.110__py3-none-any.whl → 0.1.112__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 (47) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +51 -39
  3. jarvis/jarvis_code_agent/code_agent.py +89 -53
  4. jarvis/jarvis_code_agent/file_select.py +20 -20
  5. jarvis/jarvis_code_agent/patch.py +20 -11
  6. jarvis/jarvis_code_agent/relevant_files.py +68 -16
  7. jarvis/jarvis_codebase/main.py +82 -88
  8. jarvis/jarvis_lsp/cpp.py +1 -1
  9. jarvis/jarvis_lsp/go.py +1 -1
  10. jarvis/jarvis_lsp/python.py +0 -2
  11. jarvis/jarvis_lsp/registry.py +13 -13
  12. jarvis/jarvis_lsp/rust.py +1 -1
  13. jarvis/jarvis_platform/ai8.py +14 -14
  14. jarvis/jarvis_platform/base.py +1 -1
  15. jarvis/jarvis_platform/kimi.py +17 -17
  16. jarvis/jarvis_platform/ollama.py +14 -14
  17. jarvis/jarvis_platform/openai.py +8 -8
  18. jarvis/jarvis_platform/oyi.py +19 -19
  19. jarvis/jarvis_platform/registry.py +6 -6
  20. jarvis/jarvis_platform_manager/main.py +17 -17
  21. jarvis/jarvis_rag/main.py +25 -25
  22. jarvis/jarvis_smart_shell/main.py +6 -6
  23. jarvis/jarvis_tools/ask_codebase.py +4 -4
  24. jarvis/jarvis_tools/ask_user.py +2 -2
  25. jarvis/jarvis_tools/create_code_agent.py +8 -8
  26. jarvis/jarvis_tools/create_sub_agent.py +2 -2
  27. jarvis/jarvis_tools/execute_shell.py +2 -2
  28. jarvis/jarvis_tools/file_operation.py +1 -1
  29. jarvis/jarvis_tools/git_commiter.py +4 -6
  30. jarvis/jarvis_tools/methodology.py +3 -3
  31. jarvis/jarvis_tools/rag.py +3 -3
  32. jarvis/jarvis_tools/read_code.py +4 -3
  33. jarvis/jarvis_tools/read_webpage.py +19 -6
  34. jarvis/jarvis_tools/registry.py +11 -11
  35. jarvis/jarvis_tools/search.py +88 -27
  36. jarvis/jarvis_tools/select_code_files.py +1 -1
  37. jarvis/jarvis_tools/tool_generator.py +182 -0
  38. jarvis/utils/date_utils.py +19 -0
  39. jarvis/utils.py +31 -25
  40. jarvis_ai_assistant-0.1.112.dist-info/METADATA +460 -0
  41. jarvis_ai_assistant-0.1.112.dist-info/RECORD +64 -0
  42. jarvis_ai_assistant-0.1.110.dist-info/METADATA +0 -462
  43. jarvis_ai_assistant-0.1.110.dist-info/RECORD +0 -62
  44. {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/LICENSE +0 -0
  45. {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/WHEEL +0 -0
  46. {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/entry_points.txt +0 -0
  47. {jarvis_ai_assistant-0.1.110.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/top_level.txt +0 -0
@@ -37,9 +37,9 @@ class CodeBase:
37
37
  self.embedding_model.encode([test_text],
38
38
  convert_to_tensor=True,
39
39
  normalize_embeddings=True)
40
- PrettyOutput.print("Model loaded successfully", output_type=OutputType.SUCCESS)
40
+ PrettyOutput.print("模型加载成功", output_type=OutputType.SUCCESS)
41
41
  except Exception as e:
42
- PrettyOutput.print(f"Failed to load model: {str(e)}", output_type=OutputType.ERROR)
42
+ PrettyOutput.print(f"加载模型失败: {str(e)}", output_type=OutputType.ERROR)
43
43
  raise
44
44
 
45
45
  self.vector_dim = self.embedding_model.get_sentence_embedding_dimension()
@@ -71,7 +71,7 @@ class CodeBase:
71
71
  if self.thread_count > 1:
72
72
  model.set_suppress_output(True)
73
73
  else:
74
- PrettyOutput.print(f"Make description for {file_path} ...", output_type=OutputType.PROGRESS)
74
+ PrettyOutput.print(f" {file_path} 生成描述 ...", output_type=OutputType.PROGRESS)
75
75
  prompt = f"""Please analyze the following code file and generate a detailed description. The description should include:
76
76
  1. Overall file functionality description
77
77
  2. description for each global variable, function, type definition, class, method, and other code elements
@@ -129,7 +129,7 @@ Code content:
129
129
  self.file_paths.append(file_path)
130
130
  vectors.append(cache_data["vector"])
131
131
  except Exception as e:
132
- PrettyOutput.print(f"Failed to load cache file {cache_file}: {str(e)}",
132
+ PrettyOutput.print(f"加载缓存文件 {cache_file} 失败: {str(e)}",
133
133
  output_type=OutputType.WARNING)
134
134
  continue
135
135
 
@@ -142,14 +142,14 @@ Code content:
142
142
  self.index = faiss.IndexIDMap(hnsw_index)
143
143
  self.index.add_with_ids(vectors_array, np.array(range(len(vectors)))) # type: ignore
144
144
 
145
- PrettyOutput.print(f"Loaded {len(self.vector_cache)} vector cache and rebuilt index",
145
+ PrettyOutput.print(f"加载 {len(self.vector_cache)} 个向量缓存并重建索引",
146
146
  output_type=OutputType.INFO)
147
147
  else:
148
148
  self.index = None
149
- PrettyOutput.print("No valid cache files found", output_type=OutputType.WARNING)
149
+ PrettyOutput.print("没有找到有效的缓存文件", output_type=OutputType.WARNING)
150
150
 
151
151
  except Exception as e:
152
- PrettyOutput.print(f"Failed to load cache directory: {str(e)}",
152
+ PrettyOutput.print(f"加载缓存目录失败: {str(e)}",
153
153
  output_type=OutputType.WARNING)
154
154
  self.vector_cache = {}
155
155
  self.file_paths = []
@@ -161,7 +161,7 @@ Code content:
161
161
  with open(file_path, "rb") as f:
162
162
  file_md5 = hashlib.md5(f.read()).hexdigest()
163
163
  except Exception as e:
164
- PrettyOutput.print(f"Failed to calculate MD5 for {file_path}: {str(e)}",
164
+ PrettyOutput.print(f"计算 {file_path} 的MD5失败: {str(e)}",
165
165
  output_type=OutputType.ERROR)
166
166
  file_md5 = ""
167
167
 
@@ -182,7 +182,7 @@ Code content:
182
182
  with lzma.open(cache_path, 'wb') as f:
183
183
  pickle.dump(cache_data, f, protocol=pickle.HIGHEST_PROTOCOL)
184
184
  except Exception as e:
185
- PrettyOutput.print(f"Failed to save cache for {file_path}: {str(e)}",
185
+ PrettyOutput.print(f"保存 {file_path} 的缓存失败: {str(e)}",
186
186
  output_type=OutputType.ERROR)
187
187
 
188
188
  def get_cached_vector(self, file_path: str, description: str) -> Optional[np.ndarray]:
@@ -195,7 +195,7 @@ Code content:
195
195
  with open(file_path, "rb") as f:
196
196
  current_md5 = hashlib.md5(f.read()).hexdigest()
197
197
  except Exception as e:
198
- PrettyOutput.print(f"Failed to calculate MD5 for {file_path}: {str(e)}",
198
+ PrettyOutput.print(f"计算 {file_path} 的MD5失败: {str(e)}",
199
199
  output_type=OutputType.ERROR)
200
200
  return None
201
201
 
@@ -232,7 +232,7 @@ Content: {content}
232
232
  self.cache_vector(file_path, vector, description)
233
233
  return vector
234
234
  except Exception as e:
235
- PrettyOutput.print(f"Error vectorizing file {file_path}: {str(e)}",
235
+ PrettyOutput.print(f"向量化 {file_path} 失败: {str(e)}",
236
236
  output_type=OutputType.ERROR)
237
237
  return np.zeros(self.vector_dim, dtype=np.float32) # type: ignore
238
238
 
@@ -257,7 +257,7 @@ Content: {content}
257
257
  return bool(files_to_delete)
258
258
 
259
259
  except Exception as e:
260
- PrettyOutput.print(f"Failed to clean cache: {str(e)}",
260
+ PrettyOutput.print(f"清理缓存失败: {str(e)}",
261
261
  output_type=OutputType.ERROR)
262
262
  return False
263
263
 
@@ -293,7 +293,7 @@ Content: {content}
293
293
  return file_path
294
294
 
295
295
  except Exception as e:
296
- PrettyOutput.print(f"Failed to process file {file_path}: {str(e)}",
296
+ PrettyOutput.print(f"处理 {file_path} 失败: {str(e)}",
297
297
  output_type=OutputType.ERROR)
298
298
  return None
299
299
 
@@ -318,13 +318,13 @@ Content: {content}
318
318
 
319
319
  for i, (file_path, data) in enumerate(self.vector_cache.items()):
320
320
  if "vector" not in data:
321
- PrettyOutput.print(f"Invalid cache data for {file_path}: missing vector",
321
+ PrettyOutput.print(f"无效的缓存数据 {file_path}: 缺少向量",
322
322
  output_type=OutputType.WARNING)
323
323
  continue
324
324
 
325
325
  vector = data["vector"]
326
326
  if not isinstance(vector, np.ndarray):
327
- PrettyOutput.print(f"Invalid vector type for {file_path}: {type(vector)}",
327
+ PrettyOutput.print(f"无效的向量类型 {file_path}: {type(vector)}",
328
328
  output_type=OutputType.WARNING)
329
329
  continue
330
330
 
@@ -335,26 +335,26 @@ Content: {content}
335
335
  if vectors:
336
336
  vectors = np.vstack(vectors)
337
337
  if len(vectors) != len(ids):
338
- PrettyOutput.print(f"Vector count mismatch: {len(vectors)} vectors vs {len(ids)} ids",
338
+ PrettyOutput.print(f"向量数量不匹配: {len(vectors)} 个向量 vs {len(ids)} 个ID",
339
339
  output_type=OutputType.ERROR)
340
340
  self.index = None
341
341
  return
342
342
 
343
343
  try:
344
344
  self.index.add_with_ids(vectors, np.array(ids)) # type: ignore
345
- PrettyOutput.print(f"Successfully built index with {len(vectors)} vectors",
345
+ PrettyOutput.print(f"成功构建包含 {len(vectors)} 个向量的索引",
346
346
  output_type=OutputType.SUCCESS)
347
347
  except Exception as e:
348
- PrettyOutput.print(f"Failed to add vectors to index: {str(e)}",
348
+ PrettyOutput.print(f"添加向量到索引失败: {str(e)}",
349
349
  output_type=OutputType.ERROR)
350
350
  self.index = None
351
351
  else:
352
- PrettyOutput.print("No valid vectors found, index not built",
352
+ PrettyOutput.print("没有找到有效的向量, 索引未构建",
353
353
  output_type=OutputType.WARNING)
354
354
  self.index = None
355
355
 
356
356
  except Exception as e:
357
- PrettyOutput.print(f"Failed to build index: {str(e)}",
357
+ PrettyOutput.print(f"构建索引失败: {str(e)}",
358
358
  output_type=OutputType.ERROR)
359
359
  self.index = None
360
360
 
@@ -379,20 +379,20 @@ Content: {content}
379
379
  try:
380
380
  os.remove(cache_path)
381
381
  except Exception as e:
382
- PrettyOutput.print(f"Failed to delete cache file for {cached_file}: {str(e)}",
382
+ PrettyOutput.print(f"删除缓存文件 {cached_file} 失败: {str(e)}",
383
383
  output_type=OutputType.WARNING)
384
384
 
385
385
  if files_to_delete:
386
386
  for file_path in files_to_delete:
387
387
  del self.vector_cache[file_path]
388
- PrettyOutput.print(f"Cleaned cache for {len(files_to_delete)} non-existent files",
388
+ PrettyOutput.print(f"清理了 {len(files_to_delete)} 个不存在的文件的缓存",
389
389
  output_type=OutputType.INFO)
390
390
 
391
391
  # Update the git file list
392
392
  self.git_file_list = self.get_git_file_list()
393
393
 
394
394
  # Check file changes
395
- PrettyOutput.print("Check file changes...", output_type=OutputType.INFO)
395
+ PrettyOutput.print("检查文件变化...", output_type=OutputType.INFO)
396
396
  changes_detected = False
397
397
  new_files = []
398
398
  modified_files = []
@@ -424,36 +424,36 @@ Content: {content}
424
424
  modified_files.append(file_path)
425
425
  changes_detected = True
426
426
  except Exception as e:
427
- PrettyOutput.print(f"Failed to check file {file_path}: {str(e)}",
427
+ PrettyOutput.print(f"检查 {file_path} 失败: {str(e)}",
428
428
  output_type=OutputType.ERROR)
429
429
  progress.advance(task)
430
430
 
431
431
  # If changes are detected, display changes and ask the user
432
432
  if changes_detected:
433
- output_lines = ["Detected the following changes:"]
433
+ output_lines = ["检测到以下变化:"]
434
434
  if new_files:
435
- output_lines.append("New files:")
435
+ output_lines.append("新文件:")
436
436
  output_lines.extend(f" {f}" for f in new_files)
437
437
  if modified_files:
438
- output_lines.append("Modified files:")
438
+ output_lines.append("修改的文件:")
439
439
  output_lines.extend(f" {f}" for f in modified_files)
440
440
  if deleted_files:
441
- output_lines.append("Deleted files:")
441
+ output_lines.append("删除的文件:")
442
442
  output_lines.extend(f" {f}" for f in deleted_files)
443
443
 
444
444
  PrettyOutput.print("\n".join(output_lines), output_type=OutputType.WARNING)
445
445
 
446
446
  # If force is True, continue directly
447
447
  if not force:
448
- if not user_confirm("Rebuild the index?", False):
449
- PrettyOutput.print("Cancel rebuilding the index", output_type=OutputType.INFO)
448
+ if not user_confirm("重建索引?", False):
449
+ PrettyOutput.print("取消重建索引", output_type=OutputType.INFO)
450
450
  return
451
451
 
452
452
  # Clean deleted files
453
453
  for file_path in files_to_delete:
454
454
  del self.vector_cache[file_path]
455
455
  if files_to_delete:
456
- PrettyOutput.print(f"Cleaned the cache of {len(files_to_delete)} files",
456
+ PrettyOutput.print(f"清理了 {len(files_to_delete)} 个文件的缓存",
457
457
  output_type=OutputType.INFO)
458
458
 
459
459
  # Process new and modified files
@@ -482,19 +482,19 @@ Content: {content}
482
482
  pbar.update(1)
483
483
 
484
484
  if processed_files:
485
- PrettyOutput.print("Rebuilding the vector database...", output_type=OutputType.INFO)
485
+ PrettyOutput.print("重建向量数据库...", output_type=OutputType.INFO)
486
486
  self.gen_vector_db_from_cache()
487
- PrettyOutput.print(f"Successfully generated the index for {len(processed_files)} files",
487
+ PrettyOutput.print(f"成功生成了 {len(processed_files)} 个文件的索引",
488
488
  output_type=OutputType.SUCCESS)
489
489
  else:
490
- PrettyOutput.print("No file changes detected, no need to rebuild the index", output_type=OutputType.INFO)
490
+ PrettyOutput.print("没有检测到文件变化, 不需要重建索引", output_type=OutputType.INFO)
491
491
 
492
492
  except Exception as e:
493
493
  # Try to save the cache when an exception occurs
494
494
  try:
495
495
  self._load_all_cache()
496
496
  except Exception as save_error:
497
- PrettyOutput.print(f"Failed to save cache: {str(save_error)}",
497
+ PrettyOutput.print(f"保存缓存失败: {str(save_error)}",
498
498
  output_type=OutputType.ERROR)
499
499
  raise e # Re-raise the original exception
500
500
 
@@ -524,7 +524,7 @@ Content: {content}
524
524
  score = len(matched_keywords) / len(keywords)
525
525
  return score
526
526
 
527
- def pick_results(self, query: List[str], initial_results: List[str]) -> List[str]:
527
+ def pick_results(self, query: List[str], initial_results: List[str]) -> List[Dict[str,str]]:
528
528
  """Use a large model to pick the search results
529
529
 
530
530
  Args:
@@ -538,14 +538,14 @@ Content: {content}
538
538
  return []
539
539
 
540
540
  try:
541
- PrettyOutput.print(f"Picking results for query: \n" + "\n".join(query), output_type=OutputType.INFO)
541
+ PrettyOutput.print(f"Picking results ...", output_type=OutputType.INFO)
542
542
 
543
543
  # Maximum content length per batch
544
544
  max_batch_length = self.max_token_count - 1000 # Reserve space for prompt
545
545
  max_file_length = max_batch_length // 3 # Limit individual file size
546
546
 
547
547
  # Process files in batches
548
- all_selected_files = set()
548
+ all_selected_files = []
549
549
  current_batch = []
550
550
  current_token_count = 0
551
551
 
@@ -565,7 +565,7 @@ Content: {content}
565
565
  # Process current batch
566
566
  if current_batch:
567
567
  selected = self._process_batch('\n'.join(query), current_batch)
568
- all_selected_files.update(selected)
568
+ all_selected_files.extend(selected)
569
569
  # Start new batch
570
570
  current_batch = [file_info]
571
571
  current_token_count = tokens_count
@@ -574,23 +574,22 @@ Content: {content}
574
574
  current_token_count += tokens_count
575
575
 
576
576
  except Exception as e:
577
- PrettyOutput.print(f"Failed to read file {path}: {str(e)}", OutputType.ERROR)
577
+ PrettyOutput.print(f"读取 {path} 失败: {str(e)}", OutputType.ERROR)
578
578
  continue
579
579
 
580
580
  # Process final batch
581
581
  if current_batch:
582
582
  selected = self._process_batch('\n'.join(query), current_batch)
583
- all_selected_files.update(selected)
583
+ all_selected_files.extend(selected)
584
584
 
585
585
  # Convert set to list and maintain original order
586
- final_results = [path for path in initial_results if path in all_selected_files]
587
- return final_results
586
+ return all_selected_files
588
587
 
589
588
  except Exception as e:
590
- PrettyOutput.print(f"Failed to pick: {str(e)}", OutputType.ERROR)
591
- return initial_results
589
+ PrettyOutput.print(f"选择失败: {str(e)}", OutputType.ERROR)
590
+ return [{"file": f, "reason": "" } for f in initial_results]
592
591
 
593
- def _process_batch(self, query: str, files_info: List[str]) -> List[str]:
592
+ def _process_batch(self, query: str, files_info: List[str]) -> List[Dict[str, str]]:
594
593
  """Process a batch of files"""
595
594
  prompt = f"""As a code analysis expert, please help identify the most relevant files for the given query using chain-of-thought reasoning.
596
595
 
@@ -611,8 +610,10 @@ Think through this step by step:
611
610
 
612
611
  Please output your selection in YAML format:
613
612
  <FILES>
614
- - path/to/most/relevant.py
613
+ - file: path/to/most/relevant.py
614
+ reason: xxxxxxxxxx
615
615
  - path/to/next/relevant.py
616
+ reason: yyyyyyyyyy
616
617
  </FILES>
617
618
 
618
619
  Important:
@@ -638,7 +639,7 @@ Important:
638
639
  selected_files = yaml.safe_load(files_match.group(1))
639
640
  return selected_files if selected_files else []
640
641
  except Exception as e:
641
- PrettyOutput.print(f"Failed to parse response: {str(e)}", OutputType.ERROR)
642
+ PrettyOutput.print(f"解析响应失败: {str(e)}", OutputType.ERROR)
642
643
  return []
643
644
 
644
645
  def _generate_query_variants(self, query: str) -> List[str]:
@@ -686,7 +687,7 @@ Please provide 10 search-optimized expressions in the specified format.
686
687
  try:
687
688
  variants = yaml.safe_load(question_match.group(1))
688
689
  except Exception as e:
689
- PrettyOutput.print(f"Failed to parse variants: {str(e)}", OutputType.ERROR)
690
+ PrettyOutput.print(f"解析变体失败: {str(e)}", OutputType.ERROR)
690
691
 
691
692
  # Add original query
692
693
  variants.append(query)
@@ -724,7 +725,7 @@ Please provide 10 search-optimized expressions in the specified format.
724
725
  return results
725
726
 
726
727
 
727
- def search_similar(self, query: str, top_k: int = 30) -> List[str]:
728
+ def search_similar(self, query: str, top_k: int = 30) -> List[Dict[str, str]]:
728
729
  """Search related files with optimized retrieval"""
729
730
  try:
730
731
  self.generate_codebase()
@@ -764,32 +765,27 @@ Please provide 10 search-optimized expressions in the specified format.
764
765
  all_results.sort(key=lambda x: x[1], reverse=True)
765
766
  results = all_results[:top_k]
766
767
 
767
- # Display results with scores
768
- message = "Found related files:\n"
769
- for path, score, _ in results:
770
- message += f"File: {path} (Score: {score:.3f})\n"
771
- PrettyOutput.print(message.rstrip(), output_type=OutputType.INFO, lang="markdown")
772
-
773
768
  results = self.pick_results(query_variants, [path for path, _, _ in results])
769
+
770
+ output = "Found related files:\n"
771
+ for file in results:
772
+ output += f'''- {file['file']} ({file['reason']})\n'''
773
+ PrettyOutput.print(output, output_type=OutputType.INFO, lang="markdown")
774
+
774
775
 
775
776
  return results
776
777
 
777
778
  except Exception as e:
778
- PrettyOutput.print(f"Failed to search: {str(e)}", output_type=OutputType.ERROR)
779
+ PrettyOutput.print(f"搜索失败: {str(e)}", output_type=OutputType.ERROR)
779
780
  return []
780
781
 
781
- def ask_codebase(self, query: str, top_k: int=20) -> str:
782
+ def ask_codebase(self, query: str, top_k: int=20) -> Tuple[List[Dict[str, str]], str]:
782
783
  """Query the codebase with enhanced context building"""
783
784
  files_from_codebase = self.search_similar(query, top_k)
784
785
 
785
786
  if not files_from_codebase:
786
- PrettyOutput.print("No related files found", output_type=OutputType.WARNING)
787
- return ""
788
-
789
- output = "Found related files:\n"
790
- for path in files_from_codebase:
791
- output += f"- {path}\n"
792
- PrettyOutput.print(output, output_type=OutputType.INFO, lang="markdown")
787
+ PrettyOutput.print("没有找到相关文件", output_type=OutputType.WARNING)
788
+ return [],""
793
789
 
794
790
  # Build enhanced prompt
795
791
  prompt = f"""Based on the following code files, please provide a comprehensive and accurate answer to the user's question.
@@ -799,6 +795,8 @@ Important guidelines:
799
795
  2. Explain technical concepts clearly
800
796
  3. Include relevant code snippets when helpful
801
797
  4. If the code doesn't fully answer the question, indicate what's missing
798
+ 5. Answer in user's language.
799
+ 6. Answer with professional language.
802
800
 
803
801
  Question: {query}
804
802
 
@@ -810,16 +808,16 @@ Relevant code files (ordered by relevance):
810
808
 
811
809
  for path in files_from_codebase:
812
810
  try:
813
- content = open(path, "r", encoding="utf-8").read()
811
+ content = open(path["file"], "r", encoding="utf-8").read()
814
812
  file_content = f"""
815
- File: {path}
813
+ File: {path["file"]}
816
814
  Content:
817
815
  {content}
818
816
  ----------------------------------------
819
817
  """
820
818
  if current_count + get_context_token_count(file_content) > available_count:
821
819
  PrettyOutput.print(
822
- "Due to context length limit, some files were omitted",
820
+ "由于上下文长度限制, 一些文件被省略",
823
821
  output_type=OutputType.WARNING
824
822
  )
825
823
  break
@@ -828,25 +826,21 @@ Content:
828
826
  current_count += get_context_token_count(file_content)
829
827
 
830
828
  except Exception as e:
831
- PrettyOutput.print(f"Failed to read file {path}: {str(e)}",
829
+ PrettyOutput.print(f"读取 {path} 失败: {str(e)}",
832
830
  output_type=OutputType.ERROR)
833
831
  continue
834
832
 
833
+ model = PlatformRegistry.get_global_platform_registry().get_thinking_platform()
834
+
835
835
  prompt += """
836
- Please structure your answer as follows:
837
- 1. Direct answer to the question
838
- 2. Relevant code explanations
839
- 3. Implementation details
840
- 4. Any missing information or limitations
841
- 5. Add reference files and code snippets at the end of the answer.
842
-
843
- Answer in Chinese using professional language.
836
+ Output Format:
837
+ - question: the question to answer
838
+ answer: the answer to the question
839
+ - question: the question to answer
840
+ answer: the answer to the question
844
841
  """
845
-
846
- model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
847
- response = model.chat_until_success(prompt)
848
-
849
- return response
842
+
843
+ return files_from_codebase, model.chat_until_success(prompt)
850
844
 
851
845
  def is_index_generated(self) -> bool:
852
846
  """Check if the index has been generated"""
@@ -886,7 +880,7 @@ Answer in Chinese using professional language.
886
880
  return True
887
881
 
888
882
  except Exception as e:
889
- PrettyOutput.print(f"Error checking index status: {str(e)}",
883
+ PrettyOutput.print(f"检查索引状态失败: {str(e)}",
890
884
  output_type=OutputType.ERROR)
891
885
  return False
892
886
 
@@ -931,24 +925,24 @@ def main():
931
925
  if args.command == 'generate':
932
926
  try:
933
927
  codebase.generate_codebase(force=args.force)
934
- PrettyOutput.print("Codebase generation completed", output_type=OutputType.SUCCESS)
928
+ PrettyOutput.print("代码库生成完成", output_type=OutputType.SUCCESS)
935
929
  except Exception as e:
936
- PrettyOutput.print(f"Error during codebase generation: {str(e)}", output_type=OutputType.ERROR)
930
+ PrettyOutput.print(f"代码库生成失败: {str(e)}", output_type=OutputType.ERROR)
937
931
 
938
932
  elif args.command == 'search':
939
933
  results = codebase.search_similar(args.query, args.top_k)
940
934
  if not results:
941
- PrettyOutput.print("No similar files found", output_type=OutputType.WARNING)
935
+ PrettyOutput.print("没有找到相似的文件", output_type=OutputType.WARNING)
942
936
  return
943
937
 
944
- output = "Search Results:\n"
938
+ output = "搜索结果:\n"
945
939
  for path in results:
946
940
  output += f"""- {path}\n"""
947
941
  PrettyOutput.print(output, output_type=OutputType.INFO, lang="markdown")
948
942
 
949
943
  elif args.command == 'ask':
950
944
  response = codebase.ask_codebase(args.question, args.top_k)
951
- output = f"""Answer:\n{response}"""
945
+ output = f"""{response}"""
952
946
  PrettyOutput.print(output, output_type=OutputType.INFO)
953
947
 
954
948
  else:
jarvis/jarvis_lsp/cpp.py CHANGED
@@ -41,7 +41,7 @@ class CPPLSP(BaseLSP):
41
41
 
42
42
  return True
43
43
  except Exception as e:
44
- PrettyOutput.print(f"C++ LSP initialization failed: {str(e)}", OutputType.ERROR)
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]:
jarvis/jarvis_lsp/go.py CHANGED
@@ -47,7 +47,7 @@ class GoLSP(BaseLSP):
47
47
 
48
48
  return True
49
49
  except Exception as e:
50
- PrettyOutput.print(f"Go LSP initialization failed: {str(e)}", OutputType.ERROR)
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]:
@@ -1,8 +1,6 @@
1
- import os
2
1
  from typing import List, Dict, Optional, Tuple, Any
3
2
  import jedi
4
3
  from jarvis.jarvis_lsp.base import BaseLSP
5
- from jarvis.utils import PrettyOutput, OutputType
6
4
 
7
5
  class PythonLSP(BaseLSP):
8
6
  """Python LSP implementation using jedi."""
@@ -33,7 +33,7 @@ class LSPRegistry:
33
33
  with open(os.path.join(user_lsp_dir, "__init__.py"), "w") as f:
34
34
  pass
35
35
  except Exception as e:
36
- PrettyOutput.print(f"Create LSP directory failed: {str(e)}", OutputType.ERROR)
36
+ PrettyOutput.print(f"创建 LSP 目录失败: {str(e)}", OutputType.ERROR)
37
37
  return ""
38
38
  return user_lsp_dir
39
39
 
@@ -72,7 +72,7 @@ class LSPRegistry:
72
72
  lsp_servers = {}
73
73
 
74
74
  if not os.path.exists(directory):
75
- PrettyOutput.print(f"LSP directory does not exist: {directory}", OutputType.ERROR)
75
+ PrettyOutput.print(f"LSP 目录不存在: {directory}", OutputType.ERROR)
76
76
  return lsp_servers
77
77
 
78
78
  package_name = None
@@ -104,7 +104,7 @@ class LSPRegistry:
104
104
  lsp_servers[obj.language] = obj
105
105
  break
106
106
  except Exception as e:
107
- PrettyOutput.print(f"Load LSP {module_name} failed: {str(e)}", OutputType.ERROR)
107
+ PrettyOutput.print(f"加载 LSP {module_name} 失败: {str(e)}", OutputType.ERROR)
108
108
 
109
109
  return lsp_servers
110
110
 
@@ -138,14 +138,14 @@ class LSPRegistry:
138
138
  def create_lsp(self, language: str) -> Optional[BaseLSP]:
139
139
  """Create LSP instance for specified language."""
140
140
  if language not in self.lsp_servers:
141
- PrettyOutput.print(f"LSP not found for language: {language}", OutputType.ERROR)
141
+ PrettyOutput.print(f"没有找到 LSP 支持的语言: {language}", OutputType.ERROR)
142
142
  return None
143
143
 
144
144
  try:
145
145
  lsp = self.lsp_servers[language]()
146
146
  return lsp
147
147
  except Exception as e:
148
- PrettyOutput.print(f"Create LSP failed: {str(e)}", OutputType.ERROR)
148
+ PrettyOutput.print(f"创建 LSP 失败: {str(e)}", OutputType.ERROR)
149
149
  return None
150
150
 
151
151
  def get_supported_languages(self) -> List[str]:
@@ -186,11 +186,11 @@ def main():
186
186
  lsp = registry.create_lsp(args.language)
187
187
 
188
188
  if not lsp:
189
- PrettyOutput.print(f"No LSP support for language: {args.language}", OutputType.ERROR)
189
+ PrettyOutput.print(f"没有 LSP 支持的语言: {args.language}", OutputType.ERROR)
190
190
  return 1
191
191
 
192
192
  if not lsp.initialize(os.path.dirname(os.path.abspath(args.file))):
193
- PrettyOutput.print("LSP initialization failed", OutputType.ERROR)
193
+ PrettyOutput.print("LSP 初始化失败", OutputType.ERROR)
194
194
  return 1
195
195
 
196
196
  try:
@@ -204,26 +204,26 @@ def main():
204
204
  diagnostics = lsp.get_diagnostics(args.file)
205
205
  for diag in diagnostics:
206
206
  severity = ['Error', 'Warning', 'Info', 'Hint'][diag['severity'] - 1]
207
- print(f"{severity} at {diag['range']['start']['line']}:{diag['range']['start']['character']}: {diag['message']}")
207
+ PrettyOutput.print(f"{severity} {diag['range']['start']['line']}:{diag['range']['start']['character']}: {diag['message']}", OutputType.INFO)
208
208
 
209
209
  elif args.action in ('references', 'definition'):
210
210
  if args.line is None or args.character is None:
211
- PrettyOutput.print("Line and character position required for references/definition", OutputType.ERROR)
211
+ PrettyOutput.print("需要行和字符位置用于 references/definition", OutputType.ERROR)
212
212
  return 1
213
213
 
214
214
  if args.action == 'references':
215
215
  refs = lsp.find_references(args.file, (args.line, args.character))
216
216
  for ref in refs:
217
- print(f"Reference in {ref['uri']} at {ref['range']['start']['line']}:{ref['range']['start']['character']}\nLine: {LSPRegistry.get_line_at_position(ref['uri'], ref['range']['start']['line'])}")
217
+ 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)
218
218
  else:
219
219
  defn = lsp.find_definition(args.file, (args.line, args.character))
220
220
  if defn:
221
- print(f"Definition in {defn['uri']} at {defn['range']['start']['line']}:{defn['range']['start']['character']}\nLine: {LSPRegistry.get_line_at_position(defn['uri'], defn['range']['start']['line'])}")
221
+ 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)
222
222
  else:
223
- print("No definition found")
223
+ PrettyOutput.print("没有找到定义", OutputType.WARNING)
224
224
 
225
225
  except Exception as e:
226
- PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
226
+ PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
227
227
  return 1
228
228
  finally:
229
229
  lsp.shutdown()
jarvis/jarvis_lsp/rust.py CHANGED
@@ -49,7 +49,7 @@ class RustLSP(BaseLSP):
49
49
 
50
50
  return True
51
51
  except Exception as e:
52
- PrettyOutput.print(f"Rust LSP initialization failed: {str(e)}", OutputType.ERROR)
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]: