jarvis-ai-assistant 0.1.111__py3-none-any.whl → 0.1.113__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.
- jarvis/__init__.py +1 -1
- jarvis/agent.py +72 -41
- jarvis/jarvis_code_agent/code_agent.py +23 -5
- jarvis/jarvis_code_agent/file_select.py +16 -16
- jarvis/jarvis_code_agent/patch.py +17 -11
- jarvis/jarvis_code_agent/relevant_files.py +33 -40
- jarvis/jarvis_codebase/main.py +57 -48
- jarvis/jarvis_lsp/cpp.py +1 -1
- jarvis/jarvis_lsp/go.py +1 -1
- jarvis/jarvis_lsp/python.py +0 -2
- jarvis/jarvis_lsp/registry.py +13 -13
- jarvis/jarvis_lsp/rust.py +1 -1
- jarvis/jarvis_platform/ai8.py +14 -14
- jarvis/jarvis_platform/base.py +1 -1
- jarvis/jarvis_platform/kimi.py +17 -17
- jarvis/jarvis_platform/ollama.py +14 -14
- jarvis/jarvis_platform/openai.py +8 -8
- jarvis/jarvis_platform/oyi.py +19 -19
- jarvis/jarvis_platform/registry.py +6 -6
- jarvis/jarvis_platform_manager/main.py +17 -17
- jarvis/jarvis_rag/main.py +25 -25
- jarvis/jarvis_smart_shell/main.py +6 -6
- jarvis/jarvis_tools/ask_codebase.py +3 -3
- jarvis/jarvis_tools/ask_user.py +2 -2
- jarvis/jarvis_tools/create_code_agent.py +8 -8
- jarvis/jarvis_tools/create_sub_agent.py +2 -2
- jarvis/jarvis_tools/execute_shell.py +2 -2
- jarvis/jarvis_tools/file_operation.py +1 -1
- jarvis/jarvis_tools/git_commiter.py +8 -5
- jarvis/jarvis_tools/methodology.py +3 -3
- jarvis/jarvis_tools/rag.py +3 -3
- jarvis/jarvis_tools/read_code.py +1 -1
- jarvis/jarvis_tools/read_webpage.py +19 -6
- jarvis/jarvis_tools/registry.py +11 -11
- jarvis/jarvis_tools/search.py +88 -27
- jarvis/jarvis_tools/select_code_files.py +1 -1
- jarvis/jarvis_tools/tool_generator.py +182 -0
- jarvis/utils.py +69 -28
- jarvis_ai_assistant-0.1.113.dist-info/METADATA +460 -0
- jarvis_ai_assistant-0.1.113.dist-info/RECORD +64 -0
- jarvis_ai_assistant-0.1.111.dist-info/METADATA +0 -461
- jarvis_ai_assistant-0.1.111.dist-info/RECORD +0 -63
- {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.113.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.113.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.113.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.113.dist-info}/top_level.txt +0 -0
|
@@ -8,60 +8,54 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
|
8
8
|
from jarvis.utils import OutputType, PrettyOutput
|
|
9
9
|
|
|
10
10
|
def make_question(requirement: str) -> Optional[str]:
|
|
11
|
-
"""Generate structured questions to gather necessary information for the requirement.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
str: A formatted string containing relevant questions
|
|
18
|
-
"""
|
|
19
|
-
prompt = f"""You are a helpful assistant that generates SPECIFIC questions in English for a code analysis team. The analysis team:
|
|
20
|
-
- Has access to the codebase but NO CONTEXT about the requirement
|
|
21
|
-
- Will search and analyze code based on your questions
|
|
22
|
-
- Needs complete context to understand what to look for
|
|
11
|
+
"""Generate structured questions to gather necessary information for the requirement."""
|
|
12
|
+
prompt = f"""You are a code analysis expert who helps developers understand existing system implementations. Generate specific questions to investigate:
|
|
13
|
+
- Current system implementations
|
|
14
|
+
- Existing interfaces and integration points
|
|
15
|
+
- Extension mechanisms and patterns
|
|
16
|
+
- Related components and their interactions
|
|
23
17
|
|
|
24
18
|
Key Instructions:
|
|
25
|
-
1.
|
|
26
|
-
2.
|
|
27
|
-
3.
|
|
28
|
-
4.
|
|
19
|
+
1. Focus on understanding the EXISTING system
|
|
20
|
+
2. Ask about interfaces, hooks, and extension points
|
|
21
|
+
3. Investigate integration patterns and dependencies
|
|
22
|
+
4. Explore current implementation details
|
|
29
23
|
|
|
30
24
|
For example:
|
|
31
|
-
BAD: "How
|
|
32
|
-
GOOD: "
|
|
25
|
+
BAD: "How should we implement the new feature?"
|
|
26
|
+
GOOD: "What are the existing extension points in the authentication system that we can use to add the new OAuth provider? Specifically, how does AuthProvider interface work and where is it currently used?"
|
|
33
27
|
|
|
34
|
-
Consider these aspects
|
|
28
|
+
Consider these investigation aspects:
|
|
35
29
|
|
|
36
|
-
1.
|
|
37
|
-
- "What
|
|
38
|
-
- "
|
|
39
|
-
- "
|
|
30
|
+
1. System Architecture:
|
|
31
|
+
- "What are the existing interfaces/classes that handle [functionality]?"
|
|
32
|
+
- "How is [feature] currently integrated with other components?"
|
|
33
|
+
- "Where are the extension points for [system component]?"
|
|
40
34
|
|
|
41
|
-
2.
|
|
42
|
-
- "
|
|
43
|
-
- "
|
|
44
|
-
- "
|
|
35
|
+
2. Implementation Details:
|
|
36
|
+
- "What is the current workflow for [operation] in the system?"
|
|
37
|
+
- "How does the system expose hooks/callbacks for [functionality]?"
|
|
38
|
+
- "Which interfaces/abstract classes are used for [feature] extensibility?"
|
|
45
39
|
|
|
46
|
-
3. Integration
|
|
47
|
-
- "
|
|
48
|
-
- "What
|
|
49
|
-
- "How
|
|
40
|
+
3. Integration Patterns:
|
|
41
|
+
- "How do existing components integrate with [system part]?"
|
|
42
|
+
- "What are the current integration points for [feature]?"
|
|
43
|
+
- "How does the system handle extensions to [component]?"
|
|
50
44
|
|
|
51
|
-
4.
|
|
52
|
-
- "
|
|
53
|
-
- "
|
|
54
|
-
- "
|
|
45
|
+
4. Extension Mechanisms:
|
|
46
|
+
- "What patterns are used for extending [functionality]?"
|
|
47
|
+
- "How do existing plugins/extensions connect to [system]?"
|
|
48
|
+
- "Where are the configuration points for [feature] customization?"
|
|
55
49
|
|
|
56
50
|
User Requirement:
|
|
57
51
|
{requirement}
|
|
58
52
|
|
|
59
53
|
Output Format:
|
|
60
54
|
<QUESTION>
|
|
61
|
-
[Write 3-5 specific questions
|
|
55
|
+
[Write 3-5 specific questions focusing on existing implementations and extension points. Each question should help understand how to integrate with or extend the current system]
|
|
62
56
|
</QUESTION>
|
|
63
57
|
"""
|
|
64
|
-
model = PlatformRegistry().
|
|
58
|
+
model = PlatformRegistry().get_thinking_platform()
|
|
65
59
|
response = model.chat_until_success(prompt)
|
|
66
60
|
response = re.search(r'<QUESTION>(.*?)</QUESTION>', response, re.DOTALL)
|
|
67
61
|
if response is None:
|
|
@@ -71,16 +65,15 @@ Output Format:
|
|
|
71
65
|
|
|
72
66
|
def find_relevant_information(user_input: str, root_dir: str) -> Tuple[List[Dict[str, str]], str]:
|
|
73
67
|
try:
|
|
74
|
-
PrettyOutput.print("
|
|
68
|
+
PrettyOutput.print("从代码库中查找文件...", OutputType.INFO)
|
|
75
69
|
codebase = CodeBase(root_dir)
|
|
76
70
|
question = make_question(user_input)
|
|
77
71
|
if question is None:
|
|
78
72
|
return [], ""
|
|
79
73
|
files_from_codebase, infomation = codebase.ask_codebase(question)
|
|
80
|
-
PrettyOutput.print("Find files by agent...", OutputType.INFO)
|
|
81
74
|
|
|
82
75
|
selected_files = select_files(files_from_codebase, os.getcwd())
|
|
83
76
|
return selected_files, infomation
|
|
84
77
|
except Exception:
|
|
85
|
-
PrettyOutput.print("
|
|
78
|
+
PrettyOutput.print("查找相关文件失败", OutputType.ERROR)
|
|
86
79
|
return [], ""
|
jarvis/jarvis_codebase/main.py
CHANGED
|
@@ -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("
|
|
40
|
+
PrettyOutput.print("模型加载成功", output_type=OutputType.SUCCESS)
|
|
41
41
|
except Exception as e:
|
|
42
|
-
PrettyOutput.print(f"
|
|
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"
|
|
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"
|
|
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"
|
|
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("
|
|
149
|
+
PrettyOutput.print("没有找到有效的缓存文件", output_type=OutputType.WARNING)
|
|
150
150
|
|
|
151
151
|
except Exception as e:
|
|
152
|
-
PrettyOutput.print(f"
|
|
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"
|
|
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"
|
|
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"
|
|
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"
|
|
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"
|
|
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"
|
|
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"
|
|
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"
|
|
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"
|
|
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"
|
|
345
|
+
PrettyOutput.print(f"成功构建包含 {len(vectors)} 个向量的索引",
|
|
346
346
|
output_type=OutputType.SUCCESS)
|
|
347
347
|
except Exception as e:
|
|
348
|
-
PrettyOutput.print(f"
|
|
348
|
+
PrettyOutput.print(f"添加向量到索引失败: {str(e)}",
|
|
349
349
|
output_type=OutputType.ERROR)
|
|
350
350
|
self.index = None
|
|
351
351
|
else:
|
|
352
|
-
PrettyOutput.print("
|
|
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"
|
|
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"
|
|
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"
|
|
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("
|
|
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"
|
|
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 = ["
|
|
433
|
+
output_lines = ["检测到以下变化:"]
|
|
434
434
|
if new_files:
|
|
435
|
-
output_lines.append("
|
|
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("
|
|
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("
|
|
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("
|
|
449
|
-
PrettyOutput.print("
|
|
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"
|
|
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("
|
|
485
|
+
PrettyOutput.print("重建向量数据库...", output_type=OutputType.INFO)
|
|
486
486
|
self.gen_vector_db_from_cache()
|
|
487
|
-
PrettyOutput.print(f"
|
|
487
|
+
PrettyOutput.print(f"成功生成了 {len(processed_files)} 个文件的索引",
|
|
488
488
|
output_type=OutputType.SUCCESS)
|
|
489
489
|
else:
|
|
490
|
-
PrettyOutput.print("
|
|
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"
|
|
497
|
+
PrettyOutput.print(f"保存缓存失败: {str(save_error)}",
|
|
498
498
|
output_type=OutputType.ERROR)
|
|
499
499
|
raise e # Re-raise the original exception
|
|
500
500
|
|
|
@@ -574,7 +574,7 @@ Content: {content}
|
|
|
574
574
|
current_token_count += tokens_count
|
|
575
575
|
|
|
576
576
|
except Exception as e:
|
|
577
|
-
PrettyOutput.print(f"
|
|
577
|
+
PrettyOutput.print(f"读取 {path} 失败: {str(e)}", OutputType.ERROR)
|
|
578
578
|
continue
|
|
579
579
|
|
|
580
580
|
# Process final batch
|
|
@@ -586,7 +586,7 @@ Content: {content}
|
|
|
586
586
|
return all_selected_files
|
|
587
587
|
|
|
588
588
|
except Exception as e:
|
|
589
|
-
PrettyOutput.print(f"
|
|
589
|
+
PrettyOutput.print(f"选择失败: {str(e)}", OutputType.ERROR)
|
|
590
590
|
return [{"file": f, "reason": "" } for f in initial_results]
|
|
591
591
|
|
|
592
592
|
def _process_batch(self, query: str, files_info: List[str]) -> List[Dict[str, str]]:
|
|
@@ -639,7 +639,7 @@ Important:
|
|
|
639
639
|
selected_files = yaml.safe_load(files_match.group(1))
|
|
640
640
|
return selected_files if selected_files else []
|
|
641
641
|
except Exception as e:
|
|
642
|
-
PrettyOutput.print(f"
|
|
642
|
+
PrettyOutput.print(f"解析响应失败: {str(e)}", OutputType.ERROR)
|
|
643
643
|
return []
|
|
644
644
|
|
|
645
645
|
def _generate_query_variants(self, query: str) -> List[str]:
|
|
@@ -687,7 +687,7 @@ Please provide 10 search-optimized expressions in the specified format.
|
|
|
687
687
|
try:
|
|
688
688
|
variants = yaml.safe_load(question_match.group(1))
|
|
689
689
|
except Exception as e:
|
|
690
|
-
PrettyOutput.print(f"
|
|
690
|
+
PrettyOutput.print(f"解析变体失败: {str(e)}", OutputType.ERROR)
|
|
691
691
|
|
|
692
692
|
# Add original query
|
|
693
693
|
variants.append(query)
|
|
@@ -776,7 +776,7 @@ Please provide 10 search-optimized expressions in the specified format.
|
|
|
776
776
|
return results
|
|
777
777
|
|
|
778
778
|
except Exception as e:
|
|
779
|
-
PrettyOutput.print(f"
|
|
779
|
+
PrettyOutput.print(f"搜索失败: {str(e)}", output_type=OutputType.ERROR)
|
|
780
780
|
return []
|
|
781
781
|
|
|
782
782
|
def ask_codebase(self, query: str, top_k: int=20) -> Tuple[List[Dict[str, str]], str]:
|
|
@@ -784,7 +784,7 @@ Please provide 10 search-optimized expressions in the specified format.
|
|
|
784
784
|
files_from_codebase = self.search_similar(query, top_k)
|
|
785
785
|
|
|
786
786
|
if not files_from_codebase:
|
|
787
|
-
PrettyOutput.print("
|
|
787
|
+
PrettyOutput.print("没有找到相关文件", output_type=OutputType.WARNING)
|
|
788
788
|
return [],""
|
|
789
789
|
|
|
790
790
|
# Build enhanced prompt
|
|
@@ -817,7 +817,7 @@ Content:
|
|
|
817
817
|
"""
|
|
818
818
|
if current_count + get_context_token_count(file_content) > available_count:
|
|
819
819
|
PrettyOutput.print(
|
|
820
|
-
"
|
|
820
|
+
"由于上下文长度限制, 一些文件被省略",
|
|
821
821
|
output_type=OutputType.WARNING
|
|
822
822
|
)
|
|
823
823
|
break
|
|
@@ -826,11 +826,20 @@ Content:
|
|
|
826
826
|
current_count += get_context_token_count(file_content)
|
|
827
827
|
|
|
828
828
|
except Exception as e:
|
|
829
|
-
PrettyOutput.print(f"
|
|
829
|
+
PrettyOutput.print(f"读取 {path} 失败: {str(e)}",
|
|
830
830
|
output_type=OutputType.ERROR)
|
|
831
831
|
continue
|
|
832
832
|
|
|
833
833
|
model = PlatformRegistry.get_global_platform_registry().get_thinking_platform()
|
|
834
|
+
|
|
835
|
+
prompt += """
|
|
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
|
|
841
|
+
"""
|
|
842
|
+
|
|
834
843
|
return files_from_codebase, model.chat_until_success(prompt)
|
|
835
844
|
|
|
836
845
|
def is_index_generated(self) -> bool:
|
|
@@ -871,7 +880,7 @@ Content:
|
|
|
871
880
|
return True
|
|
872
881
|
|
|
873
882
|
except Exception as e:
|
|
874
|
-
PrettyOutput.print(f"
|
|
883
|
+
PrettyOutput.print(f"检查索引状态失败: {str(e)}",
|
|
875
884
|
output_type=OutputType.ERROR)
|
|
876
885
|
return False
|
|
877
886
|
|
|
@@ -916,17 +925,17 @@ def main():
|
|
|
916
925
|
if args.command == 'generate':
|
|
917
926
|
try:
|
|
918
927
|
codebase.generate_codebase(force=args.force)
|
|
919
|
-
PrettyOutput.print("
|
|
928
|
+
PrettyOutput.print("代码库生成完成", output_type=OutputType.SUCCESS)
|
|
920
929
|
except Exception as e:
|
|
921
|
-
PrettyOutput.print(f"
|
|
930
|
+
PrettyOutput.print(f"代码库生成失败: {str(e)}", output_type=OutputType.ERROR)
|
|
922
931
|
|
|
923
932
|
elif args.command == 'search':
|
|
924
933
|
results = codebase.search_similar(args.query, args.top_k)
|
|
925
934
|
if not results:
|
|
926
|
-
PrettyOutput.print("
|
|
935
|
+
PrettyOutput.print("没有找到相似的文件", output_type=OutputType.WARNING)
|
|
927
936
|
return
|
|
928
937
|
|
|
929
|
-
output = "
|
|
938
|
+
output = "搜索结果:\n"
|
|
930
939
|
for path in results:
|
|
931
940
|
output += f"""- {path}\n"""
|
|
932
941
|
PrettyOutput.print(output, output_type=OutputType.INFO, lang="markdown")
|
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
|
|
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
|
|
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]:
|
jarvis/jarvis_lsp/python.py
CHANGED
jarvis/jarvis_lsp/registry.py
CHANGED
|
@@ -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"
|
|
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
|
|
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"
|
|
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
|
|
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"
|
|
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"
|
|
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
|
|
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}
|
|
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("
|
|
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"
|
|
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"
|
|
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("
|
|
223
|
+
PrettyOutput.print("没有找到定义", OutputType.WARNING)
|
|
224
224
|
|
|
225
225
|
except Exception as e:
|
|
226
|
-
PrettyOutput.print(f"
|
|
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
|
|
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]:
|