jarvis-ai-assistant 0.1.165__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.1.165"
4
+ __version__ = "0.1.167"
@@ -310,6 +310,17 @@ class Agent:
310
310
  """
311
311
  self.after_tool_call_cb = cb
312
312
 
313
+ def get_tool_registry(self) -> Optional[ToolRegistry]:
314
+ """获取工具注册器。
315
+
316
+ 返回:
317
+ ToolRegistry: 工具注册器实例
318
+ """
319
+ for handler in self.output_handler:
320
+ if isinstance(handler, ToolRegistry):
321
+ return handler
322
+ return None
323
+
313
324
  def make_default_addon_prompt(self, need_complete: bool) -> str:
314
325
  """生成附加提示。
315
326
 
@@ -321,7 +332,7 @@ class Agent:
321
332
  action_handlers = '\n'.join([f'- {handler.name()}' for handler in self.output_handler])
322
333
 
323
334
  # 任务完成提示
324
- complete_prompt = f"并输出{ot('!!!COMPLETE!!!')}" if need_complete and self.auto_complete else ""
335
+ complete_prompt = f"3. 输出{ot('!!!COMPLETE!!!')}" if need_complete and self.auto_complete else ""
325
336
 
326
337
  addon_prompt = f"""
327
338
  <addon>
@@ -342,9 +353,10 @@ class Agent:
342
353
  </actions>
343
354
 
344
355
  <completion>
345
- 如果任务已完成{complete_prompt},请:
356
+ 如果任务已完成,请:
346
357
  1. 说明完成原因
347
358
  2. 保持输出格式规范
359
+ {complete_prompt}
348
360
  </completion>
349
361
  </addon>
350
362
  """
@@ -658,7 +670,7 @@ arguments:
658
670
  msg = user_input
659
671
  for handler in self.input_handler:
660
672
  msg, _ = handler(msg, self)
661
- self.prompt = f"{user_input}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg)}"
673
+ self.prompt = f"{user_input}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
662
674
  self.first = False
663
675
 
664
676
  while True:
@@ -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["commit_sha"]
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
- # Store current directory
47
- original_dir = os.getcwd()
48
-
49
- try:
50
- # Change to root_dir
51
- os.chdir(root_dir)
52
-
53
- # 获取commit详细信息
54
- commit_info = subprocess.check_output(
55
- f"git show {commit_sha} --pretty=fuller",
56
- shell=True,
57
- text=True
58
- )
59
-
60
- # 获取commit修改内容
61
- diff_content = subprocess.check_output(
62
- f"git show {commit_sha} --patch",
63
- shell=True,
64
- text=True
65
- )
66
-
67
- # 分析commit的功能、原因和逻辑
68
- system_prompt = """你是一位资深代码分析专家,拥有多年代码审查和重构经验。你需要对Git commit进行深入分析,包括:
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
- tool_registry = ToolRegistry()
84
- agent = Agent(
85
- system_prompt=system_prompt,
86
- name="Commit Analysis Agent",
87
- summary_prompt=f"""请生成一份详细的commit分析报告,包含以下内容:
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
- output_handler=[tool_registry],
111
- platform=PlatformRegistry().get_thinking_platform(),
112
- auto_complete=True
113
- )
114
-
115
- analysis_result = agent.run(diff_content)
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.add_argument('commit', help='Commit SHA to analyze')
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
- result = analyzer.execute({
166
- "commit_sha": args.commit,
167
- "root_dir": args.root_dir
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)
@@ -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
- self.chat_until_success(f"<part_content>{chunk}</part_content>")
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")
@@ -413,3 +413,7 @@ class KimiModel(BasePlatform):
413
413
  def name(self) -> str:
414
414
  """Model name"""
415
415
  return "kimi"
416
+
417
+ def support_web(self) -> bool:
418
+ """Kimi平台支持web功能"""
419
+ return True
@@ -213,6 +213,7 @@ class YuanbaoPlatform(BasePlatform):
213
213
  uploaded_files.append(file_metadata)
214
214
  spinner.text = f"文件 {file_name} 上传成功"
215
215
  spinner.ok("✅")
216
+ time.sleep(3) # 上传成功后等待3秒
216
217
 
217
218
  except Exception as e:
218
219
  spinner.text = f"上传文件 {file_path} 时出错: {str(e)}"
@@ -533,3 +534,7 @@ class YuanbaoPlatform(BasePlatform):
533
534
  def name(self) -> str:
534
535
  """模型名称"""
535
536
  return self.model_name
537
+
538
+ def support_web(self) -> bool:
539
+ """Yuanbao平台支持web功能"""
540
+ return True
@@ -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
  # 检查是否在交互式终端中运行
@@ -141,7 +141,7 @@ class FileSearchReplaceTool:
141
141
  content = f.read()
142
142
  original_content = content
143
143
 
144
- success, temp_content = slow_edit(file_path, yaml.safe_dump(changes))
144
+ success, temp_content = patch_apply(file_path, yaml.safe_dump(changes))
145
145
 
146
146
  # 只有当所有替换操作都成功时,才写回文件
147
147
  if success and (temp_content != original_content or not file_exists):
@@ -208,7 +208,7 @@ class FileSearchReplaceTool:
208
208
  }
