jarvis-ai-assistant 0.1.103__py3-none-any.whl → 0.1.104__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 CHANGED
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.103"
3
+ __version__ = "0.1.104"
@@ -3,7 +3,7 @@ import re
3
3
  from typing import Dict, List
4
4
  from prompt_toolkit import PromptSession
5
5
  from prompt_toolkit.completion import WordCompleter, Completer, Completion
6
- from jarvis.utils import OutputType, PrettyOutput, get_single_line_input
6
+ from jarvis.utils import OutputType, PrettyOutput, get_single_line_input, user_confirm
7
7
 
8
8
 
9
9
  def _parse_file_selection(input_str: str, max_index: int) -> List[int]:
@@ -135,11 +135,10 @@ def select_files(related_files: List[str], root_dir: str) -> List[str]:
135
135
  for i, file in enumerate(related_files, 1):
136
136
  output += f"[{i}] {file}\n"
137
137
 
138
- PrettyOutput.print(output, OutputType.INFO)
138
+ PrettyOutput.print(output, OutputType.INFO, lang="markdown")
139
139
 
140
140
  # Ask the user if they need to adjust the file list
141
- user_input = get_single_line_input("Do you need to adjust the file list? (y/n) [n]").strip().lower() or 'n'
142
- if user_input == 'y':
141
+ if user_confirm("Do you need to adjust the file list?", False):
143
142
  # Let the user select files
144
143
  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()
145
144
  if numbers:
@@ -150,8 +149,7 @@ def select_files(related_files: List[str], root_dir: str) -> List[str]:
150
149
  PrettyOutput.print("No valid files selected, keep the current selection", OutputType.WARNING)
151
150
 
152
151
  # Ask if they need to supplement files
153
- user_input = get_single_line_input("Do you need to supplement other files? (y/n) [n]").strip().lower() or 'n'
154
- if user_input == 'y':
152
+ if user_confirm("Do you need to supplement other files?", False):
155
153
  # Create file completion session
