jarvis-ai-assistant 0.1.130__py3-none-any.whl → 0.1.131__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 (60) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +23 -9
  3. jarvis/jarvis_agent/builtin_input_handler.py +73 -0
  4. jarvis/{jarvis_code_agent → jarvis_agent}/file_input_handler.py +1 -1
  5. jarvis/jarvis_agent/main.py +1 -1
  6. jarvis/{jarvis_code_agent → jarvis_agent}/patch.py +23 -19
  7. jarvis/{jarvis_code_agent → jarvis_agent}/shell_input_handler.py +0 -1
  8. jarvis/jarvis_code_agent/code_agent.py +20 -16
  9. jarvis/jarvis_codebase/main.py +5 -5
  10. jarvis/jarvis_dev/main.py +1 -1
  11. jarvis/jarvis_git_squash/main.py +1 -1
  12. jarvis/jarvis_lsp/base.py +2 -26
  13. jarvis/jarvis_lsp/cpp.py +2 -14
  14. jarvis/jarvis_lsp/go.py +0 -13
  15. jarvis/jarvis_lsp/python.py +1 -30
  16. jarvis/jarvis_lsp/registry.py +10 -14
  17. jarvis/jarvis_lsp/rust.py +0 -12
  18. jarvis/jarvis_multi_agent/__init__.py +1 -1
  19. jarvis/jarvis_platform/registry.py +1 -1
  20. jarvis/jarvis_platform_manager/main.py +3 -3
  21. jarvis/jarvis_rag/main.py +1 -1
  22. jarvis/jarvis_tools/ask_codebase.py +40 -20
  23. jarvis/jarvis_tools/code_review.py +180 -143
  24. jarvis/jarvis_tools/create_code_agent.py +76 -72
  25. jarvis/jarvis_tools/create_sub_agent.py +32 -15
  26. jarvis/jarvis_tools/execute_shell.py +2 -2
  27. jarvis/jarvis_tools/execute_shell_script.py +1 -1
  28. jarvis/jarvis_tools/file_operation.py +2 -2
  29. jarvis/jarvis_tools/git_commiter.py +87 -68
  30. jarvis/jarvis_tools/lsp_find_definition.py +83 -67
  31. jarvis/jarvis_tools/lsp_find_references.py +62 -46
  32. jarvis/jarvis_tools/lsp_get_diagnostics.py +90 -74
  33. jarvis/jarvis_tools/methodology.py +3 -3
  34. jarvis/jarvis_tools/read_code.py +1 -1
  35. jarvis/jarvis_tools/search_web.py +18 -20
  36. jarvis/jarvis_tools/tool_generator.py +1 -1
  37. jarvis/jarvis_tools/treesitter_analyzer.py +331 -0
  38. jarvis/jarvis_treesitter/README.md +104 -0
  39. jarvis/jarvis_treesitter/__init__.py +20 -0
  40. jarvis/jarvis_treesitter/database.py +258 -0
  41. jarvis/jarvis_treesitter/example.py +115 -0
  42. jarvis/jarvis_treesitter/grammar_builder.py +182 -0
  43. jarvis/jarvis_treesitter/language.py +117 -0
  44. jarvis/jarvis_treesitter/symbol.py +31 -0
  45. jarvis/jarvis_treesitter/tools_usage.md +121 -0
  46. jarvis/jarvis_utils/git_utils.py +10 -2
  47. jarvis/jarvis_utils/input.py +3 -1
  48. jarvis/jarvis_utils/methodology.py +1 -1
  49. jarvis/jarvis_utils/utils.py +3 -3
  50. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.131.dist-info}/METADATA +2 -4
  51. jarvis_ai_assistant-0.1.131.dist-info/RECORD +85 -0
  52. jarvis/jarvis_c2rust/c2rust.yaml +0 -734
  53. jarvis/jarvis_code_agent/builtin_input_handler.py +0 -43
  54. jarvis/jarvis_tools/lsp_get_document_symbols.py +0 -87
  55. jarvis/jarvis_tools/lsp_prepare_rename.py +0 -130
  56. jarvis_ai_assistant-0.1.130.dist-info/RECORD +0 -79
  57. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.131.dist-info}/LICENSE +0 -0
  58. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.131.dist-info}/WHEEL +0 -0
  59. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.131.dist-info}/entry_points.txt +0 -0
  60. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.131.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  from typing import Dict, Any