209
209
 
210
210
 
211
- def slow_edit(filepath: str, patch_content: str) -> Tuple[bool, str]:
211
+ def patch_apply(filepath: str, patch_content: str) -> Tuple[bool, str]:
212
212
  """执行精确的文件编辑操作,使用AI模型生成差异补丁并应用。
213
213
 
214
214
  功能概述:
@@ -35,10 +35,14 @@ class FindMethodologyTool:
35
35
  "stdout": "",
36
36
  "stderr": "参数中必须包含查询文本"
37
37
  }
38
+
39
+ agent = args.get("agent", None)
40
+
41
+ tool_registry = agent.get_tool_registry() if agent else None
38
42
 
39
43
  with yaspin(text="搜索相关方法论...", color="cyan") as spinner:
40
44
  with spinner.hidden():
41
- methodology_prompt = load_methodology(args["query"])
45
+ methodology_prompt = load_methodology(args["query"], tool_registry)
42
46
 
43
47
  if methodology_prompt:
44
48
  spinner.text = "找到相关方法论"
@@ -0,0 +1,288 @@
1
+ # -*- coding: utf-8 -*-
2
+ import re
3
+ from pathlib import Path
4
+ from typing import Dict, Any, Tuple
5
+
6
+ from jarvis.jarvis_utils.config import get_data_dir
7
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
+
9
+ class generate_new_tool:
10
+ name = "generate_new_tool"
11
+ description = """
12
+ 生成并注册新的Jarvis工具。该工具会在用户数据目录下创建新的工具文件,
13
+ 并自动注册到当前的工具注册表中。适用场景:1. 需要创建新的自定义工具;
14
+ 2. 扩展Jarvis功能;3. 自动化重复性操作;4. 封装特定领域的功能。
15
+
16
+ 使用示例:
17
+
18
+ ```
19
+ # 创建一个将文本转换为大写/小写的工具
20
+ name: generate_new_tool
21
+ arguments:
22
+ tool_name: text_transformer
23
+ tool_code: |
24
+ # -*- coding: utf-8 -*-
25
+ from typing import Dict, Any
26
+
27
+ class text_transformer:
28
+ name = "text_transformer"
29
+ description = \"\"\"
30
+ 文本转换工具,可以将输入的文本转换为大写、小写或首字母大写格式。
31
+ 适用场景:1. 格式化文本; 2. 处理标题; 3. 标准化输出
32
+ \"\"\"
33
+
34
+ parameters = {
35
+ "type": "object",
36
+ "properties": {
37
+ "text": {
38
+ "type": "string",
39
+ "description": "需要转换格式的文本"
40
+ },
41
+ "transform_type": {
42
+ "type": "string",
43
+ "description": "转换类型,可选值为 upper(大写)、lower(小写)或 title(首字母大写)",
44
+ "enum": ["upper", "lower", "title"]
45
+ }
46
+ },
47
+ "required": ["text", "transform_type"]
48
+ }
49
+
50
+ @staticmethod
51
+ def check() -> bool:
52
+ return True
53
+
54
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
55
+ try:
56
+ text = args["text"]
57
+ transform_type = args["transform_type"]
58
+
59
+ if transform_type == "upper":
60
+ result = text.upper()
61
+ elif transform_type == "lower":
62
+ result = text.lower()
63
+ elif transform_type == "title":
64
+ result = text.title()
65
+ else:
66
+ return {
67
+ "success": False,
68
+ "stdout": "",
69
+ "stderr": f"不支持的转换类型: {transform_type}"
70
+ }
71
+
72
+ return {
73
+ "success": True,
74
+ "stdout": result,
75
+ "stderr": ""
76
+ }
77
+
78
+ except Exception as e:
79
+ return {
80
+ "success": False,
81
+ "stdout": "",
82
+ "stderr": f"转换失败: {str(e)}"
83
+ }
84
+ ```
85
+
86
+ 创建完成后可以立即使用:
87
+
88
+ ```
89
+ name: text_transformer
90
+ arguments:
91
+ text: hello world
92
+ transform_type: upper
93
+ ```
94
+ """
95
+
96
+ parameters = {
97
+ "type": "object",
98
+ "properties": {
99
+ "tool_name": {
100
+ "type": "string",
101
+ "description": "新工具的名称,将用作文件名和工具类名"
102
+ },
103
+ "tool_code": {
104
+ "type": "string",
105
+ "description": "工具的完整Python代码,包含类定义、名称、描述、参数和execute方法"
106
+ }
107
+ },
108
+ "required": ["tool_name", "tool_code"]
109
+ }
110
+
111
+ @staticmethod
112
+ def check() -> bool:
113
+ """检查工具是否可用"""
114
+ # 检查数据目录是否存在
115
+ data_dir = get_data_dir()
116
+ tools_dir = Path(data_dir) / "tools"
117
+
118
+ # 如果tools目录不存在,尝试创建
119
+ if not tools_dir.exists():
120
+ try:
121
+ tools_dir.mkdir(parents=True, exist_ok=True)
122
+ return True
123
+ except Exception as e:
124
+ PrettyOutput.print(f"无法创建工具目录 {tools_dir}: {e}", OutputType.ERROR)
125
+ return False
126
+
127
+ return True
128
+
129
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
130
+ """
131
+ 生成新工具并注册到当前的工具注册表中
132
+
133
+ 参数:
134
+ args: 包含工具名称和工具代码的字典
135
+
136
+ 返回:
137
+ Dict: 包含生成结果的字典
138
+ """
139
+ try:
140
+ # 从参数中获取工具信息
141
+ tool_name = args["tool_name"]
142
+ tool_code = args["tool_code"]
143
+ agent = args.get("agent", None)
144
+
145
+ # 验证工具名称
146
+ if not tool_name.isidentifier():
147
+ return {
148
+ "success": False,
149
+ "stdout": "",
150
+ "stderr": f"工具名称 '{tool_name}' 不是有效的Python标识符"
151
+ }
152
+
153
+ # 准备工具目录
154
+ tools_dir = Path(get_data_dir()) / "tools"
155
+ tools_dir.mkdir(parents=True, exist_ok=True)
156
+
157
+ # 生成工具文件路径
158
+ tool_file_path = tools_dir / f"{tool_name}.py"
159
+
160
+ # 检查是否已存在同名工具
161
+ if tool_file_path.exists():
162
+ return {
163
+ "success": False,
164
+ "stdout": "",
165
+ "stderr": f"工具 '{tool_name}' 已经存在于 {tool_file_path}"
166
+ }
167
+
168
+ # 验证并处理工具代码
169
+ processed_code, error_msg = self._validate_and_process_code(tool_name, tool_code)
170
+ if error_msg:
171
+ return {
172
+ "success": False,
173
+ "stdout": "",
174
+ "stderr": error_msg
175
+ }
176
+
177
+ # 写入工具文件
178
+ with open(tool_file_path, "w", encoding="utf-8") as f:
179
+ f.write(processed_code)
180
+
181
+ # 注册新工具到当前的工具注册表
182
+ success_message = f"工具 '{tool_name}' 已成功生成在 {tool_file_path}"
183
+
184
+ if agent:
185
+ tool_registry = agent.get_tool_registry()
186
+ if tool_registry:
187
+ # 尝试加载并注册新工具
188
+ if tool_registry.register_tool_by_file(str(tool_file_path)):
189
+ success_message += f"\n已成功注册到当前会话的工具注册表中"
190
+ else:
191
+ success_message += f"\n注册到当前会话失败,可能需要重新启动Jarvis"
192
+
193
+ return {
194
+ "success": True,
195
+ "stdout": success_message,
196
+ "stderr": ""
197
+ }
198
+
199
+ except Exception as e:
200
+ # 如果发生异常,返回失败响应,包含错误信息
201
+ return {
202
+ "success": False,
203
+ "stdout": "",
204
+ "stderr": f"生成工具失败: {str(e)}"
205
+ }
206
+
207
+ def _validate_and_process_code(self, tool_name: str, tool_code: str) -> Tuple[str, str]:
208
+ """
209
+ 验证并处理工具代码
210
+
211
+ 参数:
212
+ tool_name: 工具名称
213
+ tool_code: 工具代码
214
+
215
+ 返回:
216
+ Tuple[str, str]: (处理后的代码, 错误信息)
217
+ """
218
+ # 检查工具代码中是否包含类定义
219
+ if f"class {tool_name}" not in tool_code:
220
+ # 尝试找到任何类定义
221
+ class_match = re.search(r"class\s+(\w+)", tool_code)
222
+ if class_match:
223
+ old_class_name = class_match.group(1)
224
+ # 替换类名为工具名
225
+ tool_code = tool_code.replace(f"class {old_class_name}", f"class {tool_name}")
226
+ tool_code = tool_code.replace(f'name = "{old_class_name}"', f'name = "{tool_name}"')
227
+ else:
228
+ # 没有找到类定义,返回错误
229
+ return "", f"工具代码中缺少类定义 'class {tool_name}'"
230
+
231
+ # 检查工具代码中是否包含必要的属性和方法
232
+ missing_components = []
233
+
234
+ if f'name = "{tool_name}"' not in tool_code and f"name = '{tool_name}'" not in tool_code:
235
+ # 尝试查找任何name属性并修复
236
+ name_match = re.search(r'name\s*=\s*["\'](\w+)["\']', tool_code)
237
+ if name_match:
238
+ old_name = name_match.group(1)
239
+ tool_code = re.sub(r'name\s*=\s*["\'](\w+)["\']', f'name = "{tool_name}"', tool_code)
240
+ else:
241
+ missing_components.append(f"name = \"{tool_name}\"")
242
+
243
+ if "description = " not in tool_code:
244
+ missing_components.append("description 属性")
245
+
246
+ if "parameters = " not in tool_code:
247
+ missing_components.append("parameters 属性")
248
+
249
+ if "def execute(self, args:" not in tool_code:
250
+ missing_components.append("execute 方法")
251
+
252
+ if "def check(" not in tool_code:
253
+ # 添加默认的check方法
254
+ class_match = re.search(r"class\s+(\w+).*?:", tool_code, re.DOTALL)
255
+ if class_match:
256
+ indent = " " # 默认缩进
257
+ # 找到类定义后的第一个属性
258
+ first_attr_match = re.search(r"class\s+(\w+).*?:(.*?)(\w+\s*=)", tool_code, re.DOTALL)
259
+ if first_attr_match:
260
+ # 获取属性前的缩进
261
+ attr_indent = re.search(r"\n([ \t]*)\w+\s*=", first_attr_match.group(2))
262
+ if attr_indent:
263
+ indent = attr_indent.group(1)
264
+
265
+ check_method = f"\n{indent}@staticmethod\n{indent}def check() -> bool:\n{indent} \"\"\"检查工具是否可用\"\"\"\n{indent} return True\n"
266
+
267
+ # 在类定义后插入check方法
268
+ pattern = r"(class\s+(\w+).*?:.*?)(\n\s*\w+\s*=|\n\s*@|\n\s*def)"
269
+ replacement = r"\1" + check_method + r"\3"
270
+ tool_code = re.sub(pattern, replacement, tool_code, 1, re.DOTALL)
271
+
272
+ # 如果缺少必要组件,返回错误信息
273
+ if missing_components:
274
+ return "", f"工具代码中缺少以下必要组件: {', '.join(missing_components)}"
275
+
276
+ # 确保代码有正确的Python文件头部
277
+ if not tool_code.startswith("# -*- coding:") and not tool_code.startswith("# coding="):
278
+ tool_code = "# -*- coding: utf-8 -*-\n" + tool_code
279
+
280
+ # 确保导入了必要的模块
281
+ if "from typing import Dict, Any" not in tool_code:
282
+ imports_pos = tool_code.find("\n\n")
283
+ if imports_pos > 0:
284
+ tool_code = tool_code[:imports_pos] + "\nfrom typing import Dict, Any" + tool_code[imports_pos:]
285
+ else:
286
+ tool_code = "from typing import Dict, Any\n\n" + tool_code
287
+
288
+ return tool_code, ""
@@ -59,3 +59,8 @@ class WebpageTool:
59
59
  "stdout": "",
60
60
  "stderr": f"Failed to parse webpage: {str(e)}"
61
61
  }
62
+
63
+ @staticmethod
64
+ def check() -> bool:
65
+ """检查当前平台是否支持web功能"""
66
+ return PlatformRegistry().get_normal_platform().support_web()
@@ -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()
@@ -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'
@@ -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)
@@ -10,7 +10,7 @@
10
10
  import os
11
11
  import json
12
12
  import tempfile
13
- from typing import Dict, Optional
13
+ from typing import Any, Dict, Optional
14
14
 
15
15
  from jarvis.jarvis_utils.config import get_data_dir
16
16
  from jarvis.jarvis_utils.output import PrettyOutput, OutputType
@@ -92,7 +92,7 @@ def _create_methodology_temp_file(methodologies: Dict[str, str]) -> Optional[str
92
92
  PrettyOutput.print(f"创建方法论临时文件失败: {str(e)}", OutputType.ERROR)
93
93
  return None
94
94
 
95
- def load_methodology(user_input: str) -> str:
95
+ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> str:
96
96
  """
