jarvis-ai-assistant 0.1.122__py3-none-any.whl → 0.1.124__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +1 -1
- jarvis/jarvis_code_agent/code_agent.py +47 -86
- jarvis/jarvis_code_agent/file_select.py +0 -85
- jarvis/jarvis_code_agent/patch.py +164 -56
- jarvis/jarvis_dev/main.py +924 -0
- jarvis/jarvis_platform/base.py +21 -26
- jarvis/jarvis_platform/openai.py +1 -1
- jarvis/jarvis_tools/chdir.py +25 -0
- jarvis/jarvis_tools/create_code_agent.py +3 -6
- jarvis/jarvis_tools/execute_shell_script.py +58 -0
- jarvis/jarvis_tools/git_commiter.py +21 -15
- jarvis/jarvis_tools/read_code.py +1 -1
- jarvis/jarvis_tools/search.py +0 -1
- jarvis/jarvis_utils/__init__.py +72 -24
- {jarvis_ai_assistant-0.1.122.dist-info → jarvis_ai_assistant-0.1.124.dist-info}/METADATA +10 -10
- {jarvis_ai_assistant-0.1.122.dist-info → jarvis_ai_assistant-0.1.124.dist-info}/RECORD +21 -20
- {jarvis_ai_assistant-0.1.122.dist-info → jarvis_ai_assistant-0.1.124.dist-info}/WHEEL +1 -1
- {jarvis_ai_assistant-0.1.122.dist-info → jarvis_ai_assistant-0.1.124.dist-info}/entry_points.txt +1 -0
- jarvis/jarvis_code_agent/relevant_files.py +0 -117
- {jarvis_ai_assistant-0.1.122.dist-info → jarvis_ai_assistant-0.1.124.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.122.dist-info → jarvis_ai_assistant-0.1.124.dist-info}/top_level.txt +0 -0
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -32,37 +32,32 @@ class BasePlatform(ABC):
|
|
|
32
32
|
def _chat():
|
|
33
33
|
import time
|
|
34
34
|
start_time = time.time()
|
|
35
|
-
|
|
36
|
-
if self.suppress_output:
|
|
37
|
-
with yaspin(Spinners.dots, text="Thinking", color="yellow") as spinner:
|
|
38
|
-
response = self.chat(message)
|
|
39
|
-
spinner.ok("✓")
|
|
40
|
-
else:
|
|
41
|
-
response = self.chat(message)
|
|
35
|
+
response = self.chat(message)
|
|
42
36
|
|
|
43
37
|
# Calculate statistics
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
38
|
+
if not self.suppress_output:
|
|
39
|
+
end_time = time.time()
|
|
40
|
+
duration = end_time - start_time
|
|
41
|
+
char_count = len(response)
|
|
42
|
+
|
|
43
|
+
# Calculate token count and tokens per second
|
|
44
|
+
try:
|
|
45
|
+
from jarvis.jarvis_utils import get_context_token_count
|
|
46
|
+
token_count = get_context_token_count(response)
|
|
47
|
+
tokens_per_second = token_count / duration if duration > 0 else 0
|
|
48
|
+
except Exception as e:
|
|
49
|
+
PrettyOutput.print(f"Tokenization failed: {str(e)}", OutputType.WARNING)
|
|
50
|
+
token_count = 0
|
|
51
|
+
tokens_per_second = 0
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
# Print statistics
|
|
54
|
+
PrettyOutput.print(
|
|
55
|
+
f"对话完成 - 耗时: {duration:.2f}秒, 输出字符数: {char_count}, 输出Token数量: {token_count}, 每秒Token数量: {tokens_per_second:.2f}",
|
|
56
|
+
OutputType.INFO,
|
|
57
|
+
)
|
|
63
58
|
|
|
64
59
|
# Keep original think tag handling
|
|
65
|
-
response = re.sub(r'
|
|
60
|
+
response = re.sub(r'<think>.*?</think>', '', response, flags=re.DOTALL)
|
|
66
61
|
return response
|
|
67
62
|
|
|
68
63
|
return while_true(lambda: while_success(lambda: _chat(), 5), 5)
|
jarvis/jarvis_platform/openai.py
CHANGED
|
@@ -85,7 +85,7 @@ class OpenAIModel(BasePlatform):
|
|
|
85
85
|
full_response = ""
|
|
86
86
|
|
|
87
87
|
for chunk in response:
|
|
88
|
-
if chunk.choices[0].delta.content:
|
|
88
|
+
if chunk.choices and chunk.choices[0].delta.content:
|
|
89
89
|
text = chunk.choices[0].delta.content
|
|
90
90
|
if not self.suppress_output:
|
|
91
91
|
PrettyOutput.print_stream(text)
|
jarvis/jarvis_tools/chdir.py
CHANGED
|
@@ -17,10 +17,31 @@ class ChdirTool:
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
20
|
+
"""Execute directory change operation with comprehensive error handling.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
args: Dictionary containing 'path' key with target directory path
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Dictionary containing:
|
|
27
|
+
- success: Boolean indicating operation status
|
|
28
|
+
- stdout: Success message or empty string
|
|
29
|
+
- stderr: Error message or empty string
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
Handles and returns appropriate error messages for:
|
|
33
|
+
- Non-existent paths
|
|
34
|
+
- Non-directory paths
|
|
35
|
+
- Permission errors
|
|
36
|
+
- Generic exceptions
|
|
37
|
+
"""
|
|
38
|
+
# Main execution block with comprehensive error handling
|
|
20
39
|
try:
|
|
40
|
+
# Normalize and expand the input path (handles ~ and relative paths)
|
|
21
41
|
path = os.path.expanduser(args["path"].strip())
|
|
22
42
|
path = os.path.abspath(path)
|
|
23
43
|
|
|
44
|
+
# Validate that the target path exists
|
|
24
45
|
if not os.path.exists(path):
|
|
25
46
|
return {
|
|
26
47
|
"success": False,
|
|
@@ -28,6 +49,7 @@ class ChdirTool:
|
|
|
28
49
|
"stderr": f"Directory does not exist: {path}"
|
|
29
50
|
}
|
|
30
51
|
|
|
52
|
+
# Ensure the path points to a directory, not a file
|
|
31
53
|
if not os.path.isdir(path):
|
|
32
54
|
return {
|
|
33
55
|
"success": False,
|
|
@@ -35,6 +57,7 @@ class ChdirTool:
|
|
|
35
57
|
"stderr": f"The path is not a directory: {path}"
|
|
36
58
|
}
|
|
37
59
|
|
|
60
|
+
# Capture current directory and attempt to change to new path
|
|
38
61
|
old_path = os.getcwd()
|
|
39
62
|
os.chdir(path)
|
|
40
63
|
|
|
@@ -44,12 +67,14 @@ class ChdirTool:
|
|
|
44
67
|
"stderr": ""
|
|
45
68
|
}
|
|
46
69
|
|
|
70
|
+
# Handle cases where user lacks directory access permissions
|
|
47
71
|
except PermissionError:
|
|
48
72
|
return {
|
|
49
73
|
"success": False,
|
|
50
74
|
"stdout": "",
|
|
51
75
|
"stderr": f"No permission to access directory: {path}"
|
|
52
76
|
}
|
|
77
|
+
# Catch-all for any other unexpected errors during directory change
|
|
53
78
|
except Exception as e:
|
|
54
79
|
return {
|
|
55
80
|
"success": False,
|
|
@@ -3,7 +3,7 @@ from typing import Dict, Any
|
|
|
3
3
|
from jarvis.jarvis_code_agent.code_agent import CodeAgent
|
|
4
4
|
from jarvis.jarvis_tools.git_commiter import GitCommitTool
|
|
5
5
|
from jarvis.jarvis_tools.code_review import CodeReviewTool, extract_code_report
|
|
6
|
-
from jarvis.jarvis_utils import OutputType, PrettyOutput, has_uncommitted_changes
|
|
6
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput, has_uncommitted_changes, get_latest_commit_hash
|
|
7
7
|
|
|
8
8
|
class CreateCodeAgentTool:
|
|
9
9
|
"""Tool for managing the code development workflow."""
|
|
@@ -14,9 +14,6 @@ class CreateCodeAgentTool:
|
|
|
14
14
|
"requirement": "Technical specifications for code implementation"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
def _get_current_commit(self) -> str:
|
|
18
|
-
"""Get current commit hash."""
|
|
19
|
-
return os.popen("git rev-parse HEAD").read().strip()
|
|
20
17
|
|
|
21
18
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
22
19
|
try:
|
|
@@ -42,7 +39,7 @@ class CreateCodeAgentTool:
|
|
|
42
39
|
}
|
|
43
40
|
|
|
44
41
|
# Get current commit hash
|
|
45
|
-
start_commit =
|
|
42
|
+
start_commit = get_latest_commit_hash()
|
|
46
43
|
|
|
47
44
|
# Step 2: Development
|
|
48
45
|
PrettyOutput.print("开始开发...", OutputType.INFO)
|
|
@@ -50,7 +47,7 @@ class CreateCodeAgentTool:
|
|
|
50
47
|
agent.run(requirement)
|
|
51
48
|
|
|
52
49
|
# Get new commit hash after development
|
|
53
|
-
end_commit =
|
|
50
|
+
end_commit = get_latest_commit_hash()
|
|
54
51
|
|
|
55
52
|
# Step 3: Code Review
|
|
56
53
|
PrettyOutput.print("开始代码审查...", OutputType.INFO)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from typing import Dict, Any
|
|
2
|
+
import os
|
|
3
|
+
import tempfile
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput
|
|
6
|
+
|
|
7
|
+
class ShellScriptTool:
|
|
8
|
+
name = "execute_shell_script"
|
|
9
|
+
description = """Execute shell script file and return result"""
|
|
10
|
+
parameters = {
|
|
11
|
+
"type": "object",
|
|
12
|
+
"properties": {
|
|
13
|
+
"script_content": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Content of the shell script to execute"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"required": ["script_content"]
|
|
19
|
+
}
|
|
20
|
+
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
21
|
+
"""Execute shell script content"""
|
|
22
|
+
try:
|
|
23
|
+
script_content = args.get("script_content", "").strip()
|
|
24
|
+
if not script_content:
|
|
25
|
+
return {
|
|
26
|
+
"success": False,
|
|
27
|
+
"stdout": "",
|
|
28
|
+
"stderr": "Missing or empty script_content parameter"
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# Create temporary script file
|
|
32
|
+
script_path = os.path.join(tempfile.gettempdir(), f"jarvis_script_{os.getpid()}.sh")
|
|
33
|
+
try:
|
|
34
|
+
with open(script_path, 'w', encoding='utf-8') as f:
|
|
35
|
+
f.write(script_content)
|
|
36
|
+
os.chmod(script_path, 0o755) # Make script executable
|
|
37
|
+
|
|
38
|
+
# Use execute_shell to run the script
|
|
39
|
+
from jarvis.jarvis_tools.execute_shell import ShellTool
|
|
40
|
+
shell_tool = ShellTool()
|
|
41
|
+
result = shell_tool.execute({"command": script_path})
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
"success": result["success"],
|
|
45
|
+
"stdout": result["stdout"],
|
|
46
|
+
"stderr": result["stderr"]
|
|
47
|
+
}
|
|
48
|
+
finally:
|
|
49
|
+
# Clean up temporary script file
|
|
50
|
+
Path(script_path).unlink(missing_ok=True)
|
|
51
|
+
|
|
52
|
+
except Exception as e:
|
|
53
|
+
PrettyOutput.print(str(e), OutputType.ERROR)
|
|
54
|
+
return {
|
|
55
|
+
"success": False,
|
|
56
|
+
"stdout": "",
|
|
57
|
+
"stderr": str(e)
|
|
58
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import os
|
|
2
1
|
import re
|
|
3
2
|
import shlex
|
|
4
3
|
import subprocess
|
|
@@ -8,13 +7,23 @@ import yaml
|
|
|
8
7
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
9
8
|
from jarvis.jarvis_utils import OutputType, PrettyOutput, has_uncommitted_changes, init_env
|
|
10
9
|
import sys
|
|
10
|
+
import argparse
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class GitCommitTool:
|
|
14
14
|
name = "git_commit_agent"
|
|
15
15
|
description = "Automatically generate and execute git commits based on code changes"
|
|
16
|
-
parameters = {
|
|
17
|
-
|
|
16
|
+
parameters = {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": {
|
|
19
|
+
"lang": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Language for commit message",
|
|
22
|
+
"default": "Chinese"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"required": []
|
|
26
|
+
}
|
|
18
27
|
def _extract_commit_message(self, message):
|
|
19
28
|
"""Raw extraction preserving all characters"""
|
|
20
29
|
r = re.search(
|
|
@@ -59,26 +68,20 @@ class GitCommitTool:
|
|
|
59
68
|
PrettyOutput.print(diff, OutputType.CODE, lang="diff")
|
|
60
69
|
|
|
61
70
|
prompt = f'''Generate commit message with the paranoia of someone who's lost production data:
|
|
62
|
-
|
|
63
|
-
# Format Enforcement Protocol
|
|
64
|
-
FAILURE TO WRAP MESSAGE IN <COMMIT_MESSAGE> TAGS WILL CAUSE SYSTEM REJECTION
|
|
65
|
-
|
|
71
|
+
You should write commit message in {args.get('lang', 'Chinese')}
|
|
66
72
|
# Required Structure
|
|
67
73
|
YOU MUST USE EXACTLY THIS FORMAT:
|
|
68
|
-
|
|
69
74
|
<COMMIT_MESSAGE>
|
|
70
75
|
<type>(<scope>): <subject>
|
|
71
|
-
|
|
72
|
-
[Body description in imperative mood]
|
|
76
|
+
Body description in imperative mood
|
|
73
77
|
</COMMIT_MESSAGE>
|
|
74
|
-
|
|
75
78
|
# Format Rules
|
|
76
79
|
1. Types: fix, feat, docs, style, refactor, test, chore
|
|
77
80
|
2. Scope indicates module (e.g. auth, database)
|
|
78
81
|
3. Subject line <= 72 chars, no period
|
|
79
|
-
4. Body explains WHAT and WHY, using present tense
|
|
80
|
-
|
|
81
|
-
# Analysis Material
|
|
82
|
+
4. Body explains WHAT and WHY for every change, using present tense
|
|
83
|
+
5. Do not omit any changes
|
|
84
|
+
# Analysis Material
|
|
82
85
|
{diff}
|
|
83
86
|
'''
|
|
84
87
|
|
|
@@ -121,8 +124,11 @@ YOU MUST USE EXACTLY THIS FORMAT:
|
|
|
121
124
|
|
|
122
125
|
def main():
|
|
123
126
|
init_env()
|
|
127
|
+
parser = argparse.ArgumentParser(description='Git commit tool')
|
|
128
|
+
parser.add_argument('--lang', type=str, default='Chinese', help='Language for commit messages')
|
|
129
|
+
args = parser.parse_args()
|
|
124
130
|
tool = GitCommitTool()
|
|
125
|
-
tool.execute({})
|
|
131
|
+
tool.execute({"lang": args.lang if hasattr(args, 'lang') else 'Chinese'})
|
|
126
132
|
|
|
127
133
|
if __name__ == "__main__":
|
|
128
134
|
sys.exit(main())
|
jarvis/jarvis_tools/read_code.py
CHANGED
|
@@ -119,7 +119,7 @@ class ReadCodeTool:
|
|
|
119
119
|
formatted_lines.append(f"{line_num:>5}:{line}")
|
|
120
120
|
|
|
121
121
|
content = "".join(formatted_lines)
|
|
122
|
-
output = f"
|
|
122
|
+
output = f"\n\nFile: {filepath}\nLines: [{start_line}, {end_line}]\n{content}"
|
|
123
123
|
return {
|
|
124
124
|
"success": True,
|
|
125
125
|
"stdout": output,
|
jarvis/jarvis_tools/search.py
CHANGED
jarvis/jarvis_utils/__init__.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, List, Optional
|
|
7
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
8
8
|
import colorama
|
|
9
9
|
from colorama import Fore, Style as ColoramaStyle
|
|
10
10
|
import numpy as np
|
|
@@ -196,29 +196,26 @@ class PrettyOutput:
|
|
|
196
196
|
"""
|
|
197
197
|
|
|
198
198
|
|
|
199
|
+
# Define styles for different output types
|
|
199
200
|
# Define styles for different output types
|
|
200
201
|
styles = {
|
|
201
202
|
OutputType.SYSTEM: RichStyle(
|
|
202
203
|
color="bright_cyan",
|
|
203
|
-
italic=True,
|
|
204
204
|
bold=True,
|
|
205
205
|
),
|
|
206
206
|
OutputType.CODE: RichStyle(
|
|
207
207
|
color="green",
|
|
208
|
-
italic=True,
|
|
209
208
|
bgcolor="#1a1a1a",
|
|
210
209
|
frame=True
|
|
211
210
|
),
|
|
212
211
|
OutputType.RESULT: RichStyle(
|
|
213
212
|
color="bright_blue",
|
|
214
213
|
bold=True,
|
|
215
|
-
italic=True,
|
|
216
214
|
bgcolor="navy_blue"
|
|
217
215
|
),
|
|
218
216
|
OutputType.ERROR: RichStyle(
|
|
219
217
|
color="red",
|
|
220
218
|
bold=True,
|
|
221
|
-
italic=True,
|
|
222
219
|
blink=True,
|
|
223
220
|
bgcolor="dark_red",
|
|
224
221
|
),
|
|
@@ -226,47 +223,39 @@ class PrettyOutput:
|
|
|
226
223
|
color="gold1",
|
|
227
224
|
dim=True,
|
|
228
225
|
bgcolor="grey11",
|
|
229
|
-
italic=True
|
|
230
226
|
),
|
|
231
227
|
OutputType.PLANNING: RichStyle(
|
|
232
228
|
color="purple",
|
|
233
|
-
italic=True,
|
|
234
229
|
bold=True,
|
|
235
230
|
),
|
|
236
231
|
OutputType.PROGRESS: RichStyle(
|
|
237
232
|
color="white",
|
|
238
233
|
encircle=True,
|
|
239
|
-
italic=True,
|
|
240
234
|
),
|
|
241
235
|
OutputType.SUCCESS: RichStyle(
|
|
242
236
|
color="bright_green",
|
|
243
237
|
bold=True,
|
|
244
238
|
strike=False,
|
|
245
239
|
meta={"icon": "✓"},
|
|
246
|
-
italic=True
|
|
247
240
|
),
|
|
248
241
|
OutputType.WARNING: RichStyle(
|
|
249
242
|
color="yellow",
|
|
250
243
|
bold=True,
|
|
251
244
|
blink2=True,
|
|
252
245
|
bgcolor="dark_orange",
|
|
253
|
-
italic=True
|
|
254
246
|
),
|
|
255
247
|
OutputType.DEBUG: RichStyle(
|
|
256
248
|
color="grey58",
|
|
257
249
|
dim=True,
|
|
258
|
-
italic=True,
|
|
259
250
|
conceal=True
|
|
260
251
|
),
|
|
261
252
|
OutputType.USER: RichStyle(
|
|
262
253
|
color="spring_green2",
|
|
263
254
|
reverse=True,
|
|
264
255
|
frame=True,
|
|
265
|
-
italic=True
|
|
266
256
|
),
|
|
267
257
|
OutputType.TOOL: RichStyle(
|
|
268
258
|
color="dark_sea_green4",
|
|
269
|
-
italic=True,
|
|
270
259
|
bgcolor="grey19",
|
|
271
260
|
)
|
|
272
261
|
}
|
|
@@ -412,7 +401,7 @@ class FileCompleter(Completer):
|
|
|
412
401
|
if file_path and score < 100:
|
|
413
402
|
display_text = f"{path} ({score}%)"
|
|
414
403
|
completion = Completion(
|
|
415
|
-
text=f"
|
|
404
|
+
text=f"'{path}'", # 添加单引号包裹路径
|
|
416
405
|
start_position=-replace_length,
|
|
417
406
|
display=display_text,
|
|
418
407
|
display_meta="File"
|
|
@@ -517,21 +506,80 @@ def while_true(func, sleep_time: float = 0.1):
|
|
|
517
506
|
time.sleep(sleep_time)
|
|
518
507
|
return ret
|
|
519
508
|
|
|
520
|
-
def find_git_root(
|
|
521
|
-
|
|
522
|
-
os.chdir(
|
|
523
|
-
|
|
524
|
-
os.chdir(
|
|
525
|
-
return
|
|
509
|
+
def find_git_root(start_dir="."):
|
|
510
|
+
"""Change to git root directory of the given path"""
|
|
511
|
+
os.chdir(start_dir)
|
|
512
|
+
git_root = os.popen("git rev-parse --show-toplevel").read().strip()
|
|
513
|
+
os.chdir(git_root)
|
|
514
|
+
return git_root
|
|
526
515
|
|
|
527
516
|
def has_uncommitted_changes():
|
|
528
|
-
|
|
517
|
+
import subprocess
|
|
518
|
+
# Add all changes silently
|
|
519
|
+
subprocess.run(["git", "add", "."], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
520
|
+
|
|
529
521
|
# Check working directory changes
|
|
530
|
-
working_changes =
|
|
522
|
+
working_changes = subprocess.run(["git", "diff", "--exit-code"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode != 0
|
|
523
|
+
|
|
531
524
|
# Check staged changes
|
|
532
|
-
staged_changes =
|
|
533
|
-
|
|
525
|
+
staged_changes = subprocess.run(["git", "diff", "--cached", "--exit-code"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode != 0
|
|
526
|
+
|
|
527
|
+
# Reset changes silently
|
|
528
|
+
subprocess.run(["git", "reset"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
529
|
+
|
|
534
530
|
return working_changes or staged_changes
|
|
531
|
+
def get_commits_between(start_hash: str, end_hash: str) -> List[Tuple[str, str]]:
|
|
532
|
+
"""Get list of commits between two commit hashes
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
start_hash: Starting commit hash (exclusive)
|
|
536
|
+
end_hash: Ending commit hash (inclusive)
|
|
537
|
+
|
|
538
|
+
Returns:
|
|
539
|
+
List[Tuple[str, str]]: List of (commit_hash, commit_message) tuples
|
|
540
|
+
"""
|
|
541
|
+
try:
|
|
542
|
+
import subprocess
|
|
543
|
+
# Use git log with pretty format to get hash and message
|
|
544
|
+
result = subprocess.run(
|
|
545
|
+
['git', 'log', f'{start_hash}..{end_hash}', '--pretty=format:%H|%s'],
|
|
546
|
+
stdout=subprocess.PIPE,
|
|
547
|
+
stderr=subprocess.PIPE,
|
|
548
|
+
text=True
|
|
549
|
+
)
|
|
550
|
+
if result.returncode != 0:
|
|
551
|
+
PrettyOutput.print(f"获取commit历史失败: {result.stderr}", OutputType.ERROR)
|
|
552
|
+
return []
|
|
553
|
+
|
|
554
|
+
commits = []
|
|
555
|
+
for line in result.stdout.splitlines():
|
|
556
|
+
if '|' in line:
|
|
557
|
+
commit_hash, message = line.split('|', 1)
|
|
558
|
+
commits.append((commit_hash, message))
|
|
559
|
+
return commits
|
|
560
|
+
|
|
561
|
+
except Exception as e:
|
|
562
|
+
PrettyOutput.print(f"获取commit历史异常: {str(e)}", OutputType.ERROR)
|
|
563
|
+
return []
|
|
564
|
+
def get_latest_commit_hash() -> str:
|
|
565
|
+
"""Get the latest commit hash of the current git repository
|
|
566
|
+
|
|
567
|
+
Returns:
|
|
568
|
+
str: The commit hash, or empty string if not in a git repo or error occurs
|
|
569
|
+
"""
|
|
570
|
+
try:
|
|
571
|
+
import subprocess
|
|
572
|
+
result = subprocess.run(
|
|
573
|
+
['git', 'rev-parse', 'HEAD'],
|
|
574
|
+
stdout=subprocess.PIPE,
|
|
575
|
+
stderr=subprocess.PIPE,
|
|
576
|
+
text=True
|
|
577
|
+
)
|
|
578
|
+
if result.returncode == 0:
|
|
579
|
+
return result.stdout.strip()
|
|
580
|
+
return ""
|
|
581
|
+
except Exception:
|
|
582
|
+
return ""
|
|
535
583
|
|
|
536
584
|
def load_embedding_model():
|
|
537
585
|
model_name = "BAAI/bge-m3"
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.124
|
|
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
|
|
7
|
-
Author-email:
|
|
7
|
+
Author-email: skyfire <skyfireitdiy@hotmail.com>
|
|
8
8
|
License: MIT License
|
|
9
9
|
|
|
10
10
|
Copyright (c) 2025 skyfire
|
|
@@ -28,24 +28,25 @@ License: MIT License
|
|
|
28
28
|
SOFTWARE.
|
|
29
29
|
Project-URL: Homepage, https://github.com/skyfireitdiy/Jarvis
|
|
30
30
|
Keywords: jarvis,ai,assistant,tools,automation
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
31
33
|
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
-
Classifier:
|
|
34
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
33
35
|
Classifier: Programming Language :: Python :: 3
|
|
34
36
|
Classifier: Programming Language :: Python :: 3.8
|
|
35
37
|
Classifier: Programming Language :: Python :: 3.9
|
|
36
38
|
Classifier: Programming Language :: Python :: 3.10
|
|
37
39
|
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
39
40
|
Requires-Python: >=3.8
|
|
40
41
|
Description-Content-Type: text/markdown
|
|
41
42
|
License-File: LICENSE
|
|
42
43
|
Requires-Dist: requests>=2.25.1
|
|
43
44
|
Requires-Dist: pyyaml>=5.1
|
|
44
45
|
Requires-Dist: colorama>=0.4.6
|
|
45
|
-
Requires-Dist:
|
|
46
|
+
Requires-Dist: prompt-toolkit>=3.0.0
|
|
46
47
|
Requires-Dist: openai>=1.20.0
|
|
47
48
|
Requires-Dist: playwright>=1.41.1
|
|
48
|
-
Requires-Dist: numpy>=1.
|
|
49
|
+
Requires-Dist: numpy>=1.19.5
|
|
49
50
|
Requires-Dist: faiss-cpu>=1.8.0
|
|
50
51
|
Requires-Dist: sentence-transformers>=2.2.2
|
|
51
52
|
Requires-Dist: bs4>=0.0.1
|
|
@@ -61,14 +62,13 @@ Requires-Dist: fuzzywuzzy>=0.18.0
|
|
|
61
62
|
Requires-Dist: python-Levenshtein>=0.25.0
|
|
62
63
|
Requires-Dist: jedi>=0.17.2
|
|
63
64
|
Requires-Dist: psutil>=7.0.0
|
|
65
|
+
Requires-Dist: fastapi>=0.115.4
|
|
66
|
+
Requires-Dist: uvicorn>=0.33.0
|
|
64
67
|
Provides-Extra: dev
|
|
65
68
|
Requires-Dist: pytest; extra == "dev"
|
|
66
69
|
Requires-Dist: black; extra == "dev"
|
|
67
70
|
Requires-Dist: isort; extra == "dev"
|
|
68
71
|
Requires-Dist: mypy; extra == "dev"
|
|
69
|
-
Dynamic: author
|
|
70
|
-
Dynamic: home-page
|
|
71
|
-
Dynamic: requires-python
|
|
72
72
|
|
|
73
73
|
<div align="center">
|
|
74
74
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
2
|
-
jarvis/jarvis_agent/__init__.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=IEWrPxaE2RuPsf_eQCJWAuNjrMdwTLc1r-X__zq4Tow,51
|
|
2
|
+
jarvis/jarvis_agent/__init__.py,sha256=zOjtzMX98v7qSFQ71jUmRFyOfYUo9z0gpz7sRSlnw4Q,22435
|
|
3
3
|
jarvis/jarvis_agent/output_handler.py,sha256=kJeFTjjSu0K_2p0wyhq2veSZuhRXoaFC_8wVaoBKX0w,401
|
|
4
4
|
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
jarvis/jarvis_code_agent/code_agent.py,sha256=
|
|
6
|
-
jarvis/jarvis_code_agent/file_select.py,sha256=
|
|
7
|
-
jarvis/jarvis_code_agent/patch.py,sha256=
|
|
8
|
-
jarvis/jarvis_code_agent/relevant_files.py,sha256=Z9bHJ6qkRu8EhD06kS_e0raqrsUgRUwkYf5mgBfdKP8,3392
|
|
5
|
+
jarvis/jarvis_code_agent/code_agent.py,sha256=8Jwpo9iEDb8W_zGr82iwkGw2eFRidExFLMw2MJPTjAI,5774
|
|
6
|
+
jarvis/jarvis_code_agent/file_select.py,sha256=nBPNUSOXiCun56quOMMBUtS93k3AAb_I1m20h5kS2bM,8509
|
|
7
|
+
jarvis/jarvis_code_agent/patch.py,sha256=NzQbSnVGvzTe2wT67M2zbENB3f2jy2aGcaE8SRtzEDU,14018
|
|
9
8
|
jarvis/jarvis_codebase/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
9
|
jarvis/jarvis_codebase/main.py,sha256=qwB74U9YDgqvBSdvglQ62HmPkBT_Y5x5YF4J8LnzbQU,39778
|
|
10
|
+
jarvis/jarvis_dev/main.py,sha256=zNV7P0d9-jjZ5XAAq_o2FAYqcBfn_lai89mJgomL6fM,24270
|
|
11
11
|
jarvis/jarvis_lsp/base.py,sha256=_7pdbMKjdtYBW0DsRbjIodDHM3J7df-YgXHejN_WIrU,4490
|
|
12
12
|
jarvis/jarvis_lsp/cpp.py,sha256=sYQHEl0FoVC5Iw2pJvvGKpeNLD95XjNuTOINvdZLgME,4986
|
|
13
13
|
jarvis/jarvis_lsp/go.py,sha256=3soEuID2XV65zaxyR70RxNsvtm02l9PEZ46F_nsDdqY,5311
|
|
@@ -17,10 +17,10 @@ jarvis/jarvis_lsp/rust.py,sha256=ZvUoOZm9GWLl3kobfByBuTGrQ8aM2dLuNxS_NHr1aQQ,554
|
|
|
17
17
|
jarvis/jarvis_multi_agent/__init__.py,sha256=Z6QaRZrqUUa6r6Pe_KZi34Ymle5amQe1N-AINxiOi1c,6011
|
|
18
18
|
jarvis/jarvis_platform/__init__.py,sha256=mrOt67nselz_H1gX9wdAO4y2DY5WPXzABqJbr5Des8k,63
|
|
19
19
|
jarvis/jarvis_platform/ai8.py,sha256=rVPcbf0EbXV3lUPEmd_aO6UzYT0AHo4w13iGhHGvbjo,11964
|
|
20
|
-
jarvis/jarvis_platform/base.py,sha256=
|
|
20
|
+
jarvis/jarvis_platform/base.py,sha256=Z-GTDyySuc9TrQD0LmI3uqnWLHGiy0ge_Uu-pQhJn9o,3456
|
|
21
21
|
jarvis/jarvis_platform/kimi.py,sha256=dQM4RLSfDiJwNV25qNWPKqseEpPTo7fel3SI2Pot3l4,15701
|
|
22
22
|
jarvis/jarvis_platform/ollama.py,sha256=TsBEg8crPmBiLvMRDtXYVa2AIdeog36MmW2tn5j9x8U,5613
|
|
23
|
-
jarvis/jarvis_platform/openai.py,sha256=
|
|
23
|
+
jarvis/jarvis_platform/openai.py,sha256=Ofu-J4HmteyoPsxCHvCEDlY5J7-8t3qWr8QsCprw9-8,4463
|
|
24
24
|
jarvis/jarvis_platform/oyi.py,sha256=YueBOGVMR33eTcQPRdfDdQPlM2g5awnYzYqA6z0Y1cg,15016
|
|
25
25
|
jarvis/jarvis_platform/registry.py,sha256=h6gInSOMkUbvYqzNYwYliFLOyga5fS-WlODaw-YTICU,8514
|
|
26
26
|
jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -34,13 +34,14 @@ jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
|
34
34
|
jarvis/jarvis_tools/ask_codebase.py,sha256=-4oIe7maa-60w5-QZxOGVt47W0kVd6TB-eIU77fIIMw,3005
|
|
35
35
|
jarvis/jarvis_tools/ask_user.py,sha256=tIyiKk9F8xchjQ3Yh5fMQjhpflQTuh75HTuXMftGxZY,1827
|
|
36
36
|
jarvis/jarvis_tools/base.py,sha256=c0DMoDDPxmsqUYJR989zgUs7nIYRY6GWBrAdusIZKjc,656
|
|
37
|
-
jarvis/jarvis_tools/chdir.py,sha256=
|
|
37
|
+
jarvis/jarvis_tools/chdir.py,sha256=8v7bhYNQOW2BCwS2H4g4a0ozrzKDl-3VXxHE5S7SENY,2981
|
|
38
38
|
jarvis/jarvis_tools/code_review.py,sha256=ZMWCrkVECCVaT7UyZV0_v49Gecws-x_dQ0NamFUunEs,9775
|
|
39
|
-
jarvis/jarvis_tools/create_code_agent.py,sha256=
|
|
39
|
+
jarvis/jarvis_tools/create_code_agent.py,sha256=SAwIGBEz2i-XL-F7J7yXWYqoZzFo1i1sx4yfABh7cAo,3777
|
|
40
40
|
jarvis/jarvis_tools/create_sub_agent.py,sha256=ldpNn5LczybExvt9Sz4t1ybetLX-dTJIAF5f_oH-Z3M,2869
|
|
41
41
|
jarvis/jarvis_tools/execute_shell.py,sha256=MwgVyI1O1wshU9yR-DvSWIgoSQpVjtH9JpjVQvSrKF0,2566
|
|
42
|
+
jarvis/jarvis_tools/execute_shell_script.py,sha256=1F4nYnlYyB3JVFylhS-6wABDBD8eyzQ7hm0FP9DlirA,2118
|
|
42
43
|
jarvis/jarvis_tools/file_operation.py,sha256=9mUGXYrH7dN4XijN1R82SsMXeljOIjIMVzh8hm1aZ1s,5501
|
|
43
|
-
jarvis/jarvis_tools/git_commiter.py,sha256=
|
|
44
|
+
jarvis/jarvis_tools/git_commiter.py,sha256=LZ4rtyugvkt77HbW4_gSlAxMbMNJ3F-IJsx25k49uJo,5010
|
|
44
45
|
jarvis/jarvis_tools/lsp_find_definition.py,sha256=xV8YeN1RJfwd2F3gE6OnDeTwl-AnCmrxueHocbXkQOc,4800
|
|
45
46
|
jarvis/jarvis_tools/lsp_find_references.py,sha256=FohlJeLfTxcMUASfbjOT93hQGtI2WeyTpMGwRwShW_I,4043
|
|
46
47
|
jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=bEvbDk8TnKg9TTFFxMrYOJm5TBDgz5gO04WJFQUwQQE,4490
|
|
@@ -49,16 +50,16 @@ jarvis/jarvis_tools/lsp_prepare_rename.py,sha256=RxUyIef4awtp-jgupcD1LcPlno9P3mO
|
|
|
49
50
|
jarvis/jarvis_tools/lsp_validate_edit.py,sha256=M0iglK2QbnIEFv0RYK6o2iAYnv259jB6EU7To-rc51E,5247
|
|
50
51
|
jarvis/jarvis_tools/methodology.py,sha256=JvHV6rHhC6fbPuSqC6UHFaGEE39d4g7zFLodR72wM0g,5758
|
|
51
52
|
jarvis/jarvis_tools/rag.py,sha256=eY3GrzagaJIPQ8DmrqNUFFJnIF_GfUxqRjeSengEDss,4944
|
|
52
|
-
jarvis/jarvis_tools/read_code.py,sha256=
|
|
53
|
+
jarvis/jarvis_tools/read_code.py,sha256=e0iX9rpwUlSfrhnzgQPNvfqJ-ebxuJybrNaTgb3Hnyw,7290
|
|
53
54
|
jarvis/jarvis_tools/read_webpage.py,sha256=7QamwBi5s7lD-jTcjD0wsBvkmWPRC9-K-0JkGgeTpvs,3063
|
|
54
55
|
jarvis/jarvis_tools/registry.py,sha256=XefDvujSfqKX2uLA6tnoJFg5kyBNW0iNAAJZocfIz9w,14836
|
|
55
|
-
jarvis/jarvis_tools/search.py,sha256=
|
|
56
|
+
jarvis/jarvis_tools/search.py,sha256=UqXIUlpqy-0h3CrK23EfdqoXK0SjcthmA90OUGlIYYo,11399
|
|
56
57
|
jarvis/jarvis_tools/select_code_files.py,sha256=vbEdneWWtAN90OFASohtllTgZW400ZxQbrkgroPK1qc,1902
|
|
57
58
|
jarvis/jarvis_tools/tool_generator.py,sha256=jdniHyKcEyF9KyouudrCoZBH3czZmQXc3ns0_trZ3yU,6332
|
|
58
|
-
jarvis/jarvis_utils/__init__.py,sha256=
|
|
59
|
-
jarvis_ai_assistant-0.1.
|
|
60
|
-
jarvis_ai_assistant-0.1.
|
|
61
|
-
jarvis_ai_assistant-0.1.
|
|
62
|
-
jarvis_ai_assistant-0.1.
|
|
63
|
-
jarvis_ai_assistant-0.1.
|
|
64
|
-
jarvis_ai_assistant-0.1.
|
|
59
|
+
jarvis/jarvis_utils/__init__.py,sha256=K74tsMDZPieWX6HxOu1WHX9mJuQah4nOeuzq_j91ecg,33744
|
|
60
|
+
jarvis_ai_assistant-0.1.124.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
61
|
+
jarvis_ai_assistant-0.1.124.dist-info/METADATA,sha256=iDizLFV77rJQTHB56lhDR9Q5RePLuaeWs7zDGcI1pzA,13749
|
|
62
|
+
jarvis_ai_assistant-0.1.124.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
63
|
+
jarvis_ai_assistant-0.1.124.dist-info/entry_points.txt,sha256=H9Y_q7BZGDsgJijaXHD9GbscllATyKYfg22otrpKEoE,619
|
|
64
|
+
jarvis_ai_assistant-0.1.124.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
65
|
+
jarvis_ai_assistant-0.1.124.dist-info/RECORD,,
|