2
+ import os
2
3
  from jarvis.jarvis_code_agent.code_agent import CodeAgent
3
4
  from jarvis.jarvis_tools.git_commiter import GitCommitTool
4
5
  from jarvis.jarvis_tools.code_review import CodeReviewTool, extract_code_report
@@ -11,63 +12,83 @@ class CreateCodeAgentTool:
11
12
  name = "create_code_agent"
12
13
  description = "技术代码实现和开发过程管理工具"
13
14
  parameters = {
14
- "requirement": "代码实现的技术规范"
15
+ "requirement": """代码实现的技术规范,必须包含以下完整信息:
16
+ 1. 项目代码目录 - 项目根目录的绝对路径
17
+ 2. 项目功能 - 项目的主要功能和目标
18
+ 3. 本次要实现的feature - 本次开发要完成的具体功能需求
19
+ 4. 涉及的文件 - 需要修改或新增的文件列表
20
+ 5. 额外需要注意的信息 - 开发时需要额外注意的信息
21
+ """,
22
+ "root_dir": {
23
+ "type": "string",
24
+ "description": "代码库根目录路径(可选)",
25
+ "default": "."
26
+ }
15
27
  }
16
28
 
17
29
 
18
30
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
19
31
  try:
20
32
  requirement = args.get("requirement", "")
21
- if not requirement:
22
- return {
23
- "success": False,
24
- "stderr": "Requirement must be provided",
25
- "stdout": ""
26
- }
33
+ root_dir = args.get("root_dir", ".")
27
34
 
28
- # Step 1: Handle uncommitted changes
29
- start_commit = None
30
- if has_uncommitted_changes():
31
- PrettyOutput.print("发现未提交的更改,正在提交...", OutputType.INFO)
32
- git_commiter = GitCommitTool()
33
- result = git_commiter.execute({})
34
- if not result["success"]:
35
+ # Store current directory
36
+ original_dir = os.getcwd()
37
+
38
+ try:
39
+ # Change to root_dir
40
+ os.chdir(root_dir)
41
+ if not requirement:
35
42
  return {
36
43
  "success": False,
37
- "stderr": "Failed to commit changes: " + result["stderr"],
44
+ "stderr": "Requirement must be provided",
38
45
  "stdout": ""
39
46
  }