97
97
  加载方法论并上传到大模型。
98
98
 
@@ -103,6 +103,9 @@ def load_methodology(user_input: str) -> str:
103
103
  str: 相关的方法论提示,如果未找到方法论则返回空字符串
104
104
  """
105
105
  from yaspin import yaspin # type: ignore
106
+ from jarvis.jarvis_tools.registry import ToolRegistry
107
+
108
+ prompt = tool_registery.prompt() if tool_registery else ""
106
109
 
107
110
  # 获取方法论目录
108
111
  methodology_dir = _get_methodology_directory()
@@ -133,10 +136,13 @@ def load_methodology(user_input: str) -> str:
133
136
  full_content = base_prompt
134
137
  for problem_type, content in methodologies.items():
135
138
  full_content += f"## {problem_type}\n\n{content}\n\n---\n\n"
139
+
140
+ full_content += f"以下是所有可用的工具内容:\n\n"
141
+ full_content += prompt
136
142
 
137
143
  # 添加用户输入和输出要求
138
144
  full_content += f"""
139
- 请根据以上方法论内容,规划/总结出以下用户需求的执行步骤: {user_input}
145
+ 请根据以上方法论和可调用的工具内容,规划/总结出以下用户需求的执行步骤: {user_input}
140
146
 
141
147
  请按以下格式回复:
