jarvis-ai-assistant 0.1.132__py3-none-any.whl → 0.1.138__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 (82) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +330 -347
  3. jarvis/jarvis_agent/builtin_input_handler.py +16 -6
  4. jarvis/jarvis_agent/file_input_handler.py +9 -9
  5. jarvis/jarvis_agent/jarvis.py +143 -0
  6. jarvis/jarvis_agent/main.py +12 -13
  7. jarvis/jarvis_agent/output_handler.py +3 -3
  8. jarvis/jarvis_agent/patch.py +92 -64
  9. jarvis/jarvis_agent/shell_input_handler.py +5 -3
  10. jarvis/jarvis_code_agent/code_agent.py +263 -177
  11. jarvis/jarvis_code_agent/file_select.py +24 -24
  12. jarvis/jarvis_dev/main.py +45 -59
  13. jarvis/jarvis_git_details/__init__.py +0 -0
  14. jarvis/jarvis_git_details/main.py +179 -0
  15. jarvis/jarvis_git_squash/main.py +7 -7
  16. jarvis/jarvis_lsp/base.py +11 -53
  17. jarvis/jarvis_lsp/cpp.py +13 -28
  18. jarvis/jarvis_lsp/go.py +13 -28
  19. jarvis/jarvis_lsp/python.py +8 -27
  20. jarvis/jarvis_lsp/registry.py +21 -83
  21. jarvis/jarvis_lsp/rust.py +15 -30
  22. jarvis/jarvis_methodology/main.py +101 -0
  23. jarvis/jarvis_multi_agent/__init__.py +10 -51
  24. jarvis/jarvis_multi_agent/main.py +43 -0
  25. jarvis/jarvis_platform/__init__.py +1 -1
  26. jarvis/jarvis_platform/ai8.py +67 -89
  27. jarvis/jarvis_platform/base.py +14 -13
  28. jarvis/jarvis_platform/kimi.py +25 -28
  29. jarvis/jarvis_platform/ollama.py +24 -26
  30. jarvis/jarvis_platform/openai.py +15 -19
  31. jarvis/jarvis_platform/oyi.py +48 -50
  32. jarvis/jarvis_platform/registry.py +29 -44
  33. jarvis/jarvis_platform/yuanbao.py +39 -43
  34. jarvis/jarvis_platform_manager/main.py +81 -81
  35. jarvis/jarvis_platform_manager/openai_test.py +21 -21
  36. jarvis/jarvis_rag/file_processors.py +18 -18
  37. jarvis/jarvis_rag/main.py +262 -278
  38. jarvis/jarvis_smart_shell/main.py +12 -12
  39. jarvis/jarvis_tools/ask_codebase.py +85 -78
  40. jarvis/jarvis_tools/ask_user.py +8 -8
  41. jarvis/jarvis_tools/base.py +4 -4
  42. jarvis/jarvis_tools/chdir.py +9 -9
  43. jarvis/jarvis_tools/code_review.py +40 -21
  44. jarvis/jarvis_tools/create_code_agent.py +15 -15
  45. jarvis/jarvis_tools/create_sub_agent.py +0 -1
  46. jarvis/jarvis_tools/execute_python_script.py +3 -3
  47. jarvis/jarvis_tools/execute_shell.py +11 -11
  48. jarvis/jarvis_tools/execute_shell_script.py +3 -3
  49. jarvis/jarvis_tools/file_analyzer.py +116 -105
  50. jarvis/jarvis_tools/file_operation.py +22 -20
  51. jarvis/jarvis_tools/find_caller.py +105 -40
  52. jarvis/jarvis_tools/find_methodolopy.py +65 -0
  53. jarvis/jarvis_tools/find_symbol.py +123 -39
  54. jarvis/jarvis_tools/function_analyzer.py +140 -57
  55. jarvis/jarvis_tools/git_commiter.py +10 -10
  56. jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
  57. jarvis/jarvis_tools/methodology.py +22 -67
  58. jarvis/jarvis_tools/project_analyzer.py +137 -53
  59. jarvis/jarvis_tools/rag.py +15 -20
  60. jarvis/jarvis_tools/read_code.py +25 -23
  61. jarvis/jarvis_tools/read_webpage.py +31 -31
  62. jarvis/jarvis_tools/registry.py +72 -52
  63. jarvis/jarvis_tools/search_web.py +23 -353
  64. jarvis/jarvis_tools/tool_generator.py +19 -19
  65. jarvis/jarvis_utils/config.py +36 -96
  66. jarvis/jarvis_utils/embedding.py +83 -83
  67. jarvis/jarvis_utils/git_utils.py +20 -20
  68. jarvis/jarvis_utils/globals.py +18 -6
  69. jarvis/jarvis_utils/input.py +10 -9
  70. jarvis/jarvis_utils/methodology.py +141 -140
  71. jarvis/jarvis_utils/output.py +13 -13
  72. jarvis/jarvis_utils/utils.py +23 -71
  73. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +6 -15
  74. jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
  75. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +4 -3
  76. jarvis/jarvis_tools/lsp_find_definition.py +0 -150
  77. jarvis/jarvis_tools/lsp_find_references.py +0 -127
  78. jarvis/jarvis_tools/select_code_files.py +0 -62
  79. jarvis_ai_assistant-0.1.132.dist-info/RECORD +0 -82
  80. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
  81. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
  82. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/top_level.txt +0 -0
