jarvis-ai-assistant 0.1.111__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 (46) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +40 -34
  3. jarvis/jarvis_code_agent/code_agent.py +23 -5
  4. jarvis/jarvis_code_agent/file_select.py +16 -16
  5. jarvis/jarvis_code_agent/patch.py +17 -11
  6. jarvis/jarvis_code_agent/relevant_files.py +33 -40
  7. jarvis/jarvis_codebase/main.py +57 -48
  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 +3 -3
  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 -4
  30. jarvis/jarvis_tools/methodology.py +3 -3
  31. jarvis/jarvis_tools/rag.py +3 -3
  32. jarvis/jarvis_tools/read_code.py +1 -1
  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.py +18 -20
  39. jarvis_ai_assistant-0.1.112.dist-info/METADATA +460 -0
  40. jarvis_ai_assistant-0.1.112.dist-info/RECORD +64 -0
  41. jarvis_ai_assistant-0.1.111.dist-info/METADATA +0 -461
  42. jarvis_ai_assistant-0.1.111.dist-info/RECORD +0 -63
  43. {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/LICENSE +0 -0
  44. {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/WHEEL +0 -0
  45. {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/entry_points.txt +0 -0
  46. {jarvis_ai_assistant-0.1.111.dist-info → jarvis_ai_assistant-0.1.112.dist-info}/top_level.txt +0 -0
jarvis/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.111"
3
+ __version__ = "0.1.112"
jarvis/agent.py CHANGED
@@ -39,6 +39,7 @@ class Agent:
39
39
  auto_complete: Optional[bool] = None,
40
40
  output_handler_before_tool: Optional[List[Callable]] = None,
41
41
  output_handler_after_tool: Optional[List[Callable]] = None,
42
+ input_handler: Optional[List[Callable]] = None,
42
43
  use_methodology: Optional[bool] = None,
43
44
  record_methodology: Optional[bool] = None,
44
45
  need_summary: Optional[bool] = None,
@@ -61,7 +62,7 @@ class Agent:
61
62
  need_summary: Whether to generate summaries
62
63
  max_context_length: Maximum context length
63
64
  """
64
- PrettyOutput.print(f"Welcome to Jarvis, your AI assistant, Initiating...", OutputType.SYSTEM)
65
+ PrettyOutput.print(f"欢迎使用Jarvis,你的AI助手,正在初始化...", OutputType.SYSTEM)
65
66
  if platform is not None:
66
67
  self.model = platform
67
68
  else:
@@ -75,6 +76,7 @@ class Agent:
75
76
  self.conversation_length = 0 # Use length counter instead
76
77
  self.system_prompt = system_prompt
77
78
  self.need_summary = need_summary if need_summary is not None else is_need_summary()
79
+ self.input_handler = input_handler if input_handler is not None else []
78
80
  # Load configuration from environment variables
79
81
  self.output_handler_before_tool = output_handler_before_tool if output_handler_before_tool else []
80
82
  self.output_handler_after_tool = output_handler_after_tool if output_handler_after_tool else []
@@ -96,11 +98,11 @@ Please describe in concise bullet points, highlighting important information.
96
98
 
97
99
  self.auto_complete = auto_complete if auto_complete is not None else is_auto_complete()
98
100
 
99
- PrettyOutput.section(f"Jarvis initialized - With {self.model.name()}", OutputType.SYSTEM)
101
+ PrettyOutput.section(f"Jarvis 初始化完成 - 使用 {self.model.name()} 模型", OutputType.SYSTEM)
100
102
 
101
103
  tools = self.tool_registry.get_all_tools()
102
104
  if tools:
103
- PrettyOutput.section(f"Available tools: {', '.join([tool['name'] for tool in tools])}", OutputType.SYSTEM)
105
+ PrettyOutput.section(f"可用工具: {', '.join([tool['name'] for tool in tools])}", OutputType.SYSTEM)
104
106
 
105
107
 
106
108
  tools_prompt = self.tool_registry.load_tools()
@@ -181,12 +183,16 @@ Please describe in concise bullet points, highlighting important information.
181
183
  Will retry with exponential backoff up to 30 seconds between retries
182
184
  """
183
185
  sleep_time = 5
186
+
187
+ for handler in self.input_handler:
188
+ message = handler(message)
189
+
184
190
  while True:
185
191
  ret = self.model.chat_until_success(message)
186
192
  if ret:
187
193
  return ret
188
194
  else:
189
- PrettyOutput.print(f"Model call failed, retrying... waiting {sleep_time}s", OutputType.INFO)
195
+ PrettyOutput.print(f"模型调用失败,正在重试... 等待 {sleep_time}s", OutputType.INFO)
190
196
  time.sleep(sleep_time)
191
197
  sleep_time *= 2
192
198
  if sleep_time > 30:
@@ -209,7 +215,7 @@ Please describe in concise bullet points, highlighting important information.
209
215
  """
210
216
  # Create a new model instance to summarize, avoid affecting the main conversation
211
217
 
212
- PrettyOutput.print("Summarizing conversation history, preparing to generate summary, starting new conversation...", OutputType.PROGRESS)
218
+ PrettyOutput.print("总结对话历史,准备生成摘要,开始新对话...", OutputType.PROGRESS)
213
219
 
214
220
  prompt = """Please summarize the key information from the previous conversation, including:
215
221
  1. Current task objective
@@ -222,7 +228,7 @@ Please describe in concise bullet points, highlighting important information. Do
222
228
  """
223
229
 
224
230
  try:
225
- summary = self.model.chat_until_success(self.prompt + "\n" + prompt)
231
+ summary = self._call_model(self.prompt + "\n" + prompt)
226
232
 
227
233
  # 清空当前对话历史,但保留系统消息
228
234
  self.conversation_length = 0 # Reset conversation length
@@ -237,7 +243,7 @@ Please continue the task based on the above information.
237
243
  self.conversation_length = len(self.prompt) # 设置新的起始长度
238
244
 
239
245
  except Exception as e:
240
- PrettyOutput.print(f"Failed to summarize conversation history: {str(e)}", OutputType.ERROR)
246
+ PrettyOutput.print(f"总结对话历史失败: {str(e)}", OutputType.ERROR)
241
247
 
242
248
  def _complete_task(self) -> str:
243
249
  """Complete the current task and generate summary if needed.
@@ -249,7 +255,7 @@ Please continue the task based on the above information.
249
255
  - For main agent: May generate methodology if enabled
250
256
  - For sub-agent: May generate summary if enabled
251
257
  """
252
- PrettyOutput.section("Task completed", OutputType.SUCCESS)
258
+ PrettyOutput.section("任务完成", OutputType.SUCCESS)
253
259
 
254
260
  if not self.is_sub_agent:
255
261
  if self.record_methodology:
@@ -272,18 +278,18 @@ Please continue the task based on the above information.
272
278
  if tool_calls:
273
279
  self.tool_registry.handle_tool_calls(tool_calls)
274
280
  except Exception as e:
275
- PrettyOutput.print(f"Failed to handle methodology generation: {str(e)}", OutputType.ERROR)
281
+ PrettyOutput.print(f"处理方法论生成失败: {str(e)}", OutputType.ERROR)
276
282
 
277
283
  except Exception as e:
278
- PrettyOutput.print(f"Error generating methodology: {str(e)}", OutputType.ERROR)
284
+ PrettyOutput.print(f"生成方法论失败: {str(e)}", OutputType.ERROR)
279
285
 
280
- return "Task completed"
286
+ return "任务完成"
281
287
 
282
288
  if self.need_summary:
283
289
  self.prompt = self.summary_prompt
284
290
  return self._call_model(self.prompt)
285
291
 
286
- return "Task completed"
292
+ return "任务完成"
287
293
 
288
294
 
289
295
  def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str:
@@ -306,12 +312,12 @@ Please continue the task based on the above information.
306
312
  add_agent(self.name)
307
313
 
308
314
  try:
309
- PrettyOutput.section("Preparing environment", OutputType.PLANNING)
315
+ PrettyOutput.section("准备环境", OutputType.PLANNING)
310
316
  if file_list:
311
317
  self.model.upload_files(file_list)
312
318
 
313
319
  # 显示任务开始
314
- PrettyOutput.section(f"Starting new task: {self.name}", OutputType.PLANNING)
320
+ PrettyOutput.section(f"开始新任务: {self.name}", OutputType.PLANNING)
315
321
 
316
322
  if self.first and self.use_methodology:
317
323
  self.prompt = f"{user_input}\n\n{load_methodology(user_input)}"
@@ -322,7 +328,7 @@ Please continue the task based on the above information.
322
328
  while True:
323
329
  try:
324
330
  # 显示思考状态
325
- PrettyOutput.print("Analyzing task...", OutputType.PROGRESS)
331
+ PrettyOutput.print("正在分析任务...", OutputType.PROGRESS)
326
332
 
327
333
  # 累加对话长度
328
334
  self.conversation_length += get_context_token_count(self.prompt)
@@ -342,13 +348,13 @@ Please continue the task based on the above information.
342
348
  try:
343
349
  result = Agent._extract_tool_calls(current_response)
344
350
  except Exception as e:
345
- PrettyOutput.print(f"Tool call error: {str(e)}", OutputType.ERROR)
351
+ PrettyOutput.print(f"工具调用错误: {str(e)}", OutputType.ERROR)
346
352
  self.prompt += f"Tool call error: {str(e)}"
347
353
  continue
348
354
 
349
355
  if len(result) > 0:
350
- if not self.execute_tool_confirm or user_confirm(f"Execute tool call: {result[0]['name']}?"):
351
- PrettyOutput.print("Executing tool call...", OutputType.PROGRESS)
356
+ if not self.execute_tool_confirm or user_confirm(f"执行工具调用: {result[0]['name']}?"):
357
+ PrettyOutput.print("正在执行工具调用...", OutputType.PROGRESS)
352
358
  tool_result = self.tool_registry.handle_tool_calls(result)
353
359
  self.prompt += tool_result
354
360
 
@@ -362,7 +368,7 @@ Please continue the task based on the above information.
362
368
  return self._complete_task()
363
369
 
364
370
  # 获取用户输入
365
- user_input = get_multiline_input(f"{self.name}: You can continue to input, or enter an empty line to end the current task")
371
+ user_input = get_multiline_input(f"{self.name}: 您可以继续输入,或输入空行来结束当前任务:")
366
372
 
367
373
  if user_input:
368
374
  self.prompt = user_input
@@ -372,11 +378,11 @@ Please continue the task based on the above information.
372
378
  return self._complete_task()
373
379
 
374
380
  except Exception as e:
375
- PrettyOutput.print(str(e), OutputType.ERROR)
381
+ PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
376
382
  return f"Task failed: {str(e)}"
377
383
 
378
384
  except Exception as e:
379
- PrettyOutput.print(str(e), OutputType.ERROR)
385
+ PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
380
386
  return f"Task failed: {str(e)}"
381
387
 
382
388
  finally:
@@ -414,9 +420,9 @@ def _load_tasks() -> dict:
414
420
  if desc: # Ensure description is not empty
415
421
  tasks[str(name)] = str(desc)
416
422
  else:
417
- PrettyOutput.print("Warning: ~/.jarvis/pre-command file should contain a dictionary of task_name: task_description", OutputType.ERROR)
423
+ PrettyOutput.print("警告: ~/.jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.ERROR)
418
424
  except Exception as e:
419
- PrettyOutput.print(f"Error loading ~/.jarvis/pre-command file: {str(e)}", OutputType.ERROR)
425
+ PrettyOutput.print(f"加载 ~/.jarvis/pre-command 文件失败: {str(e)}", OutputType.ERROR)
420
426
 
421
427
  # Check .jarvis/pre-command in current directory
422
428
  if os.path.exists(".jarvis/pre-command"):
@@ -430,9 +436,9 @@ def _load_tasks() -> dict:
430
436
  if desc: # Ensure description is not empty
431
437
  tasks[str(name)] = str(desc)
432
438
  else:
433
- PrettyOutput.print("Warning: .jarvis/pre-command file should contain a dictionary of task_name: task_description", OutputType.ERROR)
439
+ PrettyOutput.print("警告: .jarvis/pre-command 文件应该包含一个字典,键为任务名称,值为任务描述", OutputType.ERROR)
434
440
  except Exception as e:
435
- PrettyOutput.print(f"Error loading .jarvis/pre-command file: {str(e)}", OutputType.ERROR)
441
+ PrettyOutput.print(f"加载 .jarvis/pre-command 文件失败: {str(e)}", OutputType.ERROR)
436
442
 
437
443
 
438
444
  if is_use_methodology():
@@ -455,17 +461,17 @@ def _select_task(tasks: dict) -> str:
455
461
  # Convert tasks to list for ordered display
456
462
  task_names = list(tasks.keys())
457
463
 
458
- task_list = ["Available tasks:"]
464
+ task_list = ["可用任务:"]
459
465
  for i, name in enumerate(task_names, 1):
460
466
  task_list.append(f"[{i}] {name}")
461
- task_list.append("[0] Skip predefined tasks")
467
+ task_list.append("[0] 跳过预定义任务")
462
468
  PrettyOutput.print("\n".join(task_list), OutputType.INFO)
463
469
 
464
470
 
465
471
  while True:
466
472
  try:
467
473
  choice = prompt(
468
- "\nPlease select a task number (0 to skip): ",
474
+ "\n请选择一个任务编号(0 跳过预定义任务):",
469
475
  ).strip()
470
476
 
471
477
  if not choice:
@@ -478,14 +484,14 @@ def _select_task(tasks: dict) -> str:
478
484
  selected_name = task_names[choice - 1]
479
485
  return tasks[selected_name] # Return the task description
480
486
  else:
481
- PrettyOutput.print("Invalid choice. Please select a number from the list.", OutputType.ERROR)
487
+ PrettyOutput.print("无效的选择。请选择列表中的一个号码。", OutputType.ERROR)
482
488
 
483
489
  except KeyboardInterrupt:
484
490
  return "" # Return empty on Ctrl+C
485
491
  except EOFError:
486
492
  return "" # Return empty on Ctrl+D
487
493
  except Exception as e:
488
- PrettyOutput.print(f"Failed to select task: {str(e)}", OutputType.ERROR)
494
+ PrettyOutput.print(f"选择任务失败: {str(e)}", OutputType.ERROR)
489
495
  continue
490
496
 
491
497
  origin_agent_system_prompt = """You are Jarvis, an AI assistant with powerful problem-solving capabilities.
@@ -529,22 +535,22 @@ def main():
529
535
  if tasks:
530
536
  selected_task = _select_task(tasks)
531
537
  if selected_task:
532
- PrettyOutput.print(f"\nExecute task: {selected_task}", OutputType.INFO)
538
+ PrettyOutput.print(f"执行任务: {selected_task}", OutputType.INFO)
533
539
  agent.run(selected_task, args.files)
534
540
  return 0
535
541
 
536
542
  # 如果没有选择预定义任务,进入交互模式
537
543
  while True:
538
544
  try:
539
- user_input = get_multiline_input("Please enter your task (input empty line to exit):")
545
+ user_input = get_multiline_input("请输入你的任务(输入空行退出):")
540
546
  if not user_input:
541
547
  break
542
548
  agent.run(user_input, args.files)
543
549
  except Exception as e:
544
- PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
550
+ PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
545
551
 
546
552
  except Exception as e:
547
- PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
553
+ PrettyOutput.print(f"初始化错误: {str(e)}", OutputType.ERROR)
548
554
  return 1
549
555
 
550
556
  return 0
@@ -34,9 +34,24 @@ class CodeAgent:
34
34
  3. Map out affected components and their interactions
35
35
  4. Plan changes that maintain system integrity
36
36
 
37
+ # Code Completeness Requirements
38
+ 1. Implementation Must Be Complete
39
+ • NO TODOs or placeholder comments
40
+ • NO unfinished functions
41
+ • NO stub implementations
42
+ • All error cases must be handled
43
+ • All edge cases must be covered
44
+
45
+ 2. Documentation Must Be Complete
46
+ • All functions must have docstrings
47
+ • All parameters must be documented
48
+ • Return values must be specified
49
+ • Exceptions must be documented
50
+ • Complex logic must be explained
51
+
37
52
  # Patch Format
38
53
  <PATCH>
39
- > /path/file start,end
54
+ > path/file start,end
40
55
  new_content
41
56
  </PATCH>
42
57
 
@@ -84,6 +99,7 @@ Key Rules:
84
99
  • Follow existing patterns exactly
85
100
  • Preserve all interfaces
86
101
  • Maintain backward compatibility
102
+ • Implement completely - no TODOs
87
103
 
88
104
  # File Handling
89
105
  Large Files (>200 lines):
@@ -105,7 +121,9 @@ Every Change Must:
105
121
  ✓ Match existing style exactly
106
122
  ✓ Handle errors consistently
107
123
  ✓ Maintain documentation
108
- ✓ Follow project patterns"""
124
+ ✓ Follow project patterns
125
+ ✓ Be completely implemented
126
+ ✓ Have no TODOs or stubs"""
109
127
  self.agent = Agent(system_prompt=code_system_prompt,
110
128
  name="CodeAgent",
111
129
  auto_complete=False,
@@ -196,17 +214,17 @@ def main():
196
214
  # Interactive mode
197
215
  while True:
198
216
  try:
199
- user_input = get_multiline_input("Please enter your requirement (input empty line to exit):")
217
+ user_input = get_multiline_input("请输入你的需求(输入空行退出):")
200
218
  if not user_input:
201
219
  break
202
220
  agent = CodeAgent()
203
221
  agent.run(user_input)
204
222
 
205
223
  except Exception as e:
206
- PrettyOutput.print(f"Error: {str(e)}", OutputType.ERROR)
224
+ PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
207
225
 
208
226
  except Exception as e:
209
- PrettyOutput.print(f"Initialization error: {str(e)}", OutputType.ERROR)
227
+ PrettyOutput.print(f"初始化错误: {str(e)}", OutputType.ERROR)
210
228
  return 1
211
229
 
212
230
  return 0
@@ -42,7 +42,7 @@ def _parse_file_selection(input_str: str, max_index: int) -> List[int]:
42
42
  if start <= end:
43
43
  selected.update(range(start, end + 1))
44
44
  except ValueError:
45
- PrettyOutput.print(f"Ignore invalid range expression: {part}", OutputType.WARNING)
45
+ PrettyOutput.print(f"忽略无效的范围表达式: {part}", OutputType.WARNING)
46
46
  # Process single number
47
47
  else:
48
48
  try:
@@ -50,9 +50,9 @@ def _parse_file_selection(input_str: str, max_index: int) -> List[int]:
50
50
  if 0 <= index < max_index:
51
51
  selected.add(index)
52
52
  else:
53
- PrettyOutput.print(f"Ignore index out of range: {part}", OutputType.WARNING)
53
+ PrettyOutput.print(f"忽略超出范围的索引: {part}", OutputType.WARNING)
54
54
  except ValueError:
55
- PrettyOutput.print(f"Ignore invalid number: {part}", OutputType.WARNING)
55
+ PrettyOutput.print(f"忽略无效的数字: {part}", OutputType.WARNING)
56
56
 
57
57
  return sorted(list(selected))
58
58
 
@@ -127,8 +127,8 @@ def _fuzzy_match_files(root_dir: str, pattern: str) -> List[str]:
127
127
 
128
128
  def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dict[str, str]]:
129
129
  """Let the user select and supplement related files"""
130
- PrettyOutput.section("Related files", OutputType.INFO)
131
-
130
+ PrettyOutput.section("相关文件", OutputType.INFO)
131
+
132
132
  output = ""
133
133
  # Display found files
134
134
  selected_files = list(related_files) # Default select all
@@ -139,18 +139,18 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
139
139
 
140
140
  if len(related_files) > 0:
141
141
  # Ask the user if they need to adjust the file list
142
- if user_confirm("Do you need to adjust the file list?", False):
142
+ if user_confirm("是否需要调整文件列表?", False):
143
143
  # Let the user select files
144
- numbers = get_single_line_input("Please enter the file numbers to include (support: 1,3-6 format, press Enter to keep the current selection)").strip()
144
+ numbers = get_single_line_input("请输入要包含的文件编号(支持: 1,3-6格式, 按回车保持当前选择)").strip()
145
145
  if numbers:
146
146
  selected_indices = _parse_file_selection(numbers, len(related_files))
147
147
  if selected_indices:
148
148
  selected_files = [related_files[i] for i in selected_indices]
149
149
  else:
150
- PrettyOutput.print("No valid files selected, keep the current selection", OutputType.WARNING)
150
+ PrettyOutput.print("没有有效的文件被选择, 保持当前选择", OutputType.WARNING)
151
151
 
152
152
  # Ask if they need to supplement files
153
- if user_confirm("Do you need to supplement other files?", False):
153
+ if user_confirm("是否需要补充其他文件?", False):
154
154
  # Create file completion session
155
155
  session = PromptSession(
156
156
  completer=_get_file_completer(root_dir),
@@ -158,7 +158,7 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
158
158
  )
159
159
 
160
160
  while True:
161
- PrettyOutput.print("Please enter the file path to supplement (support Tab completion and *? wildcard, input empty line to end):", OutputType.INFO)
161
+ PrettyOutput.print("请输入要补充的文件路径(支持Tab补全和*?通配符, 输入空行结束)", OutputType.INFO)
162
162
  try:
163
163
  file_path = session.prompt(">>> ").strip()
164
164
  except KeyboardInterrupt:
@@ -171,16 +171,16 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
171
171
  if '*' in file_path or '?' in file_path:
172
172
  matches = _fuzzy_match_files(root_dir, file_path)
173
173
  if not matches:
174
- PrettyOutput.print("No matching files found", OutputType.WARNING)
174
+ PrettyOutput.print("没有找到匹配的文件", OutputType.WARNING)
175
175
  continue
176
176
 
177
177
  # Display matching files
178
- PrettyOutput.print("Found the following matching files:", OutputType.INFO)
178
+ PrettyOutput.print("找到以下匹配的文件:", OutputType.INFO)
179
179
  for i, path in enumerate(matches, 1):
180
180
  PrettyOutput.print(f"[{i}] {path}", OutputType.INFO)
181
181
 
182
182
  # Let the user select
183
- numbers = get_single_line_input("Please select the file numbers to add (support: 1,3-6 format, press Enter to select all)").strip()
183
+ numbers = get_single_line_input("请选择要添加的文件编号(支持: 1,3-6格式, 按回车选择所有)").strip()
184
184
  if numbers:
185
185
  indices = _parse_file_selection(numbers, len(matches))
186
186
  if not indices:
@@ -195,13 +195,13 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
195
195
  for path in paths_to_add:
196
196
  full_path = os.path.join(root_dir, path)
197
197
  if not os.path.isfile(full_path):
198
- PrettyOutput.print(f"File does not exist: {path}", OutputType.ERROR)
198
+ PrettyOutput.print(f"文件不存在: {path}", OutputType.ERROR)
199
199
  continue
200
200
 
201
201
  try:
202
202
  selected_files.append({"file": path, "reason": "User Added"})
203
- PrettyOutput.print(f"File added: {path}", OutputType.SUCCESS)
203
+ PrettyOutput.print(f"文件已添加: {path}", OutputType.SUCCESS)
204
204
  except Exception as e:
205
- PrettyOutput.print(f"Failed to read file: {str(e)}", OutputType.ERROR)
205
+ PrettyOutput.print(f"读取文件失败: {str(e)}", OutputType.ERROR)
206
206
 
207
207
  return selected_files
@@ -2,13 +2,13 @@ import re
2
2
  from typing import Dict, Any, List
3
3
  import os
4
4
  from jarvis.jarvis_tools.git_commiter import GitCommitTool
5
- from jarvis.utils import OutputType, PrettyOutput, has_uncommitted_changes, user_confirm
5
+ from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, user_confirm
6
6
 
7
7
 
8
8
  def _parse_patch(patch_str: str) -> Dict[str, List[Dict[str, Any]]]:
9
9
  """Parse patches from string with format:
10
10
  <PATCH>
11
- > /path/to/file start_line,end_line
11
+ > path/to/file start_line,end_line
12
12
  content_line1
13
13
  content_line2
14
14
  ...
@@ -77,12 +77,12 @@ def apply_patch(output_str: str)->str:
77
77
  # Write new file
78
78
  with open(filepath, 'w', encoding='utf-8') as f:
79
79
  f.writelines(new_content)
80
- PrettyOutput.print(f"Created new file {filepath} successfully\n", OutputType.SUCCESS)
80
+ PrettyOutput.print(f"成功创建新文件 {filepath}", OutputType.SUCCESS)
81
81
  continue
82
82
 
83
83
  # Regular patch logic for existing files
84
84
  if not os.path.exists(filepath):
85
- PrettyOutput.print(f"File not found: {filepath}", OutputType.WARNING)
85
+ PrettyOutput.print(f"文件不存在: {filepath}", OutputType.WARNING)
86
86
  continue
87
87
 
88
88
  # Read original file content
@@ -90,7 +90,7 @@ def apply_patch(output_str: str)->str:
90
90
 
91
91
  # Validate line numbers
92
92
  if start_line < 0 or end_line > len(lines) + 1 or start_line > end_line:
93
- PrettyOutput.print(f"Invalid line range [{start_line}, {end_line}) for file: {filepath}", OutputType.WARNING)
93
+ PrettyOutput.print(f"无效的行范围 [{start_line}, {end_line}) 对于文件: {filepath}", OutputType.WARNING)
94
94
  continue
95
95
 
96
96
  # Create new content
@@ -99,15 +99,21 @@ def apply_patch(output_str: str)->str:
99
99
  # Write back to file
100
100
  open(filepath, 'w', encoding='utf-8').writelines(lines)
101
101
 
102
- PrettyOutput.print(f"Applied patch to {filepath} successfully\n", OutputType.SUCCESS)
102
+ PrettyOutput.print(f"成功应用补丁到 {filepath}", OutputType.SUCCESS)
103
103
 
104
104
  except Exception as e:
105
- PrettyOutput.print(f"Error applying patch to {filepath}: {str(e)}", OutputType.ERROR)
105
+ PrettyOutput.print(f"应用补丁到 {filepath} 失败: {str(e)}", OutputType.ERROR)
106
106
  continue
107
-
107
+ ret = ""
108
108
  if has_uncommitted_changes():
109
- handle_commit_workflow()
110
- return ""
109
+ if handle_commit_workflow():
110
+ ret += "Successfully applied the patch"
111
+ else:
112
+ ret += "User rejected the patch"
113
+ user_input = get_multiline_input("你可以继续输入: ")
114
+ if user_input:
115
+ ret += user_input
116
+ return ret
111
117
 
112
118
  def handle_commit_workflow()->bool:
113
119
  """Handle the git commit workflow and return the commit details.
@@ -119,7 +125,7 @@ def handle_commit_workflow()->bool:
119
125
  diff = os.popen("git diff HEAD").read()
120
126
  os.system("git reset HEAD")
121
127
  PrettyOutput.print(diff, OutputType.CODE, lang="diff")
122
- if not user_confirm("Do you want to commit the code?", default=True):
128
+ if not user_confirm("是否要提交代码?", default=True):
123
129
  os.system("git reset HEAD")
124
130
  os.system("git checkout -- .")
125
131
  os.system("git clean -fd")
@@ -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
- Args:
14
- requirement: The user's requirement description
15
-
16
- Returns:
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. Write questions in clear, professional English
26
- 2. Include necessary CONTEXT in each question
27
- 3. Be SPECIFIC about what needs to be found/analyzed
28
- 4. Provide enough background for someone with no prior knowledge
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 is error handling implemented?"
32
- GOOD: "Given that we need to add retry logic to the file upload feature, how does the current error handling work in upload_handler.py, specifically around network failures and timeout scenarios?"
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 when forming questions:
28
+ Consider these investigation aspects:
35
29
 
36
- 1. Implementation Context:
37
- - "What is the current implementation of [specific feature]?"
38
- - "Which modules/classes handle [specific functionality]?"
39
- - "What is the existing workflow for [specific operation]?"
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. Technical Investigation:
42
- - "How does the system currently handle [specific scenario]?"
43
- - "What patterns are used for [specific behavior]?"
44
- - "Where are the configuration settings for [specific feature]?"
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 Details:
47
- - "Which components call or depend on [specific module]?"
48
- - "What is the data flow between [component A] and [component B]?"
49
- - "How are errors propagated from [specific component]?"
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. Requirements Context:
52
- - "Given [specific requirement], what are the current limitations?"
53
- - "For [specific change], what validation rules apply?"
54
- - "In the context of [feature], what edge cases exist?"
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 in English, ensuring each includes full context for someone with no prior knowledge of the requirement]
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().get_normal_platform()
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("Find files from codebase...", OutputType.INFO)
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("Failed to find relevant files", OutputType.ERROR)
78
+ PrettyOutput.print("查找相关文件失败", OutputType.ERROR)
86
79
  return [], ""