142
148
  ### 与该任务/需求相关的方法论
@@ -175,7 +181,7 @@ def load_methodology(user_input: str) -> str:
175
181
  if upload_success:
176
182
  # 使用上传的文件生成摘要
177
183
  return platform.chat_until_success(base_prompt + f"""
178
- 请根据已上传的方法论文件内容,规划/总结出以下用户需求的执行步骤: {user_input}
184
+ 请根据已上传的方法论和可调用的工具文件内容,规划/总结出以下用户需求的执行步骤: {user_input}
179
185
 
180
186
  请按以下格式回复:
181
187
  ### 与该任务/需求相关的方法论
@@ -192,7 +198,7 @@ def load_methodology(user_input: str) -> str:
192
198
  elif hasattr(platform, 'chat_big_content'):
193
199
  # 如果上传失败但支持大内容处理,使用chat_big_content
194
200
  return platform.chat_big_content(full_content, base_prompt + f"""
195
- 请根据以上方法论内容,规划/总结出以下用户需求的执行步骤: {user_input}
201
+ 请根据以上方法论和可调用的工具文件内容,规划/总结出以下用户需求的执行步骤: {user_input}
196
202
 
197
203
  请按以下格式回复:
198
204
  ### 与该任务/需求相关的方法论
@@ -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
 
@@ -66,7 +74,7 @@ def while_success(func: Callable[[], Any], sleep_time: float = 0.1) -> Any:
66
74
  try:
67
75
  return func()
68
76
  except Exception as e:
69
- PrettyOutput.print(f"执行失败: {str(e)}, 等待 {sleep_time}s...", OutputType.ERROR)
77
+ PrettyOutput.print(f"执行失败: {str(e)}, 等待 {sleep_time}s...", OutputType.WARNING)
70
78
  time.sleep(sleep_time)
71
79
  continue
72
80
  def while_true(func: Callable[[], bool], sleep_time: float = 0.1) -> Any:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.2
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.165
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 助手
@@ -106,11 +105,19 @@ Dynamic: requires-python
106
105
 
107
106
 
108
107
  ## 🚀 快速开始 <a id="quick-start"></a>
108
+ ### 系统要求
109
+ - 目前只能在Linux系统下使用(很多工具依赖Linux系统)
110
+ - Windows没有测试过,但Windows 10以上的用户可以在WSL上使用此工具
111
+
109
112
  ### 安装
110
113
  ```bash
114
+ # 从源码安装(推荐)
111
115
  git clone https://github.com/skyfireitdiy/Jarvis
112
116
  cd Jarvis
113
117
  pip3 install -e .
118
+
119
+ # 或者从PyPI安装(可能更新不及时)
120
+ pip3 install jarvis-ai-assistant
114
121
  ```
115
122
 
116
123
  ### 最小化配置
@@ -149,55 +156,43 @@ Kimi API Key获取方式:
149
156
 
150
157
  删除Bearer前缀,剩下的内容就是Kimi API Key。
151
158
 
152
- 以上配置编写到`~/.jarvis/env`文件中。
153
159
 
154
- ### 基本使用
160
+ #### OpenAI
155
161
  ```bash
156
- # 使用通用代理
157
- jarvis
158
-
159
- # 使用代码代理
160
- jarvis-code-agent
161
- # 或者 jca
162
-
163
- # 使用智能shell的功能
164
- jarvis-smart-shell --help
165
- # 或者 jss
166
-
167
- # 使用平台管理的功能
168
- jarvis-platform-manager --help
169
-
170
- # 使用代码审查的功能
171
- jarvis-code-review --help
172
-
173
- # 使用自动化git commit的功能
174
- jarvis-git-commit --help
175
- # 或者 jgc
162
+ JARVIS_PLATFORM=openai
163
+ JARVIS_MODEL=gpt-4o # 默认模型,可选gpt-4-turbo, gpt-3.5-turbo等
164
+ JARVIS_THINKING_PLATFORM=openai
165
+ JARVIS_THINKING_MODEL=gpt-4o
176
166
 
177
- # 使用dev功能(开发中)
178
- jarvis-dev --help
179
-
180
- # 使用git squash的功能
181
- jarvis-git-squash --help
182
-
183
- # 使用多代理的功能
184
- jarvis-multi-agent --help
185
-
186
- # 使用agent的功能
187
- jarvis-agent --help
167
+ OPENAI_API_KEY=<OpenAI API Key>
168
+ OPENAI_API_BASE=https://api.openai.com/v1 # 可选,默认为官方API地址
169
+ ```
188
170
 
189
- # 使用工具的功能
190
- jarvis-tool --help
171
+ 配置说明:
172
+ 1. `OPENAI_API_KEY`: 必填。
173
+ 2. `OPENAI_API_BASE`: 可选,用于自定义API端点
191
174
 
192
- # 使用代码库查询功能
193
- jarvis-ask-codebase --help
175
+ 以上配置编写到`~/.jarvis/env`文件中。
194
176
 
195
- # 使用git details的功能
196
- jarvis-git-details --help
177
+ 支持的模型可通过`jarvis-platform-manager --list-models`查看完整列表。
197
178
 
198
- # 使用方法论的功能
199
- jarvis-methodology --help
200
- ```
179
+ ### 基本使用
180
+ | 命令 | 快捷方式 | 功能描述 |
181
+ |------|----------|----------|
182
+ | `jarvis` | - | 使用通用代理 |
183
+ | `jarvis-code-agent` | `jca` | 使用代码代理 |
184
+ | `jarvis-smart-shell` | `jss` | 使用智能shell功能 |
185
+ | `jarvis-platform-manager` | - | 使用平台管理功能 |
186
+ | `jarvis-code-review` | - | 使用代码审查功能 |
187
+ | `jarvis-git-commit` | `jgc` | 使用自动化git commit功能 |
188
+ | `jarvis-dev` | - | 使用dev功能(开发中) |
189
+ | `jarvis-git-squash` | - | 使用git squash功能 |
190
+ | `jarvis-multi-agent` | - | 使用多代理功能 |
191
+ | `jarvis-agent` | - | 使用agent功能 |
192
+ | `jarvis-tool` | - | 使用工具功能 |
193
+ | `jarvis-ask-codebase` | `jac` | 使用代码库查询功能 |
194
+ | `jarvis-git-details` | - | 使用git details功能 |
195
+ | `jarvis-methodology` | - | 使用方法论功能 |
201
196
 
202
197
  ---
203
198
 
@@ -216,6 +211,9 @@ jarvis-methodology --help
216
211
  | `JARVIS_EXECUTE_TOOL_CONFIRM` | false | 执行工具前是否需要确认 |
217
212
  | `JARVIS_CONFIRM_BEFORE_APPLY_PATCH` | true | 应用补丁前是否需要确认 |
218
213
  | `JARVIS_MAX_TOOL_CALL_COUNT` | 20 | 最大连续工具调用次数 |
214
+ | `JARVIS_AUTO_UPDATE` | true | 是否自动更新Jarvis(仅在以git仓库方式安装时有效) |
215
+
216
+ 所有配置编写到`~/.jarvis/env`文件中即可生效。
219
217
 
220
218
 
221
219
  ---
@@ -412,3 +410,5 @@ class CustomPlatform(BasePlatform):
412
410
  <div align="center">
413
411
  由 Jarvis 团队用 ❤️ 制作
414
412
  </div>
413
+
414
+ ![Jarvis技术支持群](docs/images/wechat.png)
@@ -1,5 +1,5 @@
1
- jarvis/__init__.py,sha256=3qLxN_25GeKwUXq-k5i14C5ILs61cj1lSI5enn8O4z0,74
2
- jarvis/jarvis_agent/__init__.py,sha256=h0RBXWO-m2Cl9O0zPJ8ignj1RiSSzj--CL5d1q_ahxY,25367
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=OQNu7Bi-gmiM0odjSD3AG-pqnKh8hLzwNBWr1Uy0jpE,30216
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=s8wDnHXy38n5uQ0j-XPh2wnhPULQly7OWCg_9S69XqA,6176
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=d39-0CFFLMKf0JDTF7-wMRSJqbwPL_zg0omDGaJVBpQ,4013
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=c9OglWXt-B7FU-Yn60b_wZo4SFX5jMI_RxD4SAh2fVA,16691
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=NouTKMq6xujJX8jcd6QXDvd19PiS8ItcM2HT52MDd54,21867
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=vwgq4htsjAAq0-yUW2uujnfFcqxB_pf-6xpoayemcRU,4883
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
@@ -67,34 +67,35 @@ jarvis/jarvis_tools/chdir.py,sha256=wYVBqWF5kaUkKqH3cUAOKUsACzYsFtCCJJyd8UJsp4o,
67
67
  jarvis/jarvis_tools/code_plan.py,sha256=EzLdbJnVCkJ7lL8XIQyuDJdxU1i3CFiBpqyNG-GdJw8,7753
68
68
  jarvis/jarvis_tools/create_code_agent.py,sha256=cxYkjr4rhI2EWpK78psZSRB9mxiP1IUT0SEfFIqCJzY,3411
69
69
  jarvis/jarvis_tools/create_sub_agent.py,sha256=ppTOFRd0ygSJUFr3oQ8IrCLOqbZ7vwnbdadfTDjpDgs,3025
70
- jarvis/jarvis_tools/edit_file.py,sha256=gmWwbxaPNpJFOQj0hoc8558efagbyyM-TOzL2FjWlLg,13823
70
+ jarvis/jarvis_tools/edit_file.py,sha256=1SllJmc-1gHf8h8xwQylJs84Ac0xowVpg0-X6yabwkM,13827
71
71
  jarvis/jarvis_tools/execute_script.py,sha256=cc0NlPwhkZinEexqT63d1ofEkzQddVWGsZOCVL1v_60,5739
72
72
  jarvis/jarvis_tools/file_analyzer.py,sha256=tzU1cPKyDa54hVZewP0bDzdsjvdjGQ1BRt5k8N4li3s,4868
73
73
  jarvis/jarvis_tools/file_operation.py,sha256=lP8EpsnSdA3FW8ofSAdoA8qPGMAG3UhYd6LFEzOFUVY,9044
74
- jarvis/jarvis_tools/find_methodology.py,sha256=XldbV5XwkAhIxCqAuigmT6K9Q8vwMyVOinCYQZpoU1M,2292
74
+ jarvis/jarvis_tools/find_methodology.py,sha256=FwGKSV4fHNkiAnaVUwP8GkqXl8PEqMPZBxAyvTSPFGA,2438
75
+ jarvis/jarvis_tools/generate_new_tool.py,sha256=On4dXSmZZ_rVkNaZ151QE_3OWXXqtjs0lC-Dmxv9jSQ,11572
75
76
  jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=paz1CVZ2Y8nk0U74n1QiG01oDINiZqpVlPc2f4_B150,5346
76
77
  jarvis/jarvis_tools/methodology.py,sha256=Md8W2et0xUiuTjUSRCdnlwEPYqah2dCAAkxW_95BXBY,5238
77
78
  jarvis/jarvis_tools/read_code.py,sha256=pgztSBRh8RORFalqwzzsLHQogooFvDm1ePBL0E5O1C4,5961
78
- jarvis/jarvis_tools/read_webpage.py,sha256=wpN8E1BzhrWdfZf6WKvtfuOt41jm-BAPVsMXKMWJE10,2049
79
+ jarvis/jarvis_tools/read_webpage.py,sha256=LLvAOvaQJodaeNJKQ6dU9MYEE227NMdHyLs7esluUQ4,2217
79
80
  jarvis/jarvis_tools/registry.py,sha256=rRdvLzsAkMPfRFZz9GfTP9K8mGedoDt8Pj9drRI_yL8,27133
80
81
  jarvis/jarvis_tools/rewrite_file.py,sha256=rEPPSNU7uF1iKfEW9npEpZJ2LSoQXjt2OC-_troBToE,7003
81
- jarvis/jarvis_tools/search_web.py,sha256=k7WwvOAdBOiWmE8vtNrhmu8VAiH5oT5FD82kcEhRkiI,783
82
+ jarvis/jarvis_tools/search_web.py,sha256=-h1WYOqTcYC_8fdkm-4RfwKpbtLTVxOfRROul51NgO0,951
82
83
  jarvis/jarvis_tools/virtual_tty.py,sha256=AKAaKY5KcPxifNQoXjzHaL4U6EUVA7irHLwVvz2wLVs,16396
83
84
  jarvis/jarvis_utils/__init__.py,sha256=l-fsyQ-KzyqAhrJYur8eZAqsgaifGzSm24R2qtRGJ0g,849
84
85
  jarvis/jarvis_utils/builtin_replace_map.py,sha256=A-cJ8deht2vDl2iKRhoZ7qECyJ6sboVH5Zx-L9vIBUs,4314
85
- jarvis/jarvis_utils/config.py,sha256=OsHGIyGq2cUiEXU7P5CeJ_XfUjNoswNRIvBRbAWvzMY,4083
86
+ jarvis/jarvis_utils/config.py,sha256=T7-RIPIZx6qehTFuu8AFZA-SVTDpsYUCopJ6KYZ8RAQ,4315
86
87
  jarvis/jarvis_utils/embedding.py,sha256=05KvmZvtI2-7xxmj13kAknRezWuVeold-D68wyPvZSA,7015
87
88
  jarvis/jarvis_utils/file_processors.py,sha256=tSZSMJ4qCJ_lXI0dyLgJ0j5qEh6CDXDSVI7vQiFmcuQ,2976
88
- jarvis/jarvis_utils/git_utils.py,sha256=FSKu6YBOkb_-zHU35gicYTjPLk0H4XMq5kdUP5wSzwE,9980
89
+ jarvis/jarvis_utils/git_utils.py,sha256=MxhUcQ_gFUFyBxBiorEJ1wUk9a2TerFdq3-Z11FB-AE,11324
89
90
  jarvis/jarvis_utils/globals.py,sha256=Zs0chxA_giYiolYvawFFpcnTWgCUnn6GEusAh42jbz8,2275
90
91
  jarvis/jarvis_utils/input.py,sha256=qGf2q-yWhgT-OX-j_WYi7aZ11jYmuFNiMz2_W1nUOiM,7432
91
- jarvis/jarvis_utils/methodology.py,sha256=oGPWA0m4dGOgvjhU9JZqhPA0GbJM9Bcykr9TqPFDc30,7819
92
+ jarvis/jarvis_utils/methodology.py,sha256=d25o61UtnuwgIQBgnajxx9zPsxsVzv4Ptb9BGwC93Nk,8156
92
93
  jarvis/jarvis_utils/output.py,sha256=PVG4fQ3P-eGOZUNZTowPtnjqq3GN91OE8fHa68lFOOg,8440
93
94
  jarvis/jarvis_utils/tag.py,sha256=YJHmuedLb7_AiqvKQetHr4R1FxyzIh7HN0RRkWMmYbU,429
94
- jarvis/jarvis_utils/utils.py,sha256=cm22M2nCT29Ra6k92cZbB5pnqKGyXJqL9_wNByVfDgQ,5248
95
- jarvis_ai_assistant-0.1.165.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
96
- jarvis_ai_assistant-0.1.165.dist-info/METADATA,sha256=or-Jo3A8VUVkiEIEANS6zyn2frvIovpkNZhvwDw_X1A,13435
97
- jarvis_ai_assistant-0.1.165.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
98
- jarvis_ai_assistant-0.1.165.dist-info/entry_points.txt,sha256=cKz_9SEpOvElTubKPMZMAdskD4GHz-NyKWRNssIVAWE,973
99
- jarvis_ai_assistant-0.1.165.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
100
- jarvis_ai_assistant-0.1.165.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.4.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5