@@ -6,20 +6,20 @@ from typing import Any, Tuple
6
6
  def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
7
7
  """
8
8
  处理内置的特殊输入标记,并追加相应的提示词
9
-
9
+
10
10
  参数:
11
11
  user_input: 用户输入
12
12
  agent: 代理对象
13
-
13
+
14
14
  返回:
15
15
  Tuple[str, bool]: 处理后的输入和是否需要进一步处理
16
16
  """
17
17
  # 查找特殊标记
18
18
  special_tags = re.findall(r"'<([^>]+)>'", user_input)
19
-
19
+
20
20
  if not special_tags:
21
21
  return user_input, False
22
-
22
+
23
23
  # 使用集合去重
24
24
  processed_tags = set()
25
25
  # 处理每个标记
@@ -27,7 +27,7 @@ def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
27
27
  if tag in processed_tags:
28
28
  continue
29
29
  processed_tags.add(tag)
30
-
30
+
31
31
  if tag == "CodeBase":
32
32
  user_input = user_input.replace(f"'<{tag}>'", "")
33
33
  user_input += """
@@ -68,6 +68,16 @@ def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
68
68
  agent.clear()
69
69
  if not user_input.strip():
70
70
  return "", True
71
+ elif tag == "Methodology":
72
+ user_input = user_input.replace(f"'<{tag}>'", "")
73
+ user_input += """
74
+ 请使用find_methodology工具查找相关方法论,可以使用的提问格式包括:
75
+ 1. 关于xxx的方法论有哪些?
76
+ 2. 如何解决xxx问题?
77
+ 3. xxx的最佳实践是什么?
78
+ 4. 处理xxx的标准流程是什么?
79
+ 5. 实现xxx的参考方案有哪些?
80
+ """
71
81
  # 移除对未知标记的警告输出
72
-
82
+
73
83
  return user_input, False
@@ -13,7 +13,7 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
13
13
  def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
14
14
  prompt = user_input
15
15
  files = []
16
-
16
+
17
17
  file_refs = re.findall(r"'([^']+)'", user_input)
18
18
  for ref in file_refs:
19
19
  # Handle file:start,end or file:start:end format
@@ -22,12 +22,12 @@ def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
22
22
  # Initialize with default values
23
23
  start_line = 1 # 1-based
24
24
  end_line = -1
25
-
25
+
26
26
  # Process line range if specified
27
27
  if ',' in line_range or ':' in line_range:
28
28
  try:
29
29
  raw_start, raw_end = map(int, re.split(r'[,:]', line_range))
30
-
30
+
31
31
  # Handle special values and Python-style negative indices
32
32
  try:
33
33
  with open(file_path, 'r', encoding='utf-8', errors="ignore") as f:
@@ -41,24 +41,24 @@ def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
41
41
  end_line = total_lines
42
42
  else:
43
43
  start_line = raw_start if raw_start > 0 else total_lines + raw_start + 1
44
-
44
+
45
45
  # Process end line
46
46
  if raw_end == 0: # 0表示整个文件(如果start也是0)
47
47
  end_line = total_lines
48
48
  else:
49
49
  end_line = raw_end if raw_end > 0 else total_lines + raw_end + 1
50
-
50
+
51
51
  # Auto-correct ranges
52
52
  start_line = max(1, min(start_line, total_lines))
53
53
  end_line = max(start_line, min(end_line, total_lines))
54
-
54
+
55
55
  # Final validation
56
56
  if start_line < 1 or end_line > total_lines or start_line > end_line:
57
57
  raise ValueError
58
58
 
59
59
  except:
60
60
  continue
61
-
61
+
62
62
  # Add file if it exists
63
63
  if os.path.isfile(file_path):
64
64
  files.append({
@@ -74,7 +74,7 @@ def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
74
74
  "start_line": 1, # 1-based
75
75
  "end_line": -1
76
76
  })
77
-
77
+
78
78
  # Read and process files if any were found
79
79
  if files:
80
80
  with yaspin(text="正在读取文件...", color="cyan") as spinner:
@@ -83,6 +83,6 @@ def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
83
83
  spinner.text = "文件读取完成"
84
84
  spinner.ok("✅")
85
85
  return result["stdout"] + "\n" + prompt, False
86
-
86
+
87
87
  return prompt, False
88
88
 
@@ -0,0 +1,143 @@
1
+ import argparse
2
+ import os
3
+
4
+ from prompt_toolkit import prompt
5
+ import yaml
6
+ from yaspin import yaspin
7
+ from jarvis.jarvis_agent import (
8
+ PrettyOutput, OutputType,
9
+ get_multiline_input,
10
+ Agent, # 显式导入关键组件
11
+ origin_agent_system_prompt
12
+ )
13
+ from jarvis.jarvis_agent.patch import PatchOutputHandler
14
+ from jarvis.jarvis_tools.registry import ToolRegistry
15
+ from jarvis.jarvis_utils.utils import init_env
16
+ from jarvis.jarvis_agent.file_input_handler import file_input_handler
17
+ from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
18
+ from jarvis.jarvis_agent.builtin_input_handler import builtin_input_handler
19
+
20
+
21
+ def _load_tasks() -> dict:
22
+ """Load tasks from .jarvis files in user home and current directory."""
23
+ tasks = {}
24
+
25
+ # Check .jarvis/pre-command in user directory
26
+ user_jarvis = os.path.expanduser("~/.jarvis/pre-command")
27
+ if os.path.exists(user_jarvis):
28
+ with yaspin(text=f"从{user_jarvis}加载预定义任务...", color="cyan") as spinner:
29
+ try:
30
+ with open(user_jarvis, "r", encoding="utf-8", errors="ignore") as f:
31
+ user_tasks = yaml.safe_load(f)
32
+
33
+ if isinstance(user_tasks, dict):
34
+ # Validate and add user directory tasks
35
+ for name, desc in user_tasks.items():
36
+ if desc: # Ensure description is not empty
37
+ tasks[str(name)] = str(desc)
38
+ spinner.text = "预定义任务加载完成"
39
+ spinner.ok("✅")
40
+ except Exception as e:
41
+ spinner.text = "预定义任务加载失败"
42
+ spinner.fail("❌")
43
+
44
+ # Check .jarvis/pre-command in current directory
45
+ if os.path.exists(".jarvis/pre-command"):
46
+ with yaspin(text=f"从{os.path.abspath('.jarvis/pre-command')}加载预定义任务...", color="cyan") as spinner:
47
+ try:
48
+ with open(".jarvis/pre-command", "r", encoding="utf-8", errors="ignore") as f:
49
+ local_tasks = yaml.safe_load(f)
50
+
51
+ if isinstance(local_tasks, dict):
52
+ # Validate and add current directory tasks, overwrite user directory tasks if there is a name conflict
53
+ for name, desc in local_tasks.items():
54
+ if desc: # Ensure description is not empty
55
+ tasks[str(name)] = str(desc)
56
+ spinner.text = "预定义任务加载完成"
57
+ spinner.ok("✅")
58
+ except Exception as e:
59
+ spinner.text = "预定义任务加载失败"
60
+ spinner.fail("❌")
61
+
62
+ return tasks
63
+
64
+ def _select_task(tasks: dict) -> str:
65
+ """Let user select a task from the list or skip. Returns task description if selected."""
66
+ if not tasks:
67
+ return ""
68
+ # Convert tasks to list for ordered display
69
+ task_names = list(tasks.keys())
70
+
71
+ task_list = ["可用任务:"]
72
+ for i, name in enumerate(task_names, 1):
73
+ task_list.append(f"[{i}] {name}")
74
+ task_list.append("[0] 跳过预定义任务")
75
+ PrettyOutput.print("\n".join(task_list), OutputType.INFO)
76
+
77
+
78
+ while True:
79
+ try:
80
+ choice = prompt(
81
+ "\n请选择一个任务编号(0 跳过预定义任务):",
82
+ ).strip()
83
+
84
+ if not choice:
85
+ return ""
86
+
87
+ choice = int(choice)
88
+ if choice == 0:
89
+ return ""
90
+ elif 1 <= choice <= len(task_names):
91
+ selected_name = task_names[choice - 1]
92
+ return tasks[selected_name] # Return the task description
93
+ else:
94
+ PrettyOutput.print("无效的选择。请选择列表中的一个号码。", OutputType.WARNING)
95
+
96
+ except KeyboardInterrupt:
97
+ return "" # Return empty on Ctrl+C
98
+ except EOFError:
99
+ return "" # Return empty on Ctrl+D
100
+ except Exception as e:
101
+ PrettyOutput.print(f"选择任务失败: {str(e)}", OutputType.ERROR)
102
+ continue
103
+
104
+
105
+
106
+
107
+ def main() -> int:
108
+ """Jarvis main entry point"""
109
+ init_env()
110
+ parser = argparse.ArgumentParser(description='Jarvis AI assistant')
111
+ parser.add_argument('-p', '--platform', type=str, help='Platform to use')
112
+ parser.add_argument('-m', '--model', type=str, help='Model to use')
113
+ args = parser.parse_args()
114
+
115
+ try:
116
+ agent = Agent(
117
+ system_prompt=origin_agent_system_prompt,
118
+ platform=args.platform,
119
+ model_name=args.model,
120
+ input_handler=[file_input_handler, shell_input_handler, builtin_input_handler], # type: ignore
121
+ output_handler=[ToolRegistry(), PatchOutputHandler()],
122
+ need_summary=False
123
+ )
124
+
125
+ tasks = _load_tasks()
126
+ if tasks:
127
+ selected_task = _select_task(tasks)
128
+ if selected_task:
129
+ PrettyOutput.print(f"执行任务: {selected_task}", OutputType.INFO)
130
+ agent.run(selected_task)
131
+ return 0
132
+
133
+ user_input = get_multiline_input("请输入你的任务(输入空行退出):")
134
+ if user_input:
135
+ agent.run(user_input)
136
+ return 0
137
+
138
+ except Exception as e:
139
+ PrettyOutput.print(f"初始化错误: {str(e)}", OutputType.ERROR)
140
+ return 1
141
+
142
+ if __name__ == "__main__":
143
+ exit(main())
@@ -7,22 +7,20 @@ from jarvis.jarvis_utils.input import get_multiline_input
7
7
  from jarvis.jarvis_utils.output import PrettyOutput, OutputType
8
8
  from jarvis.jarvis_utils.utils import init_env
9
9
 
10
- # 从__init__.py导入系统提示
11
- from jarvis.jarvis_agent import origin_agent_system_prompt
12
10
 
13
11
  def load_config(config_path: str) -> dict:
14
12
  """Load configuration from YAML file