40
-
41
- # Get current commit hash
42
- start_commit = get_latest_commit_hash()
43
-
44
- # Step 2: Development
45
- PrettyOutput.print("开始开发...", OutputType.INFO)
46
- agent = CodeAgent()
47
- agent.run(requirement)
48
-
49
- # Get new commit hash after development
50
- end_commit = get_latest_commit_hash()
51
-
52
- # Step 3: Code Review
53
- PrettyOutput.print("开始代码审查...", OutputType.INFO)
54
- reviewer = CodeReviewTool()
55
- review_result = reviewer.execute({
56
- "review_type": "range",
57
- "start_commit": start_commit,
58
- "end_commit": end_commit
59
- })
60
-
61
- if not review_result["success"]:
62
- return {
63
- "success": False,
64
- "stderr": "Code review failed: " + review_result["stderr"],
65
- "stdout": ""
66
- }
67
-
68
- # Step 4: Generate Summary
69
- summary = f"""开发总结:
70
-
47
+
48
+ # Step 1: Handle uncommitted changes
49
+ start_commit = None
50
+ if has_uncommitted_changes():
51
+ PrettyOutput.print("发现未提交的更改,正在提交...", OutputType.INFO)
52
+ git_commiter = GitCommitTool()
53
+ result = git_commiter.execute({})
54
+ if not result["success"]:
55
+ return {
56
+ "success": False,
57
+ "stderr": "Failed to commit changes: " + result["stderr"],
58
+ "stdout": ""
59
+ }
60
+
61
+ # Get current commit hash
62
+ start_commit = get_latest_commit_hash()
63
+
64
+ # Step 2: Development
65
+ PrettyOutput.print("开始开发...", OutputType.INFO)
66
+ agent = CodeAgent()
67
+ agent.run(requirement)
68
+
69
+ # Get new commit hash after development
70
+ end_commit = get_latest_commit_hash()
71
+
72
+ # Step 3: Code Review
73
+ PrettyOutput.print("开始代码审查...", OutputType.INFO)
74
+ reviewer = CodeReviewTool()
75
+ review_result = reviewer.execute({
76
+ "review_type": "range",
77
+ "start_commit": start_commit,
78
+ "end_commit": end_commit,
79
+ "root_dir": root_dir
80
+ })
81
+
82
+ if not review_result["success"]:
83
+ return {
84
+ "success": False,
85
+ "stderr": "Code review failed: " + review_result["stderr"],
86
+ "stdout": ""
87
+ }
88
+
89
+ # Step 4: Generate Summary
90
+ summary = f"""开发总结:
91
+
71
92
  开始提交: {start_commit}
72
93
  结束提交: {end_commit}
73
94
 
@@ -77,12 +98,15 @@ class CreateCodeAgentTool:
77
98
  代码审查结果:
78
99
  {extract_code_report(review_result["stdout"])}