156
154
  session = PromptSession(
157
155
  completer=_get_file_completer(root_dir),
@@ -108,6 +108,8 @@ def handle_commit_workflow()->bool:
108
108
  Returns:
109
109
  tuple[bool, str, str]: (continue_execution, commit_id, commit_message)
110
110
  """
111
+ diff = os.popen("git diff HEAD").read()
112
+ PrettyOutput.print(diff, OutputType.CODE, lang="diff")
111
113
  if not user_confirm("Do you want to commit the code?", default=True):
112
114
  os.system("git reset HEAD")
113
115
  os.system("git checkout -- .")
@@ -1,6 +1,3 @@
1
-
2
-
3
-
4
1
  import os
5
2
  import re
6
3
  from typing import List
@@ -27,19 +24,53 @@ def find_relevant_files(user_input: str, root_dir: str) -> List[str]:
27
24
  find_file_tool_registry.use_tools(["read_code", "execute_shell"])
28
25
  find_file_agent = Agent(
29
26
  system_prompt="""You are a file agent, you are responsible for finding files related to the user's requirement.
30
- You can use `read_code` tool to read the code and analyze the code, and `execute_shell` tool to execute shell command(such as `grep/find/ls/git/ctags`) to find files.
31
27
 
32
- IMPORTANT:
33
- - Only provide the file path, do not provide any other information.
34
- - If you can't find the file, please provide empty list.
35
- - Don't modify the code, just find related files.
28
+ SEARCH STRATEGY:
29
+ 1. First Pass - Quick Search:
30
+ - Use `execute_shell` with git grep/find to locate potential files
31
+ - Search for key terms, function names, and relevant patterns
32
+ - Example: execute_shell("git grep -l 'search_term'")
33
+
34
+ 2. Content Analysis:
35
+ - For each potential file, analyze its content
36
+ - Follow the file reading guidelines for large files
37
+ - Look for:
38
+ * Direct matches to requirement terms
39
+ * Related functionality
40
+ * Imported/referenced files
41
+ * Test files for modified code
42
+
43
+ FILE READING GUIDELINES:
44
+ 1. For Large Files (>200 lines):
45
+ - Do NOT read the entire file at once
46
+ - First use grep/ctags to locate relevant sections
47
+ - Then read specific sections with context
48
+ - Example:
49
+ * execute_shell("grep -n 'function_name' path/to/file")
50
+ * read_code("path/to/file", start_line=found_line-10, end_line=found_line+20)
51
+
52
+ 2. For Small Files:
53
+ - Can read entire file directly
54
+
55
+ IMPORTANT RULES:
56
+ - Only return files that are DIRECTLY related to the requirement
57
+ - Exclude false positives and loosely related files
58
+ - If a file only contains imports/references, don't include it
59
+ - Include both implementation and test files when relevant
60
+ - If unsure about a file, use grep/read_code to verify relevance
61
+ - Return empty list if no truly relevant files are found
62
+ - Do NOT modify any code, only find files
63
+
64
+ OUTPUT FORMAT:
65
+ - Only provide file paths in the specified YAML format
66
+ - No additional explanations or comments
36
67
  """,
37
68
  name="FindFileAgent",
38
69
  is_sub_agent=True,
39
70
  tool_registry=find_file_tool_registry,
40
71
  platform=PlatformRegistry().get_normal_platform(),
41
72
  auto_complete=True,
42
- summary_prompt="""Please provide the file path as this format(yaml list), if you can't find the file, please provide empty list:
73
+ summary_prompt="""Please provide the file paths as YAML list:
43
74
  <FILE_PATH>
44
75
  - file_path1
45
76
  - file_path2
@@ -9,7 +9,7 @@ from jarvis.models.registry import PlatformRegistry
9
9
  import concurrent.futures
10
10
  from threading import Lock
11
11
  from concurrent.futures import ThreadPoolExecutor
12
- from jarvis.utils import OutputType, PrettyOutput, find_git_root, get_file_md5, get_max_context_length, get_single_line_input, get_thread_count, load_embedding_model, load_rerank_model
12
+ from jarvis.utils import OutputType, PrettyOutput, find_git_root, get_file_md5, get_max_context_length, get_single_line_input, get_thread_count, load_embedding_model, load_rerank_model, user_confirm
13
13
  from jarvis.utils import init_env
14
14
  import argparse
15
15
  import pickle
@@ -443,16 +443,9 @@ Content: {content}
443
443
 
444
444
  # If force is True, continue directly
445
445
  if not force:
446
- # Ask the user whether to continue
447
- while True:
448
- response = get_single_line_input("Rebuild the index? [y/N]").lower().strip()
449
- if response in ['y', 'yes']:
450
- break
451
- elif response in ['', 'n', 'no']:
452
- PrettyOutput.print("Cancel rebuilding the index", output_type=OutputType.INFO)
453
- return
454
- else:
455
- PrettyOutput.print("Please input y or n", output_type=OutputType.WARNING)
446
+ if not user_confirm("Rebuild the index?", False):
447
+ PrettyOutput.print("Cancel rebuilding the index", output_type=OutputType.INFO)
448
+ return
456
449
 
457
450
  # Clean deleted files
458
451
  for file_path in files_to_delete:
@@ -718,7 +711,7 @@ Please output 3 expressions directly, separated by two line breaks, without numb
718
711
  message = "Found related files:\n"
719
712
  for path, score, _ in initial_results:
720
713
  message += f"File: {path} Similarity: {score:.3f}\n"
721
- PrettyOutput.print(message.rstrip(), output_type=OutputType.INFO)
714
+ PrettyOutput.print(message.rstrip(), output_type=OutputType.INFO, lang="markdown")
722
715
 
723
716
  # Reorder the preliminary results
724
717
  return self.pick_results(query, [path for path, _, _ in initial_results])
@@ -737,7 +730,7 @@ Please output 3 expressions directly, separated by two line breaks, without numb
737
730
  message = "Found related files:\n"
738
731
  for path in results:
739
732
  message += f"File: {path}\n"
740
- PrettyOutput.print(message.rstrip(), output_type=OutputType.SUCCESS)
733
+ PrettyOutput.print(message.rstrip(), output_type=OutputType.SUCCESS, lang="markdown")
741
734
 
742
735
  prompt = f"""You are a code expert, please answer the user's question based on the following file information:
743
736
  """
@@ -862,8 +855,8 @@ def main():
862
855
 
863
856
  output = "Search Results:\n"
864
857
  for path in results:
865
- output += f"""{path}\n"""
866
- PrettyOutput.print(output, output_type=OutputType.INFO)
858
+ output += f"""- {path}\n"""
859
+ PrettyOutput.print(output, output_type=OutputType.INFO, lang="markdown")
867
860
 
868
861
  elif args.command == 'ask':
869
862
  response = codebase.ask_codebase(args.question, args.top_k)
@@ -29,7 +29,7 @@ def list_platforms():
29
29
  output += f" • {model_name} - {description}\n"
30
30
  else:
31
31
  output += f" • {model_name}\n"
32
- PrettyOutput.print(output, OutputType.SUCCESS)
32
+ PrettyOutput.print(output, OutputType.SUCCESS, lang="markdown")
33
33
  else:
34
34
  PrettyOutput.print(" • No available model information", OutputType.WARNING)
35
35
 
jarvis/jarvis_rag/main.py CHANGED
@@ -699,7 +699,7 @@ Content: {doc.content}
699
699
  output = f"""File: {doc.metadata['file_path']}\n"""
700
700
  output += f"""Fragment {doc.metadata['chunk_index'] + 1}/{doc.metadata['total_chunks']}\n"""
701
701
  output += f"""Content:\n{doc.content}\n"""
702
- PrettyOutput.print(output, output_type=OutputType.INFO)
702
+ PrettyOutput.print(output, output_type=OutputType.INFO, lang="markdown")
703
703
 
704
704
  # Build base prompt
705
705
  base_prompt = f"""Please answer the user's question based on the following document fragments. If the document content is not sufficient to answer the question completely, please clearly indicate.
@@ -792,7 +792,7 @@ def main():
792
792
  output = f"""File: {doc.metadata['file_path']}\n"""
793
793
  output += f"""Fragment {doc.metadata['chunk_index'] + 1}/{doc.metadata['total_chunks']}\n"""
794
794
  output += f"""Content:\n{doc.content}\n"""
795
- PrettyOutput.print(output, output_type=OutputType.INFO)
795
+ PrettyOutput.print(output, output_type=OutputType.INFO, lang="markdown")
796
796
  return 0
797
797
 
798
798
  if args.ask:
@@ -87,13 +87,10 @@ def main():
87
87
  })
88
88
 
89
89
  if result["success"]:
90
- print(result["stdout"])
90
+ PrettyOutput.print(result["stdout"], OutputType.INFO, lang="markdown")
91
91
  else:
92
92
  PrettyOutput.print(result["stderr"], OutputType.ERROR)
93
- return 1
94
93
 
95
- return 0
96
-
97
94
 
98
95
  if __name__ == "__main__":
99
96
  main()
jarvis/tools/chdir.py CHANGED
@@ -3,8 +3,6 @@ import os
3
3
  from jarvis.utils import PrettyOutput, OutputType
