jarvis-ai-assistant 0.1.166__py3-none-any.whl → 0.1.167__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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +3 -2
- jarvis/jarvis_code_analysis/code_review.py +4 -4
- jarvis/jarvis_git_details/main.py +153 -65
- jarvis/jarvis_platform/base.py +14 -2
- jarvis/jarvis_platform/kimi.py +4 -0
- jarvis/jarvis_platform/yuanbao.py +4 -0
- jarvis/jarvis_smart_shell/main.py +12 -2
- jarvis/jarvis_tools/read_webpage.py +5 -0
- jarvis/jarvis_tools/search_web.py +6 -1
- jarvis/jarvis_utils/config.py +9 -0
- jarvis/jarvis_utils/git_utils.py +40 -1
- jarvis/jarvis_utils/utils.py +8 -0
- {jarvis_ai_assistant-0.1.166.dist-info → jarvis_ai_assistant-0.1.167.dist-info}/METADATA +7 -4
- {jarvis_ai_assistant-0.1.166.dist-info → jarvis_ai_assistant-0.1.167.dist-info}/RECORD +19 -19
- {jarvis_ai_assistant-0.1.166.dist-info → jarvis_ai_assistant-0.1.167.dist-info}/WHEEL +1 -1
- {jarvis_ai_assistant-0.1.166.dist-info/licenses → jarvis_ai_assistant-0.1.167.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.166.dist-info → jarvis_ai_assistant-0.1.167.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.166.dist-info → jarvis_ai_assistant-0.1.167.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_agent/__init__.py
CHANGED
|
@@ -332,7 +332,7 @@ class Agent:
|
|
|
332
332
|
action_handlers = '\n'.join([f'- {handler.name()}' for handler in self.output_handler])
|
|
333
333
|
|
|
334
334
|
# 任务完成提示
|
|
335
|
-
complete_prompt = f"
|
|
335
|
+
complete_prompt = f"3. 输出{ot('!!!COMPLETE!!!')}" if need_complete and self.auto_complete else ""
|
|
336
336
|
|
|
337
337
|
addon_prompt = f"""
|
|
338
338
|
<addon>
|
|
@@ -353,9 +353,10 @@ class Agent:
|
|
|
353
353
|
</actions>
|
|
354
354
|
|
|
355
355
|
<completion>
|
|
356
|
-
|
|
356
|
+
如果任务已完成,请:
|
|
357
357
|
1. 说明完成原因
|
|
358
358
|
2. 保持输出格式规范
|
|
359
|
+
{complete_prompt}
|
|
359
360
|
</completion>
|
|
360
361
|
</addon>
|
|
361
362
|
"""
|
|
@@ -8,7 +8,6 @@ import tempfile
|
|
|
8
8
|
from yaspin import yaspin
|
|
9
9
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
10
10
|
from jarvis.jarvis_tools.read_code import ReadCodeTool
|
|
11
|
-
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
12
11
|
from jarvis.jarvis_agent import Agent
|
|
13
12
|
|
|
14
13
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
@@ -488,7 +487,7 @@ class CodeReviewTool:
|
|
|
488
487
|
|
|
489
488
|
我将分析上传的代码差异文件,进行全面的代码审查。
|
|
490
489
|
</code_review_guide>"""
|
|
491
|
-
|
|
490
|
+
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
492
491
|
tool_registry = ToolRegistry()
|
|
493
492
|
tool_registry.dont_use_tools(["code_review"])
|
|
494
493
|
agent = Agent(
|
|
@@ -554,8 +553,9 @@ class CodeReviewTool:
|
|
|
554
553
|
如果检测到了特定编程语言,请参考语言特定的审查清单进行评估,并在报告中包含相关分析。
|
|
555
554
|
</notes>
|
|
556
555
|
|
|
556
|
+
输出格式:
|
|
557
557
|
{ot("REPORT")}
|
|
558
|
-
[
|
|
558
|
+
[在此处插入完整MARKDOWN格式的审查报告]
|
|
559
559
|
{ct("REPORT")}""",
|
|
560
560
|
output_handler=[tool_registry],
|
|
561
561
|
platform=PlatformRegistry().get_thinking_platform(),
|
|
@@ -654,7 +654,7 @@ def extract_code_report(result: str) -> str:
|
|
|
654
654
|
sm = re.search(ot("REPORT")+r'\n(.*?)\n'+ct("REPORT"), result, re.DOTALL)
|
|
655
655
|
if sm:
|
|
656
656
|
return sm.group(1)
|
|
657
|
-
return
|
|
657
|
+
return result
|
|
658
658
|
|
|
659
659
|
def main():
|
|
660
660
|
"""CLI entry point"""
|
|
@@ -31,41 +31,140 @@ class GitCommitAnalyzer:
|
|
|
31
31
|
"""执行commit分析
|
|
32
32
|
|
|
33
33
|
Args:
|
|
34
|
-
args: 包含commit_sha和root_dir的参数字典
|
|
34
|
+
args: 包含commit_sha/commit_range和root_dir的参数字典
|
|
35
|
+
commit_sha: 单个commit的SHA
|
|
36
|
+
commit_range: 两个commit的SHA范围,格式为"commit1..commit2"
|
|
37
|
+
root_dir: 代码库根目录
|
|
35
38
|
|
|
36
39
|
Returns:
|
|
37
|
-
|
|
38
|
-
- success: 操作是否成功
|
|
39
|
-
- stdout: 包含commit_info和diff_content的结果
|
|
40
|
-
- stderr: 错误信息(如果操作失败)
|
|
40
|
+
包含分析结果的字典
|
|
41
41
|
"""
|
|
42
42
|
try:
|
|
43
|
-
commit_sha = args
|
|
43
|
+
commit_sha = args.get("commit_sha")
|
|
44
|
+
commit_range = args.get("commit_range")
|
|
44
45
|
root_dir = args.get("root_dir", ".")
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
47
|
+
if commit_range:
|
|
48
|
+
return self.analyze_commit_range(commit_range, root_dir)
|
|
49
|
+
elif commit_sha:
|
|
50
|
+
return self.analyze_single_commit(commit_sha, root_dir)
|
|
51
|
+
else:
|
|
52
|
+
raise ValueError("Either commit_sha or commit_range must be provided")
|
|
53
|
+
except Exception as e:
|
|
54
|
+
return {
|
|
55
|
+
"success": False,
|
|
56
|
+
"stdout": {},
|
|
57
|
+
"stderr": f"Failed to analyze commit: {str(e)}"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
def analyze_single_commit(self, commit_sha: str, root_dir: str) -> Dict[str, Any]:
|
|
61
|
+
"""分析单个commit
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
commit_sha: commit的SHA
|
|
65
|
+
root_dir: 代码库根目录
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
包含分析结果的字典
|
|
69
|
+
"""
|
|
70
|
+
original_dir = os.getcwd()
|
|
71
|
+
try:
|
|
72
|
+
os.chdir(root_dir)
|
|
73
|
+
|
|
74
|
+
# 获取commit详细信息
|
|
75
|
+
commit_info = subprocess.check_output(
|
|
76
|
+
f"git show {commit_sha} --pretty=fuller",
|
|
77
|
+
shell=True,
|
|
78
|
+
text=True
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# 获取commit修改内容
|
|
82
|
+
diff_content = subprocess.check_output(
|
|
83
|
+
f"git show {commit_sha} --patch",
|
|
84
|
+
shell=True,
|
|
85
|
+
text=True
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# 分析commit的功能、原因和逻辑
|
|
89
|
+
analysis_result = self._analyze_diff_content(diff_content)
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
"success": True,
|
|
93
|
+
"stdout": {
|
|
94
|
+
"commit_info": commit_info,
|
|
95
|
+
"diff_content": diff_content,
|
|
96
|
+
"analysis_result": analysis_result
|
|
97
|
+
},
|
|
98
|
+
"stderr": ""
|
|
99
|
+
}
|
|
100
|
+
except subprocess.CalledProcessError as error:
|
|
101
|
+
return {
|
|
102
|
+
"success": False,
|
|
103
|
+
"stdout": {},
|
|
104
|
+
"stderr": f"Failed to analyze commit: {str(error)}"
|
|
105
|
+
}
|
|
106
|
+
finally:
|
|
107
|
+
os.chdir(original_dir)
|
|
108
|
+
|
|
109
|
+
def analyze_commit_range(self, commit_range: str, root_dir: str) -> Dict[str, Any]:
|
|
110
|
+
"""分析两个commit之间的代码变更
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
commit_range: 两个commit的SHA范围,格式为"commit1..commit2"
|
|
114
|
+
root_dir: 代码库根目录
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
包含分析结果的字典
|
|
118
|
+
"""
|
|
119
|
+
original_dir = os.getcwd()
|
|
120
|
+
try:
|
|
121
|
+
os.chdir(root_dir)
|
|
122
|
+
|
|
123
|
+
# 获取commit范围差异
|
|
124
|
+
diff_content = subprocess.check_output(
|
|
125
|
+
f"git diff {commit_range} --patch",
|
|
126
|
+
shell=True,
|
|
127
|
+
text=True
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# 获取commit范围信息
|
|
131
|
+
commit_info = subprocess.check_output(
|
|
132
|
+
f"git log {commit_range} --pretty=fuller",
|
|
133
|
+
shell=True,
|
|
134
|
+
text=True
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# 使用相同的分析方法处理差异内容
|
|
138
|
+
analysis_result = self._analyze_diff_content(diff_content)
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
"success": True,
|
|
142
|
+
"stdout": {
|
|
143
|
+
"commit_info": commit_info,
|
|
144
|
+
"diff_content": diff_content,
|
|
145
|
+
"analysis_result": analysis_result
|
|
146
|
+
},
|
|
147
|
+
"stderr": ""
|
|
148
|
+
}
|
|
149
|
+
except subprocess.CalledProcessError as error:
|
|
150
|
+
return {
|
|
151
|
+
"success": False,
|
|
152
|
+
"stdout": {},
|
|
153
|
+
"stderr": f"Failed to analyze commit range: {str(error)}"
|
|
154
|
+
}
|
|
155
|
+
finally:
|
|
156
|
+
os.chdir(original_dir)
|
|
157
|
+
|
|
158
|
+
def _analyze_diff_content(self, diff_content: str) -> str:
|
|
159
|
+
"""分析diff内容并生成报告
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
diff_content: git diff或git show的输出内容
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
分析结果字符串
|
|
166
|
+
"""
|
|
167
|
+
system_prompt = """你是一位资深代码分析专家,拥有多年代码审查和重构经验。你需要对Git commit进行深入分析,包括:
|
|
69
168
|
1. 修改的功能:明确说明本次commit实现或修改了哪些功能
|
|
70
169
|
2. 修改的原因:分析为什么要进行这些修改(如修复bug、优化性能、添加新功能等)
|
|
71
170
|
3. 修改的逻辑:详细说明代码修改的具体实现逻辑和思路
|
|
@@ -80,11 +179,11 @@ class GitCommitAnalyzer:
|
|
|
80
179
|
- 保持结构清晰,便于理解
|
|
81
180
|
- 重点关注关键修改和潜在风险"""
|
|
82
181
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
182
|
+
tool_registry = ToolRegistry()
|
|
183
|
+
agent = Agent(
|
|
184
|
+
system_prompt=system_prompt,
|
|
185
|
+
name="Commit Analysis Agent",
|
|
186
|
+
summary_prompt=f"""请生成一份详细的commit分析报告,包含以下内容:
|
|
88
187
|
{ot("REPORT")}
|
|
89
188
|
# 功能分析
|
|
90
189
|
[说明本次commit实现或修改了哪些功能]
|
|
@@ -107,31 +206,12 @@ class GitCommitAnalyzer:
|
|
|
107
206
|
# 最佳实践
|
|
108
207
|
[检查代码是否符合行业最佳实践和项目规范]
|
|
109
208
|
{ct("REPORT")}""",
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
"success": True,
|
|
119
|
-
"stdout": {
|
|
120
|
-
"commit_info": commit_info,
|
|
121
|
-
"diff_content": diff_content,
|
|
122
|
-
"analysis_result": analysis_result
|
|
123
|
-
},
|
|
124
|
-
"stderr": ""
|
|
125
|
-
}
|
|
126
|
-
finally:
|
|
127
|
-
# Always restore original directory
|
|
128
|
-
os.chdir(original_dir)
|
|
129
|
-
except subprocess.CalledProcessError as error:
|
|
130
|
-
return {
|
|
131
|
-
"success": False,
|
|
132
|
-
"stdout": {},
|
|
133
|
-
"stderr": f"Failed to analyze commit: {str(error)}"
|
|
134
|
-
}
|
|
209
|
+
output_handler=[tool_registry],
|
|
210
|
+
platform=PlatformRegistry().get_thinking_platform(),
|
|
211
|
+
auto_complete=True
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
return agent.run(diff_content)
|
|
135
215
|
|
|
136
216
|
|
|
137
217
|
def extract_analysis_report(result: str) -> str:
|
|
@@ -146,7 +226,7 @@ def extract_analysis_report(result: str) -> str:
|
|
|
146
226
|
search_match = re.search(ot("REPORT")+r'\n(.*?)\n'+ct("REPORT"), result, re.DOTALL)
|
|
147
227
|
if search_match:
|
|
148
228
|
return search_match.group(1)
|
|
149
|
-
return
|
|
229
|
+
return result
|
|
150
230
|
|
|
151
231
|
|
|
152
232
|
def main():
|
|
@@ -156,16 +236,24 @@ def main():
|
|
|
156
236
|
init_env()
|
|
157
237
|
|
|
158
238
|
parser = argparse.ArgumentParser(description='Git Commit Analyzer')
|
|
159
|
-
parser.
|
|
239
|
+
group = parser.add_mutually_exclusive_group(required=True)
|
|
240
|
+
group.add_argument('commit', nargs='?', help='Commit SHA to analyze')
|
|
241
|
+
group.add_argument('--range', type=str, help='Commit range to analyze (commit1..commit2)')
|
|
160
242
|
parser.add_argument('--root-dir', type=str, help='Root directory of the codebase', default=".")
|
|
161
243
|
|
|
162
244
|
args = parser.parse_args()
|
|
163
245
|
|
|
164
246
|
analyzer = GitCommitAnalyzer()
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
247
|
+
if args.range:
|
|
248
|
+
result = analyzer.execute({
|
|
249
|
+
"commit_range": args.range,
|
|
250
|
+
"root_dir": args.root_dir
|
|
251
|
+
})
|
|
252
|
+
else:
|
|
253
|
+
result = analyzer.execute({
|
|
254
|
+
"commit_sha": args.commit,
|
|
255
|
+
"root_dir": args.root_dir
|
|
256
|
+
})
|
|
169
257
|
|
|
170
258
|
if result["success"]:
|
|
171
259
|
PrettyOutput.section("Commit Information:", OutputType.SUCCESS)
|
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -40,13 +40,20 @@ class BasePlatform(ABC):
|
|
|
40
40
|
raise NotImplementedError("upload_files is not implemented")
|
|
41
41
|
|
|
42
42
|
def chat_big_content(self, content: str, prompt: str) -> str:
|
|
43
|
+
# 检查content大小不超过10MB
|
|
44
|
+
if len(content.encode('utf-8')) > 10 * 1024 * 1024:
|
|
45
|
+
return "Error: Content size exceeds 10MB limit"
|
|
46
|
+
|
|
43
47
|
prefix_prompt = f"""
|
|
44
48
|
我将分多次提供大量的上下文内容,在我明确告诉你内容已经全部提供完毕之前,每次仅需要输出“已收到”。
|
|
45
49
|
"""
|
|
46
50
|
self.chat_until_success(prefix_prompt)
|
|
47
|
-
split_content = split_text_into_chunks(content, get_max_input_token_count() - 1024)
|
|
51
|
+
split_content = split_text_into_chunks(content, get_max_input_token_count() - 1024, get_max_input_token_count() - 2048)
|
|
52
|
+
submit_count = 0
|
|
48
53
|
for chunk in split_content:
|
|
49
|
-
|
|
54
|
+
submit_count += 1
|
|
55
|
+
PrettyOutput.print(f"已提交{submit_count}次(总{len(split_content)}次)", OutputType.INFO)
|
|
56
|
+
self.chat_until_success(f"<part_content>{chunk}</part_content>请返回已收到")
|
|
50
57
|
return self.chat_until_success(f"内容已经全部提供完毕\n\n{prompt}")
|
|
51
58
|
|
|
52
59
|
|
|
@@ -109,3 +116,8 @@ class BasePlatform(ABC):
|
|
|
109
116
|
def set_web(self, web: bool):
|
|
110
117
|
"""Set web flag"""
|
|
111
118
|
self.web = web
|
|
119
|
+
|
|
120
|
+
@abstractmethod
|
|
121
|
+
def support_web(self) -> bool:
|
|
122
|
+
"""Check if platform supports web functionality"""
|
|
123
|
+
raise NotImplementedError("support_web is not implemented")
|
jarvis/jarvis_platform/kimi.py
CHANGED
|
@@ -17,6 +17,8 @@ def execute_command(command: str, should_run: bool) -> None:
|
|
|
17
17
|
os.system(command)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
|
|
21
|
+
|
|
20
22
|
def install_fish_completion() -> int:
|
|
21
23
|
"""Install fish shell command completion with interactive choice
|
|
22
24
|
|
|
@@ -110,7 +112,7 @@ def process_request(request: str) -> Optional[str]:
|
|
|
110
112
|
except Exception:
|
|
111
113
|
return None
|
|
112
114
|
|
|
113
|
-
def main():
|
|
115
|
+
def main() -> int:
|
|
114
116
|
# 创建参数解析器
|
|
115
117
|
init_env()
|
|
116
118
|
parser = argparse.ArgumentParser(
|
|
@@ -135,6 +137,12 @@ Example:
|
|
|
135
137
|
|
|
136
138
|
# install子命令
|
|
137
139
|
install_parser = subparsers.add_parser('install', help='安装fish shell的命令补全功能')
|
|
140
|
+
install_parser.add_argument(
|
|
141
|
+
"--shell",
|
|
142
|
+
choices=["fish"],
|
|
143
|
+
default="fish",
|
|
144
|
+
help="指定shell类型(仅支持fish)"
|
|
145
|
+
)
|
|
138
146
|
|
|
139
147
|
|
|
140
148
|
# 解析参数
|
|
@@ -144,9 +152,11 @@ Example:
|
|
|
144
152
|
|
|
145
153
|
# 处理install命令
|
|
146
154
|
if args.command == "install":
|
|
155
|
+
if args.shell != "fish":
|
|
156
|
+
print(f"错误: 不支持的shell类型: {args.shell}, 仅支持fish")
|
|
157
|
+
return 1
|
|
147
158
|
return install_fish_completion()
|
|
148
159
|
|
|
149
|
-
|
|
150
160
|
# 处理request命令
|
|
151
161
|
if not args.request:
|
|
152
162
|
# 检查是否在交互式终端中运行
|
|
@@ -23,4 +23,9 @@ class SearchWebTool:
|
|
|
23
23
|
"stdout": model.chat_until_success(query), # type: ignore
|
|
24
24
|
"stderr": "",
|
|
25
25
|
"success": True,
|
|
26
|
-
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def check() -> bool:
|
|
30
|
+
"""检查当前平台是否支持web功能"""
|
|
31
|
+
return PlatformRegistry().get_normal_platform().support_web()
|
jarvis/jarvis_utils/config.py
CHANGED
|
@@ -143,3 +143,12 @@ def get_data_dir() -> str:
|
|
|
143
143
|
if not data_path:
|
|
144
144
|
return os.path.expanduser('~/.jarvis')
|
|
145
145
|
return data_path
|
|
146
|
+
|
|
147
|
+
def get_auto_update() -> bool:
|
|
148
|
+
"""
|
|
149
|
+
获取是否自动更新git仓库。
|
|
150
|
+
|
|
151
|
+
返回:
|
|
152
|
+
bool: 如果需要自动更新则返回True,默认为True
|
|
153
|
+
"""
|
|
154
|
+
return os.getenv('JARVIS_AUTO_UPDATE', 'true') == 'true'
|
jarvis/jarvis_utils/git_utils.py
CHANGED
|
@@ -13,7 +13,7 @@ import os
|
|
|
13
13
|
import re
|
|
14
14
|
import subprocess
|
|
15
15
|
from typing import List, Tuple, Dict
|
|
16
|
-
from jarvis.jarvis_utils.config import is_confirm_before_apply_patch
|
|
16
|
+
from jarvis.jarvis_utils.config import get_auto_update, is_confirm_before_apply_patch
|
|
17
17
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
18
18
|
from jarvis.jarvis_utils.utils import user_confirm
|
|
19
19
|
def find_git_root(start_dir: str = ".") -> str:
|
|
@@ -294,3 +294,42 @@ def is_file_in_git_repo(filepath: str) -> bool:
|
|
|
294
294
|
return os.path.abspath(filepath).startswith(os.path.abspath(repo_root))
|
|
295
295
|
except:
|
|
296
296
|
return False
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def check_and_update_git_repo(repo_path: str) -> bool:
|
|
300
|
+
"""检查并更新git仓库
|
|
301
|
+
|
|
302
|
+
参数:
|
|
303
|
+
repo_path: 仓库路径
|
|
304
|
+
|
|
305
|
+
返回:
|
|
306
|
+
bool: 是否执行了更新
|
|
307
|
+
"""
|
|
308
|
+
curr_dir = os.path.abspath(os.getcwd())
|
|
309
|
+
git_root = find_git_root(repo_path)
|
|
310
|
+
if git_root is None:
|
|
311
|
+
return False
|
|
312
|
+
|
|
313
|
+
try:
|
|
314
|
+
if not get_auto_update():
|
|
315
|
+
return False
|
|
316
|
+
# 检查是否有未提交的修改
|
|
317
|
+
if has_uncommitted_changes():
|
|
318
|
+
return False
|
|
319
|
+
|
|
320
|
+
# 获取远程更新
|
|
321
|
+
subprocess.run(["git", "fetch"], cwd=git_root, check=True)
|
|
322
|
+
# 检查本地是否落后
|
|
323
|
+
result = subprocess.run(["git", "rev-list", "--count", "HEAD..origin/main"],
|
|
324
|
+
cwd=git_root, capture_output=True, text=True)
|
|
325
|
+
if result.returncode == 0 and int(result.stdout.strip()) > 0:
|
|
326
|
+
PrettyOutput.print("检测到新版本,正在更新Jarvis...", OutputType.INFO)
|
|
327
|
+
subprocess.run(["git", "pull"], cwd=git_root, check=True)
|
|
328
|
+
PrettyOutput.print("Jarvis已更新到最新版本", OutputType.SUCCESS)
|
|
329
|
+
return True
|
|
330
|
+
return False
|
|
331
|
+
except Exception as e:
|
|
332
|
+
PrettyOutput.print(f"Git仓库更新检查失败: {e}", OutputType.WARNING)
|
|
333
|
+
return False
|
|
334
|
+
finally:
|
|
335
|
+
os.chdir(curr_dir)
|
jarvis/jarvis_utils/utils.py
CHANGED
|
@@ -17,6 +17,7 @@ def init_env() -> None:
|
|
|
17
17
|
1. 创建不存在的jarvis_data目录
|
|
18
18
|
2. 加载环境变量到os.environ
|
|
19
19
|
3. 处理文件读取异常
|
|
20
|
+
4. 检查git仓库状态并在落后时更新
|
|
20
21
|
"""
|
|
21
22
|
jarvis_dir = Path(get_data_dir())
|
|
22
23
|
env_file = jarvis_dir / "env"
|
|
@@ -52,6 +53,13 @@ def init_env() -> None:
|
|
|
52
53
|
continue
|
|
53
54
|
except Exception as e:
|
|
54
55
|
PrettyOutput.print(f"警告: 读取 {env_file} 失败: {e}", OutputType.WARNING)
|
|
56
|
+
|
|
57
|
+
# 检查是否是git仓库并更新
|
|
58
|
+
from jarvis.jarvis_utils.git_utils import check_and_update_git_repo
|
|
59
|
+
|
|
60
|
+
check_and_update_git_repo(str(script_dir))
|
|
61
|
+
|
|
62
|
+
|
|
55
63
|
def while_success(func: Callable[[], Any], sleep_time: float = 0.1) -> Any:
|
|
56
64
|
"""循环执行函数直到成功
|
|
57
65
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.167
|
|
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
|
|
@@ -65,7 +65,6 @@ Requires-Dist: build; extra == "dev"
|
|
|
65
65
|
Requires-Dist: twine; extra == "dev"
|
|
66
66
|
Dynamic: author
|
|
67
67
|
Dynamic: home-page
|
|
68
|
-
Dynamic: license-file
|
|
69
68
|
Dynamic: requires-python
|
|
70
69
|
|
|
71
70
|
# 🤖 Jarvis AI 助手
|
|
@@ -167,7 +166,6 @@ JARVIS_THINKING_MODEL=gpt-4o
|
|
|
167
166
|
|
|
168
167
|
OPENAI_API_KEY=<OpenAI API Key>
|
|
169
168
|
OPENAI_API_BASE=https://api.openai.com/v1 # 可选,默认为官方API地址
|
|
170
|
-
OPENAI_MODEL_NAME=gpt-4o # 可选,覆盖JARVIS_MODEL设置
|
|
171
169
|
```
|
|
172
170
|
|
|
173
171
|
配置说明:
|
|
@@ -213,6 +211,9 @@ OPENAI_MODEL_NAME=gpt-4o # 可选,覆盖JARVIS_MODEL设置
|
|
|
213
211
|
| `JARVIS_EXECUTE_TOOL_CONFIRM` | false | 执行工具前是否需要确认 |
|
|
214
212
|
| `JARVIS_CONFIRM_BEFORE_APPLY_PATCH` | true | 应用补丁前是否需要确认 |
|
|
215
213
|
| `JARVIS_MAX_TOOL_CALL_COUNT` | 20 | 最大连续工具调用次数 |
|
|
214
|
+
| `JARVIS_AUTO_UPDATE` | true | 是否自动更新Jarvis(仅在以git仓库方式安装时有效) |
|
|
215
|
+
|
|
216
|
+
所有配置编写到`~/.jarvis/env`文件中即可生效。
|
|
216
217
|
|
|
217
218
|
|
|
218
219
|
---
|
|
@@ -409,3 +410,5 @@ class CustomPlatform(BasePlatform):
|
|
|
409
410
|
<div align="center">
|
|
410
411
|
由 Jarvis 团队用 ❤️ 制作
|
|
411
412
|
</div>
|
|
413
|
+
|
|
414
|
+

|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
2
|
-
jarvis/jarvis_agent/__init__.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=VoCqUtOk8zQixRfRJnQKEG0d7yF3JDV_1pUvP0_XpdY,74
|
|
2
|
+
jarvis/jarvis_agent/__init__.py,sha256=uCyjBD1ib9ewmJ1RJVy6QrVWOxy_4oNVFjvggqMRYg0,25712
|
|
3
3
|
jarvis/jarvis_agent/builtin_input_handler.py,sha256=KhvlV_QdB3P-M0TCkWvdxidNie1jU7KoMOqTIXCpwwA,1529
|
|
4
4
|
jarvis/jarvis_agent/file_input_handler.py,sha256=EwaitWczbwLCKNpWU9C7m829_G5uLZ_hNcVXlX2ANes,3437
|
|
5
5
|
jarvis/jarvis_agent/jarvis.py,sha256=rn0rLMGuVDyUa0_xdAmPV3M4yhIvE9ldSwD5DaJKo-8,5819
|
|
@@ -8,7 +8,7 @@ jarvis/jarvis_agent/output_handler.py,sha256=7qori-RGrQmdiFepoEe3oPPKJIvRt90l_JD
|
|
|
8
8
|
jarvis/jarvis_agent/shell_input_handler.py,sha256=pi3AtPKrkKc6K9e99S1djKXQ_XrxtP6FrSWebQmRT6E,1261
|
|
9
9
|
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
jarvis/jarvis_code_agent/code_agent.py,sha256=awCuRODHek434ixuG62PeAtFjQ7fQheJERJDpT4Bjuk,16859
|
|
11
|
-
jarvis/jarvis_code_analysis/code_review.py,sha256=
|
|
11
|
+
jarvis/jarvis_code_analysis/code_review.py,sha256=hVuKUfOKpgAyXG7pNKJG5SOcuGri8UcBza_W4fk34wY,30265
|
|
12
12
|
jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=cKQ_FOGy5TQgM-YkRCqORo-mUOZaPAJ9VDmZoFX58us,78
|
|
13
13
|
jarvis/jarvis_code_analysis/checklists/c_cpp.py,sha256=SXPpYCNeCtU1PpKdKPiYDuOybfY9vaL0ejDn4imxDwA,1317
|
|
14
14
|
jarvis/jarvis_code_analysis/checklists/csharp.py,sha256=vS-cu6RCGg5SyK9MJ3RE381gt3xYl-yea3Bj2UQEcwQ,2420
|
|
@@ -32,7 +32,7 @@ jarvis/jarvis_code_analysis/checklists/web.py,sha256=-Pnj1FQTsGVZUQK7-4ptDsGd7a2
|
|
|
32
32
|
jarvis/jarvis_data/huggingface.tar.gz,sha256=dWKnc_tvyx-I_ZkXo91O0b38KxDmLW1ZbmJ3E6fCl_k,1120205
|
|
33
33
|
jarvis/jarvis_dev/main.py,sha256=zfL9rl-Jfhpi4E4OxMKw3eOVjy6kSzQdxhn3yGv1UTw,42952
|
|
34
34
|
jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
jarvis/jarvis_git_details/main.py,sha256=
|
|
35
|
+
jarvis/jarvis_git_details/main.py,sha256=l4Ol96DFISq2ctAgzmfUuS4i6JdWh0JAu_isY3iuzVo,8919
|
|
36
36
|
jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
37
|
jarvis/jarvis_git_squash/main.py,sha256=uZf05Y7UN8kwlrfsSeX2NEGCaowwzZsm9LqjgmQxeic,2203
|
|
38
38
|
jarvis/jarvis_git_utils/git_commiter.py,sha256=0ABGCpZUcJIDFiCi0naQeJ1oySeQ2MDmyMzI96oXD58,13006
|
|
@@ -49,16 +49,16 @@ jarvis/jarvis_methodology/main.py,sha256=_KDGEQw6j_VZ9O8eDe-c8F84zl6JrKmsNRva9PG
|
|
|
49
49
|
jarvis/jarvis_multi_agent/__init__.py,sha256=LEJofDjh80U34RyZv2ECAzpt2zkhA0Jn3KZh-ABoAKA,4343
|
|
50
50
|
jarvis/jarvis_multi_agent/main.py,sha256=Z6N5VMjzaernnRjPkqgYRv09cIhWIFQ6a__AqHA8xrQ,1567
|
|
51
51
|
jarvis/jarvis_platform/__init__.py,sha256=0YnsUoM4JkIBOtImFdjfuDbrqQZT3dEaAwSJ62DrpCc,104
|
|
52
|
-
jarvis/jarvis_platform/base.py,sha256=
|
|
52
|
+
jarvis/jarvis_platform/base.py,sha256=Y5K0c6c6-74wFW38OWc7Boqtyfmf3sMZkR0S9rDSM8g,4588
|
|
53
53
|
jarvis/jarvis_platform/human.py,sha256=0sbEhST4rKKGGV45dAdJqvVBnRPPeCe6HqxR245S4Z8,2462
|
|
54
|
-
jarvis/jarvis_platform/kimi.py,sha256=
|
|
54
|
+
jarvis/jarvis_platform/kimi.py,sha256=yz7OVT54YDSUVuFlijDB7VdsJmtqRgj-qYKPHy8f0WQ,16787
|
|
55
55
|
jarvis/jarvis_platform/openai.py,sha256=8enxCISjHtCs0qoqEag68v68m_clKr7jgEpUA0CyUBo,4139
|
|
56
56
|
jarvis/jarvis_platform/registry.py,sha256=UjCdPT9WIRxU-F0uuPpKmKRRCcNNxjr-bRTEPgRSNx4,7740
|
|
57
|
-
jarvis/jarvis_platform/yuanbao.py,sha256=
|
|
57
|
+
jarvis/jarvis_platform/yuanbao.py,sha256=gPFy03DA0PemBNQTtxbDCBJ6mqUtSZclfiZbdNq1Ivk,22036
|
|
58
58
|
jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
59
|
jarvis/jarvis_platform_manager/main.py,sha256=gFqXKNweU9mE-IRqV7qhXmZ5483D01s9bI76POX1uXc,22596
|
|
60
60
|
jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
61
|
-
jarvis/jarvis_smart_shell/main.py,sha256=
|
|
61
|
+
jarvis/jarvis_smart_shell/main.py,sha256=uq5NCdNAdcHqvtG0zpajz85SigSKH1SSAcEpyHa_BOc,5180
|
|
62
62
|
jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
63
63
|
jarvis/jarvis_tools/ask_codebase.py,sha256=kIQwlSrCqtjXyl3YE8m6i188U62sZ78LAOz06Vsm-2k,9659
|
|
64
64
|
jarvis/jarvis_tools/ask_user.py,sha256=cWSLG33b79IbIZEWsSNV5RHvGX6eo3nTM8TUhOMnGh8,2167
|
|
@@ -76,26 +76,26 @@ jarvis/jarvis_tools/generate_new_tool.py,sha256=On4dXSmZZ_rVkNaZ151QE_3OWXXqtjs0
|
|
|
76
76
|
jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=paz1CVZ2Y8nk0U74n1QiG01oDINiZqpVlPc2f4_B150,5346
|
|
77
77
|
jarvis/jarvis_tools/methodology.py,sha256=Md8W2et0xUiuTjUSRCdnlwEPYqah2dCAAkxW_95BXBY,5238
|
|
78
78
|
jarvis/jarvis_tools/read_code.py,sha256=pgztSBRh8RORFalqwzzsLHQogooFvDm1ePBL0E5O1C4,5961
|
|
79
|
-
jarvis/jarvis_tools/read_webpage.py,sha256=
|
|
79
|
+
jarvis/jarvis_tools/read_webpage.py,sha256=LLvAOvaQJodaeNJKQ6dU9MYEE227NMdHyLs7esluUQ4,2217
|
|
80
80
|
jarvis/jarvis_tools/registry.py,sha256=rRdvLzsAkMPfRFZz9GfTP9K8mGedoDt8Pj9drRI_yL8,27133
|
|
81
81
|
jarvis/jarvis_tools/rewrite_file.py,sha256=rEPPSNU7uF1iKfEW9npEpZJ2LSoQXjt2OC-_troBToE,7003
|
|
82
|
-
jarvis/jarvis_tools/search_web.py,sha256
|
|
82
|
+
jarvis/jarvis_tools/search_web.py,sha256=-h1WYOqTcYC_8fdkm-4RfwKpbtLTVxOfRROul51NgO0,951
|
|
83
83
|
jarvis/jarvis_tools/virtual_tty.py,sha256=AKAaKY5KcPxifNQoXjzHaL4U6EUVA7irHLwVvz2wLVs,16396
|
|
84
84
|
jarvis/jarvis_utils/__init__.py,sha256=l-fsyQ-KzyqAhrJYur8eZAqsgaifGzSm24R2qtRGJ0g,849
|
|
85
85
|
jarvis/jarvis_utils/builtin_replace_map.py,sha256=A-cJ8deht2vDl2iKRhoZ7qECyJ6sboVH5Zx-L9vIBUs,4314
|
|
86
|
-
jarvis/jarvis_utils/config.py,sha256=
|
|
86
|
+
jarvis/jarvis_utils/config.py,sha256=T7-RIPIZx6qehTFuu8AFZA-SVTDpsYUCopJ6KYZ8RAQ,4315
|
|
87
87
|
jarvis/jarvis_utils/embedding.py,sha256=05KvmZvtI2-7xxmj13kAknRezWuVeold-D68wyPvZSA,7015
|
|
88
88
|
jarvis/jarvis_utils/file_processors.py,sha256=tSZSMJ4qCJ_lXI0dyLgJ0j5qEh6CDXDSVI7vQiFmcuQ,2976
|
|
89
|
-
jarvis/jarvis_utils/git_utils.py,sha256=
|
|
89
|
+
jarvis/jarvis_utils/git_utils.py,sha256=MxhUcQ_gFUFyBxBiorEJ1wUk9a2TerFdq3-Z11FB-AE,11324
|
|
90
90
|
jarvis/jarvis_utils/globals.py,sha256=Zs0chxA_giYiolYvawFFpcnTWgCUnn6GEusAh42jbz8,2275
|
|
91
91
|
jarvis/jarvis_utils/input.py,sha256=qGf2q-yWhgT-OX-j_WYi7aZ11jYmuFNiMz2_W1nUOiM,7432
|
|
92
92
|
jarvis/jarvis_utils/methodology.py,sha256=d25o61UtnuwgIQBgnajxx9zPsxsVzv4Ptb9BGwC93Nk,8156
|
|
93
93
|
jarvis/jarvis_utils/output.py,sha256=PVG4fQ3P-eGOZUNZTowPtnjqq3GN91OE8fHa68lFOOg,8440
|
|
94
94
|
jarvis/jarvis_utils/tag.py,sha256=YJHmuedLb7_AiqvKQetHr4R1FxyzIh7HN0RRkWMmYbU,429
|
|
95
|
-
jarvis/jarvis_utils/utils.py,sha256=
|
|
96
|
-
jarvis_ai_assistant-0.1.
|
|
97
|
-
jarvis_ai_assistant-0.1.
|
|
98
|
-
jarvis_ai_assistant-0.1.
|
|
99
|
-
jarvis_ai_assistant-0.1.
|
|
100
|
-
jarvis_ai_assistant-0.1.
|
|
101
|
-
jarvis_ai_assistant-0.1.
|
|
95
|
+
jarvis/jarvis_utils/utils.py,sha256=R3SS4v35HwgZxvQmCKrdUWdu4AeceRZ1gEHH8KK6ST8,5471
|
|
96
|
+
jarvis_ai_assistant-0.1.167.dist-info/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
97
|
+
jarvis_ai_assistant-0.1.167.dist-info/METADATA,sha256=AHbi3nL5geVT43ECivtOUMao921-InbKknih9aBBoWU,14455
|
|
98
|
+
jarvis_ai_assistant-0.1.167.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
99
|
+
jarvis_ai_assistant-0.1.167.dist-info/entry_points.txt,sha256=cKz_9SEpOvElTubKPMZMAdskD4GHz-NyKWRNssIVAWE,973
|
|
100
|
+
jarvis_ai_assistant-0.1.167.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
101
|
+
jarvis_ai_assistant-0.1.167.dist-info/RECORD,,
|
{jarvis_ai_assistant-0.1.166.dist-info/licenses → jarvis_ai_assistant-0.1.167.dist-info}/LICENSE
RENAMED
|
File without changes
|
{jarvis_ai_assistant-0.1.166.dist-info → jarvis_ai_assistant-0.1.167.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{jarvis_ai_assistant-0.1.166.dist-info → jarvis_ai_assistant-0.1.167.dist-info}/top_level.txt
RENAMED
|
File without changes
|