79
100
  """
80
-
81
- return {
82
- "success": True,
83
- "stdout": summary,
84
- "stderr": ""
85
- }
101
+
102
+ return {
103
+ "success": True,
104
+ "stdout": summary,
105
+ "stderr": ""
106
+ }
107
+ finally:
108
+ # Always restore original directory
109
+ os.chdir(original_dir)
86
110
 
87
111
  except Exception as e:
88
112
  return {
@@ -90,23 +114,3 @@ class CreateCodeAgentTool:
90
114
  "stderr": f"Development workflow failed: {str(e)}",
91
115
  "stdout": ""
92
116
  }
93
-
94
- def main():
95
- """CLI entry point"""
96
- import argparse
97
-
98
- parser = argparse.ArgumentParser(description='Code development workflow tool')
99
- parser.add_argument('requirement', help='Development requirement or task description')
100
-
101
- args = parser.parse_args()
102
-
103
- tool = CreateCodeAgentTool()
104
- result = tool.execute({"requirement": args.requirement})
105
-
106
- if result["success"]:
107
- PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
108
- else:
109
- PrettyOutput.print(result["stderr"], OutputType.WARNING)
110
-
111
- if __name__ == "__main__":
112
- main()
@@ -1,4 +1,5 @@
1
1
  from typing import Dict, Any
2
+ import os
2
3
 
3
4
 
4
5
  from jarvis.jarvis_agent import Agent, origin_agent_system_prompt
@@ -30,8 +31,13 @@ class SubAgentTool:
30
31
  "description": "任务的完成目标",
31
32
  "default": ""
32
33
  },
34
+ "root_dir": {
35
+ "type": "string",
36
+ "description": "任务执行的根目录路径(可选)",
37
+ "default": "."
38
+ }
33
39
  },
34
- "required": ["agent_name", "task", "context", "goal"]
40
+ "required": ["agent_name", "task"]
35
41
  }
36
42
 
37
43
 
@@ -42,6 +48,7 @@ class SubAgentTool:
42
48
  task = args["task"]
43
49
  context = args.get("context", "")
44
50
  goal = args.get("goal", "")
51
+ root_dir = args.get("root_dir", ".")
45
52
 
46
53
  PrettyOutput.print(f"创建子代理: {agent_name}", OutputType.INFO)
47
54
 
@@ -53,22 +60,32 @@ class SubAgentTool:
53
60
  task_description += f"\n\nCompletion goal:\n{goal}"
54
61
 
55
62
 
56
- # Create sub-agent
57
- sub_agent = Agent(
58
- system_prompt=origin_agent_system_prompt,
59
- name=f"Agent({agent_name})",
60
- is_sub_agent=True
61
- )
63
+ # Store current directory
64
+ original_dir = os.getcwd()
62
65
 
63
- # Run sub-agent, pass file list
64
- PrettyOutput.print("子代理开始执行任务...", OutputType.INFO)
65
- result = sub_agent.run(task_description)
66
+ try:
67
+ # Change to root_dir
68
+ os.chdir(root_dir)
66
69
 
67
- return {
68
- "success": True,
69
- "stdout": f"Sub-agent task completed\n\n{result}",
70
- "stderr": ""
71
- }
70
+ # Create sub-agent
71
+ sub_agent = Agent(
72
+ system_prompt=origin_agent_system_prompt,
73
+ name=f"Agent({agent_name})",
74
+ is_sub_agent=True
75
+ )
76
+
77
+ # Run sub-agent, pass file list
78
+ PrettyOutput.print("子代理开始执行任务...", OutputType.INFO)
79
+ result = sub_agent.run(task_description)
80
+
81
+ return {
82
+ "success": True,
83
+ "stdout": f"Sub-agent task completed\n\n{result}",
84
+ "stderr": ""
85
+ }
86
+ finally:
87
+ # Always restore original directory
88
+ os.chdir(original_dir)
72
89
 
73
90
  except Exception as e:
74
91
  PrettyOutput.print(str(e), OutputType.ERROR)
@@ -74,11 +74,11 @@ class ShellTool:
74
74
  tee_command = f"script -q -c '{escaped_command}' {output_file}"
75
75
 
76
76
  # Execute command and capture return code
77
- return_code = os.system(tee_command)
77
+ os.system(tee_command)
78
78
 
79
79
  # Read and process output file
80
80
  try:
81
- with open(output_file, 'r', encoding='utf-8', errors='replace') as f:
81
+ with open(output_file, 'r', encoding='utf-8', errors='ignore') as f:
82
82
  output = f.read()
83
83
  # Remove header and footer added by script command
84
84
  if output:
@@ -33,7 +33,7 @@ class ShellScriptTool:
33
33
  # Create temporary script file
34
34
  script_path = os.path.join(tempfile.gettempdir(), f"jarvis_script_{os.getpid()}.sh")
35
35
  try:
36
- with open(script_path, 'w', encoding='utf-8') as f:
36
+ with open(script_path, 'w', encoding='utf-8', errors="ignore") as f:
37
37
  f.write(script_content)
38
38
  # Use execute_shell to run the script
39
39
  from jarvis.jarvis_tools.execute_shell import ShellTool
@@ -55,7 +55,7 @@ class FileOperationTool:
55
55
  "stderr": "File too large (>10MB)"
56
56
  }
57
57
 
58
- with open(abs_path, 'r', encoding='utf-8') as f:
58
+ with open(abs_path, 'r', encoding='utf-8', errors="ignore") as f:
59
59
  lines = f.readlines()
60
60
 
61
61
 
@@ -90,7 +90,7 @@ class FileOperationTool:
90
90
  elif operation == "write":
91
91
  with yaspin(text=f"正在写入文件: {abs_path}...", color="cyan") as spinner:
92
92
  os.makedirs(os.path.dirname(os.path.abspath(abs_path)), exist_ok=True)
93
- with open(abs_path, 'w', encoding='utf-8') as f:
93
+ with open(abs_path, 'w', encoding='utf-8', errors="ignore") as f:
94
94
  f.write(content)
95
95
  spinner.text = f"文件写入完成: {abs_path}"
96
96
  spinner.ok("✅")
@@ -8,6 +8,7 @@ from yaspin import yaspin
8
8
  from jarvis.jarvis_platform.registry import PlatformRegistry
9
9
  import sys
10
10
  import argparse
11
+ import os
11
12
 
12
13
  from jarvis.jarvis_utils.git_utils import find_git_root, has_uncommitted_changes
13
14
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
@@ -24,6 +25,11 @@ class GitCommitTool:
24
25
  "type": "string",
25
26
  "description": "提交信息的语言",
26
27
  "default": "Chinese"
28
+ },
29
+ "root_dir": {
30
+ "type": "string",
31
+ "description": "Git仓库的根目录路径(可选)",
32
+ "default": "."
27
33
  }
28
34
  },
29
35
  "required": []
@@ -51,83 +57,95 @@ class GitCommitTool:
51
57
  def execute(self, args: Dict) -> Dict[str, Any]:
52
58
  """Execute automatic commit process with support for multi-line messages and special characters"""
53
59
  try:
54
- find_git_root()
55
- if not has_uncommitted_changes():
56
- PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
57
- return {"success": True, "stdout": "No changes to commit", "stderr": ""}
60
+ root_dir = args.get("root_dir", ".")
58
61
 
59
- with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
60
- # 添加文件
61
- spinner.text = "正在添加文件到提交..."
62
- subprocess.Popen(
63
- ["git", "add", "."],
64
- stdout=subprocess.DEVNULL,
65
- stderr=subprocess.DEVNULL
66
- ).wait()
67
- spinner.write("✅ 添加文件到提交")
68
-
69
- # 获取差异
70
- spinner.text = "正在获取代码差异..."
71
- process = subprocess.Popen(
72
- ["git", "diff", "--cached", "--exit-code"],
73
- stdout=subprocess.PIPE,
74
- stderr=subprocess.PIPE
75
- )
76
- diff = process.communicate()[0].decode()
77
- spinner.write("✅ 获取差异")
62
+ # Store current directory
63
+ original_dir = os.getcwd()
64
+
65
+ try:
66
+ # Change to root_dir
67
+ os.chdir(root_dir)
78
68
 
79
- # 生成提交信息
80
- spinner.text = "正在生成提交消息..."
81
- prompt = f'''根据以下规则生成提交信息:
82
- 提交信息应使用{args.get('lang', '中文')}书写
83
- # 必需结构
84
- 必须使用以下格式:
85
- <COMMIT_MESSAGE>
86
- <类型>(<范围>): <主题>
87
- 使用祈使语气描述变更内容
88
- </COMMIT_MESSAGE>
89
- # 格式规则
90
- 1. 类型: fix, feat, docs, style, refactor, test, chore
91
- 2. 范围表示模块 (例如: auth, database)
92
- 3. 主题行 <= 72个字符,不以句号结尾
93
- 4. 正文使用现在时态解释每个变更的内容和原因
94
- 5. 不要遗漏任何变更
95
- # 分析材料
96
- {diff}
97
- '''
98
- platform = PlatformRegistry().get_codegen_platform()
99
- commit_message = platform.chat_until_success(prompt)
100
- commit_message = self._extract_commit_message(commit_message)
101
- spinner.write("✅ 生成提交消息")
69
+ find_git_root()
70
+ if not has_uncommitted_changes():
71
+ PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
72
+ return {"success": True, "stdout": "No changes to commit", "stderr": ""}
102
73
 
103
- # 执行提交
104
- spinner.text = "正在准备提交..."
105
- with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
106
- tmp_file.write(commit_message)
107
- tmp_file.flush()
108
- spinner.text = "正在执行提交..."
109
- commit_cmd = ["git", "commit", "-F", tmp_file.name]
74
+ with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
75
+ # 添加文件
76
+ spinner.text = "正在添加文件到提交..."
110
77
  subprocess.Popen(
111
- commit_cmd,
78
+ ["git", "add", "."],
112
79
  stdout=subprocess.DEVNULL,
113
80
  stderr=subprocess.DEVNULL
114
81
  ).wait()
115
- spinner.write("✅ 提交")
82
+ spinner.write("✅ 添加文件到提交")
83
+
84
+ # 获取差异
85
+ spinner.text = "正在获取代码差异..."
86
+ process = subprocess.Popen(
87
+ ["git", "diff", "--cached", "--exit-code"],
88
+ stdout=subprocess.PIPE,
89
+ stderr=subprocess.PIPE
90
+ )
91
+ diff = process.communicate()[0].decode()
92
+ spinner.write("✅ 获取差异")
93
+
94
+ # 生成提交信息
95
+ spinner.text = "正在生成提交消息..."
96
+ prompt = f'''根据以下规则生成提交信息:
97
+ 提交信息应使用{args.get('lang', '中文')}书写
98
+ # 必需结构
99
+ 必须使用以下格式:
100
+ <COMMIT_MESSAGE>
101
+ <类型>(<范围>): <主题>
102
+ 使用祈使语气描述变更内容
103
+ </COMMIT_MESSAGE>
104
+ # 格式规则
105
+ 1. 类型: fix, feat, docs, style, refactor, test, chore
106
+ 2. 范围表示模块 (例如: auth, database)
107
+ 3. 主题行 <= 72个字符,不以句号结尾
108
+ 4. 正文使用现在时态解释每个变更的内容和原因
109
+ 5. 不要遗漏任何变更
110
+ # 分析材料
111
+ {diff}
112
+ '''
113
+ platform = PlatformRegistry().get_codegen_platform()
114
+ commit_message = platform.chat_until_success(prompt)
115
+ commit_message = self._extract_commit_message(commit_message)
116
+ spinner.write("✅ 生成提交消息")
117
+
118
+ # 执行提交
119
+ spinner.text = "正在准备提交..."
120
+ with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
121
+ tmp_file.write(commit_message)
122
+ tmp_file.flush()
123
+ spinner.text = "正在执行提交..."
124
+ commit_cmd = ["git", "commit", "-F", tmp_file.name]
125
+ subprocess.Popen(
126
+ commit_cmd,
127
+ stdout=subprocess.DEVNULL,
128
+ stderr=subprocess.DEVNULL
129
+ ).wait()
130
+ spinner.write("✅ 提交")
116
131
 
117
- commit_hash = self._get_last_commit_hash()
118
- spinner.text = "完成提交"
119
- spinner.ok("✅")
132
+ commit_hash = self._get_last_commit_hash()
133
+ spinner.text = "完成提交"
134
+ spinner.ok("✅")
120
135
 
121
- PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
136
+ PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
122
137
 
123
- return {
124
- "success": True,
125
- "stdout": yaml.safe_dump({
126
- "commit_hash": commit_hash,
127
- "commit_message": commit_message
128
- }),
129
- "stderr": ""
130
- }
138
+ return {
139
+ "success": True,
140
+ "stdout": yaml.safe_dump({
141
+ "commit_hash": commit_hash,
142
+ "commit_message": commit_message
143
+ }),
144
+ "stderr": ""
145
+ }
146
+ finally:
147
+ # Always restore original directory
148
+ os.chdir(original_dir)
131
149
 
132
150
  except Exception as e:
133
151
  return {
@@ -140,9 +158,10 @@ def main():
140
158
  init_env()
141
159
  parser = argparse.ArgumentParser(description='Git commit tool')
142
160
  parser.add_argument('--lang', type=str, default='Chinese', help='Language for commit messages')
161
+ parser.add_argument('--root-dir', type=str, default='.', help='Root directory of the Git repository')
143
162
  args = parser.parse_args()
144
163
  tool = GitCommitTool()
145
- tool.execute({"lang": args.lang if hasattr(args, 'lang') else 'Chinese'})
164
+ tool.execute({"lang": args.lang if hasattr(args, 'lang') else 'Chinese', "root_dir": args.root_dir})
146
165
 
147
166
  if __name__ == "__main__":
148
167
  sys.exit(main())