4
4
 
5
5
  class ChdirTool:
6
- """修改当前工作目录的工具"""
7
-
8
6
  name = "chdir"
9
7
  description = "Change current working directory"
10
8
  parameters = {
@@ -19,22 +17,10 @@ class ChdirTool:
19
17
  }
20
18
 
21
19
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
22
- """执行目录切换
23
-
24
- Args:
25
- args: 包含 path 参数的字典
26
-
27
- Returns:
28
- 执行结果字典,包含:
29
- - success: 是否成功
30
- - stdout: 成功时的输出信息
31
- - error: 失败时的错误信息
32
- """
33
20
  try:
34
- path = os.path.expanduser(args["path"].strip()) # 展开 ~ 等路径
35
- path = os.path.abspath(path) # 转换为绝对路径
21
+ path = os.path.expanduser(args["path"].strip())
22
+ path = os.path.abspath(path)
36
23
 
37
- # 检查目录是否存在
38
24
  if not os.path.exists(path):
39
25
  return {
40
26
  "success": False,
@@ -42,7 +28,6 @@ class ChdirTool:
42
28
  "stderr": f"Directory does not exist: {path}"
43
29
  }
44
30
 
45
- # 检查是否是目录
46
31
  if not os.path.isdir(path):
47
32
  return {
48
33
  "success": False,
@@ -50,7 +35,6 @@ class ChdirTool:
50
35
  "stderr": f"The path is not a directory: {path}"
51
36
  }
52
37
 
53
- # 尝试切换目录
54
38
  old_path = os.getcwd()
55
39
  os.chdir(path)
56
40
 
@@ -72,22 +56,3 @@ class ChdirTool:
72
56
  "stdout": "",
73
57
  "stderr": f"Failed to switch directory: {str(e)}"
74
58
  }
75
-
76
- def main():
77
- """命令行直接运行工具"""
78
- import argparse
79
-
80
- parser = argparse.ArgumentParser(description='Change current working directory')
81
- parser.add_argument('path', help='Directory path to switch to, supports both relative and absolute paths')
82
- args = parser.parse_args()
83
-
84
- tool = ChdirTool()
85
- result = tool.execute({"path": args.path})
86
-
87
- if result["success"]:
88
- PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
89
- else:
90
- PrettyOutput.print(result["stderr"], OutputType.ERROR)
91
-
92
- if __name__ == "__main__":
93
- main()
@@ -1,27 +1,30 @@
1
- from typing import Dict, Any
1
+ from typing import Dict, Any, List
2
2
  import subprocess
3
3
  import yaml
4
4
  from jarvis.models.registry import PlatformRegistry
5
5
  from jarvis.tools.registry import ToolRegistry
6
6
  from jarvis.utils import OutputType, PrettyOutput, init_env, find_git_root
7
7
  from jarvis.agent import Agent
8
+ import re
8
9
 
9
10
  class CodeReviewTool:
10
11
  name = "code_review"