15
-
13
+
16
14
  Args:
17
15
  config_path: Path to the YAML configuration file
18
-
16
+
19
17
  Returns:
20
18
  dict: Configuration dictionary
21
19
  """
22
20
  if not os.path.exists(config_path):
23
21
  PrettyOutput.print(f"配置文件 {config_path} 不存在,使用默认配置", OutputType.WARNING)
24
22
  return {}
25
-
23
+
26
24
  with open(config_path, 'r', encoding='utf-8', errors="ignore") as f:
27
25
  try:
28
26
  config = yaml.safe_load(f)
@@ -35,42 +33,43 @@ def main():
35
33
  """Main entry point for Jarvis agent"""
36
34
  # Initialize environment
37
35
  init_env()
38
-
36
+
39
37
  # Set up argument parser
40
38
  parser = argparse.ArgumentParser(description='Jarvis AI assistant')
41
- parser.add_argument('-c', '--config', type=str, required=True,
39
+ parser.add_argument('-c', '--config', type=str, required=True,
42
40
  help='Path to the YAML configuration file')
43
41
  parser.add_argument('-t', '--task', type=str,
44
42
  help='Initial task to execute')
45
43
  args = parser.parse_args()
46
-
44
+
47
45
  # Load configuration
48
46
  config = load_config(args.config)
49
-
47
+
50
48
  # Create and run agent
51
49
  try:
52
50
  agent = Agent(**config)
53
-
51
+
54
52
  # Run agent with initial task if specified
55
53
  if args.task:
56
54
  PrettyOutput.print(f"执行初始任务: {args.task}", OutputType.INFO)
57
55
  agent.run(args.task)
58
56
  return 0
59
-
57
+
60
58
  # Enter interactive mode if no initial task
61
59
  while True:
62
60
  try:
63
61
  user_input = get_multiline_input("请输入你的任务(输入空行退出):")
64
62
  if not user_input:
65
63
  break
64
+ agent.set_addon_prompt("如果有必要,请先指定出行动计划,然后根据计划一步步执行")
66
65
  agent.run(user_input)
67
66
  except Exception as e:
68
67
  PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
69
-
68
+
70
69
  except Exception as e:
71
70
  PrettyOutput.print(f"初始化错误: {str(e)}", OutputType.ERROR)
72
71
  return 1
73
-
72
+
74
73
  return 0
75
74
 
76
75
  if __name__ == "__main__":
@@ -7,13 +7,13 @@ from typing import Any, Tuple
7
7
 
8
8
  class OutputHandler(ABC):
9
9
  @abstractmethod
10
- def handle(self, response: str) -> Tuple[bool, Any]:
10
+ def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
11
11
  pass
12
-
12
+
13
13
  @abstractmethod
14
14
  def can_handle(self, response: str) -> bool:
15
15
  pass
16
-
16
+
17
17
  @abstractmethod
18
18
  def prompt(self) -> str:
19
19
  pass