11
- description = "Autonomous code review agent for commit analysis"
12
+ description = "Autonomous code review agent for code changes analysis"
12
13
  parameters = {
13
14
  "type": "object",
14
15
  "properties": {
15
- "commit_sha": {
16
+ "review_type": {
16
17
  "type": "string",
17
- "description": "Target commit SHA to analyze"
18
+ "description": "Type of review: 'commit' for specific commit, 'current' for current changes",
19
+ "enum": ["commit", "current"],
20
+ "default": "current"
18
21
  },
19
- "requirement_desc": {
22
+ "commit_sha": {
20
23
  "type": "string",
21
- "description": "Development goal to verify"
24
+ "description": "Target commit SHA to analyze (required for review_type='commit')"
22
25
  }
23
26
  },
24
- "required": ["commit_sha", "requirement_desc"]
27
+ "required": []
25
28
  }
26
29
 
27
30
  def __init__(self):
@@ -30,11 +33,47 @@ class CodeReviewTool:
30
33
 
31
34
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
32
35
  try:
33
- commit_sha = args["commit_sha"].strip()
34
- requirement = args["requirement_desc"].strip()
36
+ review_type = args.get("review_type", "current").strip()
35
37
 
38
+ # Build git diff command based on review type
39
+ if review_type == "commit":
40
+ if "commit_sha" not in args:
41
+ return {
42
+ "success": False,
43
+ "stdout": {},
44
+ "stderr": "commit_sha is required for commit review type"
45
+ }
46
+ commit_sha = args["commit_sha"].strip()
47
+ diff_cmd = f"git show {commit_sha} | cat -"
48
+ else: # current changes
49
+ diff_cmd = "git diff HEAD | cat -"
50
+
51
+ # Execute git diff command
52
+ try:
53
+ diff_output = subprocess.check_output(diff_cmd, shell=True, text=True)
54
+ if not diff_output:
55
+ return {
56
+ "success": False,
57
+ "stdout": {},
58
+ "stderr": "No changes to review"
59
+ }
60
+ PrettyOutput.print(diff_output, OutputType.CODE, lang="diff")
61
+ except subprocess.CalledProcessError as e:
62
+ return {
63
+ "success": False,
64
+ "stdout": {},
65
+ "stderr": f"Failed to get diff: {str(e)}"
66
+ }
67
+
36
68
  system_prompt = """You are an autonomous code review expert. Perform in-depth analysis following these guidelines:
37
69
 
70
+ IMPORTANT:
71
+ - Only analyze the provided diff content
72
+ - Do NOT make assumptions about code not shown
73
+ - Do NOT invent or imagine potential issues
74
+ - Report ONLY issues that can be directly observed
75
+ - If something is unclear, state it explicitly rather than making assumptions
76
+
38
77
  REVIEW FOCUS AREAS:
39
78
  1. Requirement Alignment:
40
79
  - Verify implementation matches original requirements
@@ -90,44 +129,35 @@ REVIEW PROCESS:
90
129
  OUTPUT REQUIREMENTS:
91
130
  - Categorize issues by severity (Critical/Major/Minor)
92
131
  - Reference specific code locations
93
- - Provide concrete examples
94
- - Suggest actionable improvements
95
- - Highlight security risks clearly
96
- - Separate technical debt from blockers"""
97
-
98
- summary_prompt = """Please generate a concise summary report of the code review, format as yaml:
99
- <REPORT>
100
- - file: xxxx.py
101
- location: [start_line_number, end_line_number]
102
- description:
103
- severity:
104
- suggestion:
105
- </REPORT>
106
-
107
- Please describe in concise bullet points, highlighting important information.
132
+ - Provide concrete examples from the diff
133
+ - Suggest actionable improvements based on observed code
134
+ - Highlight security risks clearly with evidence from the code
135
+ - Separate technical debt from blockers
136
+ - If certain aspects cannot be reviewed due to limited context, note this explicitly
137
+ - Do not speculate about code not shown in the diff
108
138
  """
109
-
110
139
  tool_registry = ToolRegistry()
111
- tool_registry.use_tools(["execute_shell", "read_code", "ask_user", "ask_codebase", "find_in_codebase", "create_ctags_agent"])
112
140
  tool_registry.dont_use_tools(["code_review"])
113
-
114
- review_agent = Agent(
115
- name="Code Review Agent",
116
- platform=PlatformRegistry().get_thinking_platform(),
141
+ agent = Agent(
117
142
  system_prompt=system_prompt,
143
+ name="Code Review Agent",
144
+ summary_prompt="""Please generate a concise summary report of the code review, format as yaml:
145
+ <REPORT>
146
+ - file: xxxx.py
147
+ location: [start_line_number, end_line_number]
148
+ description: # Only describe issues directly observable in the diff
149
+ severity: # Critical/Major/Minor based on concrete evidence
150
+ suggestion: # Specific, actionable improvements for the observed code
151
+ </REPORT>""",
118
152
  is_sub_agent=True,
119
153
  tool_registry=tool_registry,
120
- summary_prompt=summary_prompt,
154
+ platform=PlatformRegistry().get_thinking_platform(),
121
155
  auto_complete=True
122
156
  )
123
-
124
- result = review_agent.run(
125
- f"Analyze commit {commit_sha} for requirement: {requirement}"
126
- )
127
-
157
+ result = agent.run(diff_output)
128
158
  return {
129
159
  "success": True,
130
- "stdout": {"report": result},
160
+ "stdout": result,
131
161
  "stderr": ""
132
162
  }
133
163
 
@@ -137,25 +167,42 @@ Please describe in concise bullet points, highlighting important information.
137
167
  "stdout": {},
138
168
  "stderr": f"Review failed: {str(e)}"
139
169
  }
170
+
171
+
172
+ def _extract_code_report(result: str) -> str:
173
+ sm = re.search(r"<REPORT>(.*?)</REPORT>", result, re.DOTALL)
174
+ if sm:
175
+ return sm.group(1)
176
+ return ""
140
177
 
141
178
  def main():
142
179
  """CLI entry point"""
143
180
  import argparse
144
181
 
145
182
  parser = argparse.ArgumentParser(description='Autonomous code review tool')
146
- parser.add_argument('--commit', required=True)
147
- parser.add_argument('--requirement', required=True)
183
+ parser.add_argument('--type', choices=['commit', 'current'], default='current',
184
+ help='Type of review: commit or current changes')
185
+ parser.add_argument('--commit', help='Commit SHA to review (required for commit type)')
148
186
  args = parser.parse_args()
149
187
 
188
+ # Validate arguments
189
+ if args.type == 'commit' and not args.commit:
190
+ parser.error("--commit is required when type is 'commit'")
191
+
150
192
  tool = CodeReviewTool()
151
- result = tool.execute({
152
- "commit_sha": args.commit,
153
- "requirement_desc": args.requirement
154
- })
193
+ tool_args = {
194
+ "review_type": args.type
195
+ }
196
+ if args.commit:
197
+ tool_args["commit_sha"] = args.commit
198
+
199
+ result = tool.execute(tool_args)
155
200
 
156
201
  if result["success"]:
157
- PrettyOutput.print("Autonomous Review Result:", OutputType.INFO)
158
- print(yaml.dump(result["stdout"], allow_unicode=True))
202
+ PrettyOutput.section("Autonomous Review Result:", OutputType.SUCCESS)
203
+ report = _extract_code_report(result["stdout"])
204
+ PrettyOutput.print(report, OutputType.SUCCESS, lang="yaml")
205
+
159
206
  else:
160
207
  PrettyOutput.print(result["stderr"], OutputType.ERROR)
161
208
 
@@ -162,15 +162,3 @@ class CtagsTool:
162
162
  "stdout": "",
163
163
  "stderr": f"Analysis failed: {str(e)}"
164
164
  }
165
-
166
- def main():
167
- """CLI testing"""
168
- init_env()
169
- tool = CtagsTool()
170
- query = get_multiline_input("Please enter your query:")
171
- result = tool.execute({
172
- "query": query
173
- })
174
- PrettyOutput.print(yaml.dump(result, default_style='|'), OutputType.INFO)
175
- if __name__ == "__main__":
176
- main()
@@ -76,33 +76,3 @@ class FindInCodebaseTool:
76
76
  "stdout": "",
77
77
  "stderr": f"Failed to execute search: {str(e)}"
78
78
  }
79
-
80
- def main():
81
- """Command line interface for the tool"""
82
- import argparse
83
-
84
- parser = argparse.ArgumentParser(description='Search for relevant files in codebase')
85
- parser.add_argument('query', help='Search query or requirement description')
86
- parser.add_argument('--top-k', type=int, default=20, help='Maximum number of results to return')
87
-
88
- args = parser.parse_args()
89
-
90
- tool = FindInCodebaseTool()
91
- result = tool.execute({
92
- "query": args.query,
93
- "top_k": args.top_k
94
- })
95
-
96
- if result["success"]:
97
- if result["stdout"]:
98
- print(result["stdout"])
99
- else:
100
- PrettyOutput.print("No relevant files found", OutputType.WARNING)
101
- else:
102
- PrettyOutput.print(result["stderr"], OutputType.ERROR)
103
- return 1
104
-
105
- return 0
106
-
107
- if __name__ == "__main__":
108
- exit(main())
@@ -31,7 +31,7 @@ class GitCommitTool:
31
31
  os.system("git add .")
32
32
  PrettyOutput.print("Get diff...", OutputType.SYSTEM)
33
33
  diff = os.popen("git diff --cached --exit-code").read()
34
- PrettyOutput.print(diff, OutputType.CODE)
34
+ PrettyOutput.print(diff, OutputType.CODE, lang="diff")
35
35
  prompt = f'''Please generate a commit message for the following changes.
36
36
  Format:
37
37
  <COMMIT_MESSAGE>
jarvis/tools/rag.py CHANGED
@@ -133,7 +133,7 @@ def main():
133
133
  })
134
134
 
135
135
  if result["success"]:
136
- PrettyOutput.print(f"Answer: {result['stdout']}", OutputType.INFO)
136
+ PrettyOutput.print(f"{result['stdout']}", OutputType.INFO, lang="markdown")
137
137
  else:
138
138
  PrettyOutput.print(result["stderr"], OutputType.ERROR)
139
139
 
jarvis/tools/read_code.py CHANGED
@@ -114,34 +114,3 @@ class ReadCodeTool:
114
114
  "stdout": "",
115
115
  "stderr": f"Failed to read code: {str(e)}"
116
116
  }
117
-
118
-
119
- def main():
120
- """Command line interface for the tool"""
121
- import argparse
122
-
123
- parser = argparse.ArgumentParser(description='Read code file with line numbers')
124
- parser.add_argument('filepath', help='Path to the code file')
125
- parser.add_argument('--start', type=int, default=0, help='Start line number (0-based)')
126
- parser.add_argument('--end', type=int, default=-1, help='End line number (0-based)')
127
-
128
- args = parser.parse_args()
129
-
130
- tool = ReadCodeTool()
131
- result = tool.execute({
132
- "filepath": args.filepath,
133
- "start_line": args.start,
134
- "end_line": args.end
135
- })
136
-
137
- if result["success"]:
138
- print(result["stdout"])
139
- else:
140
- PrettyOutput.print(result["stderr"], OutputType.ERROR)
141
- return 1
142
-
143
- return 0
144
-
145
-
146
- if __name__ == "__main__":
147
- main()
jarvis/utils.py CHANGED
@@ -4,7 +4,7 @@ import time
4
4
  import os
5
5
  from enum import Enum
6
6
  from datetime import datetime
7
- from typing import Any, Dict
7
+ from typing import Any, Dict, Optional
8
8
  import colorama
9
9
  from colorama import Fore, Style as ColoramaStyle
10
10
  import numpy as np
@@ -163,10 +163,10 @@ class PrettyOutput:
163
163
  return formatted
164
164
 
165
165
  @staticmethod
166
- def print(text: str, output_type: OutputType, timestamp: bool = True):
166
+ def print(text: str, output_type: OutputType, timestamp: bool = True, lang: Optional[str] = None):
167
167
  """Print formatted output using rich console"""
168
168
  # Get formatted header
169
- lang = PrettyOutput._detect_language(text, default_lang='markdown')
169
+ lang = lang if lang is not None else PrettyOutput._detect_language(text, default_lang='markdown')
170
170
  header = PrettyOutput.format("", output_type, timestamp)
171
171
 
172
172
  content = Syntax(text, lang, theme="monokai")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.103
3
+ Version: 0.1.104
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -153,20 +153,18 @@ Jarvis supports configuration through environment variables that can be set in t
153
153
 
154
154
  ## 🎯 Usage
155
155
 
156
- ### Main Assistant
156
+ ### Code Modification
157
157
  ```bash
158
+ # Using main agent
158
159
  jarvis
160
+
161
+ # Using code agent directly
162
+ jarvis-code-agent
159
163
  ```
160
164
 
161
- ### Codebase Search
165
+ ### Codebase Query
162
166
  ```bash
163
- # Generate codebase index
164
- jarvis-codebase generate
165
-
166
- # Search similar code
167
- jarvis-codebase search "your search query"
168
-
169
- # Ask questions about codebase
167
+ # Ask questions about the codebase
170
168
  jarvis-codebase ask "your question"
171
169
  ```
172
170
 
@@ -175,71 +173,98 @@ jarvis-codebase ask "your question"
175
173
  # Build document index
176
174
  jarvis-rag --dir /path/to/documents --build
177
175
 
178
- # Search documents
179
- jarvis-rag --query "your search query"
176
+ # Ask questions about documents
177
+ jarvis-rag --query "your question"
178
+ ```
179
+
180
+ ### Smart Shell
181
+ ```bash
182
+ # Using full name
183
+ jarvis-smart-shell "describe what you want to do"
184
+
185
+ # Using shorthand
186
+ jss "describe what you want to do"
180
187
  ```
181
188
 
182
- ### Search Tool
189
+ ### Development Tools
183
190
  ```bash
184
- # Basic search
185
- jarvis-search "your query"
191
+ # Manage git commits
192
+ jarvis-git-commit
186
193
 
187
- # Show only URLs
188
- jarvis-search "your query" --url-only
194
+ # Generate and manage ctags
195
+ jarvis-ctags
189
196
 
190
- # Limit results
191
- jarvis-search "your query" --max 3
197
+ # Manage AI platforms
198
+ jarvis-platform
192
199
  ```
193
200
 
194
- ## 🛠️ Tools
201
+ Each command supports `--help` flag for detailed usage information:
202
+ ```bash
203
+ jarvis --help
204
+ jarvis-code-agent --help
205
+ jarvis-codebase --help
206
+ jarvis-rag --help
207
+ jarvis-smart-shell --help
208
+ jarvis-platform --help
209
+ jarvis-git-commit --help
210
+ jarvis-ctags --help
211
+ ```
195
212
 
213
+ ## 🛠️ Tools
196
214
 
197
215
  ### Built-in Tools
198
216
 
199
217
  | Tool | Description |
200
218
  |------|-------------|
219
+ | read_code | Read code files with line numbers and range support |
201
220
  | execute_shell | Execute system commands and capture output |
202
- | file_operation | File operations (read/write/append/delete) |
203
- | generate_tool | AI-powered tool generation and integration |
204
- | methodology | Experience accumulation and methodology management |
205
- | create_sub_agent | Create specialized sub-agents for specific tasks |
206
- | coder | Automatic code modification and generation tool |
207
- | codebase | Codebase management and search tool |
221
+ | search | Web search for development related queries |
222
+ | ask_user | Interactive user input collection |
223
+ | ask_codebase | Intelligent codebase querying and analysis |
224
+ | code_review | Automated code review with multi-dimensional analysis |
225
+ | file_operation | Basic file operations (read/exists) |
226
+ | git_commiter | Automated git commit handling |
208
227
 
209
228
  ### Tool Locations
210
229
  - Built-in tools: `src/jarvis/tools/`
211
230
  - User tools: `~/.jarvis/tools/`
212
231
 
213
-
214
232
  ### Key Features
215
233
 
216
- #### 1. Self-Extending Capabilities
217
- - Tool generation through natural language description
218
- - Automatic code generation and integration
219
- - Dynamic capability expansion through sub-agents
220
- - Automatic code modification with version control
221
- - Codebase indexing and semantic search
222
-
223
- #### 2. Methodology Learning
224
- - Automatic experience accumulation from interactions
225
- - Pattern recognition and methodology extraction
226
- - Continuous refinement through usage
227
- - Code modification history tracking
228
- - Codebase analysis and documentation generation
229
-
230
- #### 3. Adaptive Problem Solving
231
- - Context-aware sub-agent creation
232
- - Dynamic tool composition
233
- - Learning from execution feedback
234
+ #### 1. Code Intelligence
235
+ - Smart file selection and analysis based on requirements
236
+ - Semantic codebase search and querying
237
+ - Efficient handling of large files with context-aware reading
238
+ - Precise patch-based code modifications
239
+ - Automated git commit management
240
+
241
+ #### 2. Multi-Model Architecture
242
+ - Support for multiple AI platforms (Kimi/OpenAI/AI8/OYI/Ollama)
243
+ - Platform-specific optimizations for different tasks
244
+ - Specialized models for code generation, thinking, and general tasks
245
+ - Streaming response support for better interaction
246
+ - Automatic model fallback and retry mechanisms
247
+
248
+ #### 3. RAG Capabilities
249
+ - Document indexing and semantic search
250
+ - Smart context management for large documents
251
+ - Automatic file change detection
252
+ - Efficient caching mechanisms
253
+ - Multi-format document support
254
+
255
+ #### 4. Development Tools
256
+ - Interactive shell command generation
257
+ - Code review with multi-dimensional analysis
234
258
  - Codebase-aware problem solving
235
- - Multi-model collaboration for complex tasks
236
-
237
- #### 4. Code Intelligence
238
- - Automatic codebase indexing
239
- - Semantic code search
240
- - Code modification with git integration
241
- - Code analysis and documentation
242
- - Multi-model code generation
259
+ - File operations with safety checks
260
+ - Progress tracking and error handling
261
+
262
+ #### 5. User Experience
263
+ - Beautiful console output with color support
264
+ - Interactive multi-line input
265
+ - Progress indicators for long operations
266
+ - Clear error messages and handling
267
+ - Context-aware response formatting
243
268
 
244
269
  ## 🎯 Extending Jarvis
245
270
 
@@ -1,17 +1,17 @@
1
- jarvis/__init__.py,sha256=A2vW7Ac_EmnSRhUOBJFq0qUWC2iJ1qwVxHAT5sJhxnk,51
1
+ jarvis/__init__.py,sha256=16lJ0KXB1-quQt7lnzbfKIeCnmBrimAGb3_CCqEl5Co,51
2
2
  jarvis/agent.py,sha256=6r5_pv3sumUrUCd2ntWVGg7yp1KTA3JCzz2IKH582k0,20010
3
- jarvis/utils.py,sha256=FiWpRM0RjSJyDRimhvU2xa5SIUI70rxWq4ItSeMOCfw,20715
3
+ jarvis/utils.py,sha256=x4wHSwoZ8pz32RJkxpZ0XdwEjikX5idXnCXUdtO8PtE,20783
4
4
  jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  jarvis/jarvis_code_agent/code_agent.py,sha256=8dIiFPZiWOEyIBDWUrqAdtn9g7eFrvvcCGPx5S56Ngc,6757
6
- jarvis/jarvis_code_agent/file_select.py,sha256=59s_w1E0ihY1RxBZ1kyXNyQVTHjmjO8L9mg2FtjrsyQ,8192
7
- jarvis/jarvis_code_agent/patch.py,sha256=du06gKWwmKcDPEtZmQJCOZbotNMKVtS-bz-8MYT78b0,4044
8
- jarvis/jarvis_code_agent/relevant_files.py,sha256=8rL-hfdelJhWSt6MJKaxmQmFXf-WY-O8L18Ntw9dpnE,2686
6
+ jarvis/jarvis_code_agent/file_select.py,sha256=KNxalhepCM2e-V__ca8ErmbXSXHP_1xmd0UEVWUXic8,8083
7
+ jarvis/jarvis_code_agent/patch.py,sha256=7nv-5-cPgSXZ6xfb_tmuITbCWEMRF8rLIMlQkDd7odw,4147
8
+ jarvis/jarvis_code_agent/relevant_files.py,sha256=mlJuj65TZ9atgTi85W3BW_0GcFNDNyf6JHe9yugHIr4,3965
9
9
  jarvis/jarvis_codebase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- jarvis/jarvis_codebase/main.py,sha256=Q_kVOjtL_AgSVkVUUYBNNKqA386GVxpnx0FXj1omUOc,36739
10
+ jarvis/jarvis_codebase/main.py,sha256=XjqIdo_vVuVoPT8HcyuuymXk4lX5mzxOk0teRZ7Mhic,36403
11
11
  jarvis/jarvis_platform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- jarvis/jarvis_platform/main.py,sha256=waLMHQmdecph_mZuPXWjpkmqibJFYHnCHroL9gL0nh0,4959
12
+ jarvis/jarvis_platform/main.py,sha256=LxpOKy7wGaBxgeR5bCG5m_CoYTHVQ9Vd23J-6SE2oUU,4976
13
13
  jarvis/jarvis_rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- jarvis/jarvis_rag/main.py,sha256=4St9VkaqK9zOq7AgurLB02nEj1_SvZAiFWhS3i_FcBY,33167
14
+ jarvis/jarvis_rag/main.py,sha256=00XeKbI6Qkd4NKRvtRLxClbCDrTJYot1bwIxWcui58k,33201
15
15
  jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  jarvis/jarvis_smart_shell/main.py,sha256=yWsD9Td81sr8I1pkimlDxucDPaLWb95NuCo4LCGnT7M,3947
17
17
  jarvis/models/__init__.py,sha256=mrOt67nselz_H1gX9wdAO4y2DY5WPXzABqJbr5Des8k,63
@@ -23,29 +23,28 @@ jarvis/models/openai.py,sha256=SAbVIvFO4q6bRl8zlDaH5bKbrP0T_zd1WzlbkPCvkwg,4121
23
23
  jarvis/models/oyi.py,sha256=nNBe-A0cOZ6vuGrnrUjeuC3N3oYRQeFazTUpFrAmx2w,15080
24
24
  jarvis/models/registry.py,sha256=nDYyGzT2uGSxbEbqp1JhuXa7bXeiMaX4hPAFAg74eyA,8683
25
25
  jarvis/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- jarvis/tools/ask_codebase.py,sha256=cYMQd2Ba0Ka_Kpt9dAJrbcPhaXvfY_-A8S6i0UxtY3w,2975
26
+ jarvis/tools/ask_codebase.py,sha256=1mLe9CHDU-NFJHmu3mxrWuA4IiHqQyum2ga31P3hLzU,2991
27
27
  jarvis/tools/ask_user.py,sha256=k0PcMqvCkf_W9kMWnFsgcFefVf1A5DhpM6WVXFMdhdQ,1823
28
28
  jarvis/tools/base.py,sha256=c0DMoDDPxmsqUYJR989zgUs7nIYRY6GWBrAdusIZKjc,656
29
- jarvis/tools/chdir.py,sha256=3aGvpvWO6Fj9RdjWXanjeNBDZ7kz3TO8_Zo8DurENDk,2934
30
- jarvis/tools/code_review.py,sha256=Reck765EIfhx8mteaJPw9IRnBkEzGS8INcQ0vVoKUw8,4939
31
- jarvis/tools/create_code_sub_agent.py,sha256=_G2HUWyik5FFCV1JU8JqF_mutcW6n6WWCvkhb5LGrL0,765
29
+ jarvis/tools/chdir.py,sha256=A53BNXFB9tvwoV_cxW_LpF_DfxANgAEJ8rjikTaTa-I,1813
30
+ jarvis/tools/code_review.py,sha256=IN9eM_Zh-k7dprvnScrUz4jTqcdkkszMeXa6qIItE3w,7140
32
31
  jarvis/tools/create_code_test_agent.py,sha256=SqdIpymoDUX7L6hh5vqnZLyeVwW-QmLfytU-xkG7Gag,3462
33
- jarvis/tools/create_ctags_agent.py,sha256=P-vqqUxh33R6kuMy8b5s3bANh1cVmkHpvz0vV5DNbXE,5184
32
+ jarvis/tools/create_ctags_agent.py,sha256=VAZUcst9DPCO6b_VP72geBZljWjfied09EPgSokYA0E,4878
34
33
  jarvis/tools/create_sub_agent.py,sha256=0lZDtYRFjr9C9xtBKV-sxWfhK0TX-cxAHj3Zez76A4s,2853
35
34
  jarvis/tools/execute_shell.py,sha256=bawfof8bUg3f9bjyCSifLa9bU-hkNoNOuos22uZffdg,2564
36
35
  jarvis/tools/file_operation.py,sha256=-1U_J5SEuBjRylzEl7wvCfjspNv6aA49UvFHLNQ3bJU,4098
37
- jarvis/tools/find_in_codebase.py,sha256=u-T6mEWv6JyE74fYZBjVlxXsqUnkf0BtgwVUy-SX4XI,3321
38
- jarvis/tools/git_commiter.py,sha256=BcapUhKymAV5Ofi-Cjg4nvYiAj4u5yBaOfsIr0iEp0c,2536
36
+ jarvis/tools/find_in_codebase.py,sha256=bxILvDox2oGd0XZ-gvfWjH7Yj4ciyMYC3VJI3aWiMw8,2455
37
+ jarvis/tools/git_commiter.py,sha256=7kJhtTyu09Cp4VP_IDKRrKXIKxQXkBF1drCgPkYzk6M,2549
39
38
  jarvis/tools/methodology.py,sha256=yZldtjPZpNq8eGJ6IbhwHB0v3cFUtfPd14r7LDCo5IU,5622
40
- jarvis/tools/rag.py,sha256=m8s-7dCPFhUrdTHvKj3HulNSsoOssBN7kqqn9n1l3Zw,4943
41
- jarvis/tools/read_code.py,sha256=_ObjMWirIYOdZi-D9KSRTd_4tg-5WwKLOn5ilrTF77I,4834
39
+ jarvis/tools/rag.py,sha256=2fQHqc4bw8JM-OxGTsHobLIOTo8Mip3rdtJCmAoY8XU,4952
40
+ jarvis/tools/read_code.py,sha256=5DGmeXTgumAiG0RP1xB4sF4NdmBm5BEGjRRlIBzjGnQ,4002
42
41
  jarvis/tools/read_webpage.py,sha256=JCReSXhkDHDkQ606sZYIKG1Itlprjpmu1sSbF-Ed-jI,2478
43
42
  jarvis/tools/registry.py,sha256=81Q_x9BJV6SIfPWURq4uzXxP2JCiFeaGbGM1IO5FSy4,11658
44
43
  jarvis/tools/search.py,sha256=IciWpdKoa03Kl5J1SdblI2VhkUBoIRuLHHM2X4KlMWE,9209
45
44
  jarvis/tools/select_code_files.py,sha256=bjJGwCNw0Ue_8jW60K1gcy1rUgKqoHihicu5SS58WNk,1890
46
- jarvis_ai_assistant-0.1.103.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
47
- jarvis_ai_assistant-0.1.103.dist-info/METADATA,sha256=Tr5iXpTFgFd9Z-iSNzIi1B0nB4HA6NfY2l5k4QRKgs8,12913
48
- jarvis_ai_assistant-0.1.103.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
49
- jarvis_ai_assistant-0.1.103.dist-info/entry_points.txt,sha256=jHc8XiYoVNlzKcvV5mA-uYvlDRUTO_74_glpb5vvvUg,494
50
- jarvis_ai_assistant-0.1.103.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
51
- jarvis_ai_assistant-0.1.103.dist-info/RECORD,,
45
+ jarvis_ai_assistant-0.1.104.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
46
+ jarvis_ai_assistant-0.1.104.dist-info/METADATA,sha256=_AFsS0M4n0yuT_7xZfUpB8UtgS0gYm-wfcGLxgnTRDY,13594
47
+ jarvis_ai_assistant-0.1.104.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
48
+ jarvis_ai_assistant-0.1.104.dist-info/entry_points.txt,sha256=9wmOanjcRugTjJWeDg4lKiUtePaymFUOIi-8Gm2azCU,502
49
+ jarvis_ai_assistant-0.1.104.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
50
+ jarvis_ai_assistant-0.1.104.dist-info/RECORD,,
@@ -1,9 +1,9 @@
1
1
  [console_scripts]
2
2
  jarvis = jarvis.agent:main
3
3
  jarvis-code-agent = jarvis.jarvis_code_agent.code_agent:main
4
+ jarvis-code-review = jarvis.tools.code_review:main
4
5
  jarvis-codebase = jarvis.jarvis_codebase.main:main
5
6
  jarvis-ctags = jarvis.tools.create_ctags_agent:main
6
- jarvis-gh = jarvis.jarvis_github.main:main
7
7
  jarvis-git-commit = jarvis.tools.git_commiter:main
8
8
  jarvis-platform = jarvis.jarvis_platform.main:main
9
9
  jarvis-rag = jarvis.jarvis_rag.main:main
@@ -1,30 +0,0 @@
1
-
2
-
3
-
4
- from typing import Any, Dict
5
- from jarvis.jarvis_code_agent.code_agent import CodeAgent
6
-
7
-
8
- class CodeSubAgentTool:
9
- name = "create_code_sub_agent"
10
- description = "Create a sub-agent to handle the code modification"
11
- parameters = {
12
- "type": "object",
13
- "properties": {
14
- "requirement": {
15
- "type": "string",
16
- "description": "The requirement of the sub-agent"
17
- }
18
- }
19
- }
20
-
21
- def execute(self, args: Dict) -> Dict[str, Any]:
22
- """Execute the sub-agent"""
23
- requirement = args["requirement"]
24
- agent = CodeAgent()
25
- output = agent.run(requirement)
26
- return {
27
- "success": True,
28
- "stdout": output,
29
- "stderr": ""
30
- }