jarvis-ai-assistant 0.1.188__py3-none-any.whl → 0.1.189__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.188"
4
+ __version__ = "0.1.189"
@@ -4,8 +4,6 @@ import datetime
4
4
  import platform
5
5
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
6
6
 
7
- from jarvis.jarvis_platform.base import BasePlatform
8
-
9
7
  # 第三方库导入
10
8
  from yaspin import yaspin # type: ignore
11
9
 
@@ -224,7 +222,11 @@ class Agent:
224
222
 
225
223
  # 如果有上传文件,自动禁用方法论
226
224
  self.use_methodology = (
227
- False if files else (use_methodology if use_methodology is not None else is_use_methodology())
225
+ False
226
+ if files
227
+ else (
228
+ use_methodology if use_methodology is not None else is_use_methodology()
229
+ )
228
230
  )
229
231
  self.use_analysis = (
230
232
  use_analysis if use_analysis is not None else is_use_analysis()
@@ -440,24 +442,15 @@ class Agent:
440
442
  self.conversation_length += get_context_token_count(response)
441
443
  return response
442
444
 
443
- def _summarize_and_clear_history(self) -> str:
444
- """总结当前对话并清理历史记录
445
-
446
- 该方法将:
447
- 1. 生成关键信息摘要
448
- 2. 清除对话历史
449
- 3. 保留系统消息
450
- 4. 添加摘要作为新上下文
451
- 5. 重置对话长度计数器
445
+ def generate_summary(self) -> str:
446
+ """生成对话历史摘要
452
447
 
453
448
  返回:
454
449
  str: 包含对话摘要的字符串
455
450
 
456
451
  注意:
457
- 当上下文长度超过最大值时使用
452
+ 仅生成摘要,不修改对话状态
458
453
  """
459
- # Create a new model instance to summarize, avoid affecting the main conversation
460
-
461
454
  with yaspin(text="正在总结对话历史...", color="cyan") as spinner:
462
455
  summary_prompt = """
463
456
  <summary_request>
@@ -482,36 +475,48 @@ class Agent:
482
475
  </summary_request>
483
476
  """
484
477
 
485
- try:
486
- with spinner.hidden():
487
- summary = self.model.chat_until_success(self.prompt + "\n" + summary_prompt) # type: ignore
478
+ try:
479
+ with spinner.hidden():
480
+ summary = self.model.chat_until_success(self.prompt + "\n" + summary_prompt) # type: ignore
481
+ spinner.text = "总结对话历史完成"
482
+ spinner.ok("✅")
483
+ return summary
484
+ except Exception as e:
485
+ spinner.text = "总结对话历史失败"
486
+ spinner.fail("❌")
487
+ return ""
488
488
 
489
- self.model.reset() # type: ignore
489
+ def _summarize_and_clear_history(self) -> str:
490
+ """总结当前对话并清理历史记录
490
491
 
491
- # 清空当前对话历史,但保留系统消息
492
- self.conversation_length = 0 # Reset conversation length
492
+ 该方法将:
493
+ 1. 调用_generate_summary生成摘要
494
+ 2. 清除对话历史
495
+ 3. 保留系统消息
496
+ 4. 添加摘要作为新上下文
497
+ 5. 重置对话长度计数器
493
498
 
494
- # 添加总结作为新的上下文
495
- spinner.text = "总结对话历史完成"
496
- spinner.ok("✅")
497
- return f"""<summary>
498
- <header>
499
+ 返回:
500
+ str: 包含对话摘要的字符串
501
+
502
+ 注意:
503
+ 当上下文长度超过最大值时使用
504
+ """
505
+ summary = self.generate_summary()
506
+ self.clear_history() # type: ignore
507
+
508
+ if not summary:
509
+ return ""
510
+
511
+ return f"""
499
512
  以下是之前对话的关键信息总结:
500
- </header>
501
513
 
502
514
  <content>
503
515
  {summary}
504
516
  </content>
505
517
 
506
- <instructions>
507
518
  请基于以上信息继续完成任务。请注意,这是之前对话的摘要,上下文长度已超过限制而被重置。请直接继续任务,无需重复已完成的步骤。如有需要,可以询问用户以获取更多信息。
508
- </instructions>
509
- </summary>
510
519
  """
511
- except Exception as e:
512
- spinner.text = "总结对话历史失败"
513
- spinner.fail("❌")
514
- return ""
515
520
 
516
521
  def _call_tools(self, response: str) -> Tuple[bool, Any]:
517
522
  """调用工具执行响应
@@ -770,32 +775,31 @@ arguments:
770
775
  3. 包含错误处理和恢复逻辑
771
776
  4. 自动加载相关方法论(如果是首次运行)
772
777
  """
778
+
779
+ self.prompt = f"{user_input}"
773
780
  try:
774
781
  set_agent(self.name, self)
775
782
 
776
- self.prompt = f"{user_input}"
777
-
778
- if self.first:
779
- # 如果有上传文件,先上传文件
780
- if self.files and isinstance(self.model, BasePlatform) and hasattr(self.model, "upload_files"):
781
- self.model.upload_files(self.files)
782
- self.prompt = f"{user_input}"
783
-
784
- # 如果启用方法论且没有上传文件,上传方法论
785
- elif self.use_methodology:
786
- platform = self.model if hasattr(self.model, "upload_files") else None
787
- if platform and upload_methodology(platform):
788
- self.prompt = f"{user_input}"
789
- else:
790
- # 上传失败则回退到本地加载
791
- msg = user_input
792
- for handler in self.input_handler:
793
- msg, _ = handler(msg, self)
794
- self.prompt = f"{user_input}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
795
-
796
- self.first = False
797
-
798
783
  while True:
784
+ if self.first:
785
+ # 如果有上传文件,先上传文件
786
+ if (
787
+ self.files
788
+ and self.model
789
+ and self.model.support_upload_files()
790
+ ):
791
+ self.model.upload_files(self.files)
792
+
793
+ # 如果启用方法论且没有上传文件,上传方法论
794
+ elif self.use_methodology:
795
+ if not self.model or not upload_methodology(self.model):
796
+ # 上传失败则回退到本地加载
797
+ msg = self.prompt
798
+ for handler in self.input_handler:
799
+ msg, _ = handler(msg, self)
800
+ self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
801
+
802
+ self.first = False
799
803
  try:
800
804
  current_response = self._call_model(self.prompt, True)
801
805
  self.prompt = ""
@@ -836,7 +840,7 @@ arguments:
836
840
  PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
837
841
  return f"Task failed: {str(e)}"
838
842
 
839
- def _clear_history(self):
843
+ def clear_history(self):
840
844
  """清空对话历史但保留系统提示
841
845
 
842
846
  该方法将:
@@ -588,25 +588,33 @@ class CodeReviewTool:
588
588
  temp_file.flush()
589
589
 
590
590
  try:
591
- upload_success = False
592
591
  # Check if content is too large
593
592
  is_large_content = is_context_overflow(diff_output)
594
593
 
595
594
  # Upload the file to the agent's model
596
- if is_large_content and agent.model and hasattr(agent.model, 'upload_files'):
595
+ if is_large_content:
596
+ if not agent.model or not agent.model.support_upload_files():
597
+ return {
598
+ "success": False,
599
+ "stdout": "",
600
+ "stderr": "代码差异太大,无法处理"
601
+ }
602
+
597
603
  with yaspin(text="正在上传代码差异文件...", color="cyan") as spinner:
598
604
  upload_success = agent.model.upload_files([temp_file_path])
599
605
  if upload_success:
600
606
  spinner.ok("✅")
601
607
  PrettyOutput.print(f"已成功上传代码差异文件", OutputType.SUCCESS)
602
608
  else:
603
- spinner.fail("❌")
604
- PrettyOutput.print(f"上传代码差异文件失败,将使用分块处理", OutputType.WARNING)
605
- else:
606
- upload_success = False
609
+ return {
610
+ "success": False,
611
+ "stdout": "",
612
+ "stderr": "上传代码差异文件失败"
613
+ }
614
+
607
615
 
608
616
  # Prepare the prompt based on upload status
609
- if upload_success:
617
+ if is_large_content:
610
618
  # When file is uploaded, reference it in the prompt
611
619
  complete_prompt = user_prompt + f"""
612
620
 
@@ -619,13 +627,6 @@ class CodeReviewTool:
619
627
  # Run the agent with the prompt
620
628
  result = agent.run(complete_prompt)
621
629
  else:
622
- if is_large_content:
623
- return {
624
- "success": False,
625
- "stdout": "",
626
- "stderr": "错误:上传代码差异文件失败"
627
- }
628
- # Include the diff directly in the prompt for smaller content
629
630
  complete_prompt = user_prompt + "\n\n代码差异内容:\n```diff\n" + diff_output + "\n```"
630
631
  result = agent.run(complete_prompt)
631
632
  finally:
@@ -179,7 +179,7 @@
179
179
  "JARVIS_MAX_BIG_CONTENT_SIZE": {
180
180
  "type": "number",
181
181
  "description": "最大大内容尺寸",
182
- "default": 1024000
182
+ "default": 160000
183
183
  },
184
184
  "JARVIS_PRETTY_OUTPUT": {
185
185
  "type": "boolean",
jarvis/jarvis_dev/main.py CHANGED
@@ -1160,42 +1160,42 @@ def create_dev_team() -> MultiAgent:
1160
1160
  description="Project Manager - Coordinates team and manages project delivery",
1161
1161
  system_prompt=PM_PROMPT_WITH_TOOLS,
1162
1162
  output_handler=[PM_output_handler],
1163
- platform=PlatformRegistry().get_thinking_platform(),
1163
+ platform=PlatformRegistry().get_normal_platform(),
1164
1164
  ),
1165
1165
  dict(
1166
1166
  name="BA",
1167
1167
  description="Business Analyst - Analyzes and documents requirements",
1168
1168
  system_prompt=BA_PROMPT_WITH_TOOLS,
1169
1169
  output_handler=[BA_output_handler],
1170
- platform=PlatformRegistry().get_thinking_platform(),
1170
+ platform=PlatformRegistry().get_normal_platform(),
1171
1171
  ),
1172
1172
  dict(
1173
1173
  name="SA",
1174
1174
  description="Solution Architect - Designs technical solutions",
1175
1175
  system_prompt=SA_PROMPT_WITH_TOOLS,
1176
1176
  output_handler=[SA_output_handler],
1177
- platform=PlatformRegistry().get_thinking_platform(),
1177
+ platform=PlatformRegistry().get_normal_platform(),
1178
1178
  ),
1179
1179
  dict(
1180
1180
  name="TL",
1181
1181
  description="Technical Lead - Leads development team and ensures technical quality",
1182
1182
  system_prompt=TL_PROMPT_WITH_TOOLS,
1183
1183
  output_handler=[TL_output_handler],
1184
- platform=PlatformRegistry().get_thinking_platform(),
1184
+ platform=PlatformRegistry().get_normal_platform(),
1185
1185
  ),
1186
1186
  dict(
1187
1187
  name="DEV",
1188
1188
  description="Developer - Implements features and writes code",
1189
1189
  system_prompt=DEV_PROMPT_WITH_TOOLS,
1190
1190
  output_handler=[DEV_output_handler],
1191
- platform=PlatformRegistry().get_thinking_platform(),
1191
+ platform=PlatformRegistry().get_normal_platform(),
1192
1192
  ),
1193
1193
  dict(
1194
1194
  name="QA",
1195
1195
  description="Quality Assurance - Ensures product quality through testing",
1196
1196
  system_prompt=QA_PROMPT_WITH_TOOLS,
1197
1197
  output_handler=[QA_output_handler],
1198
- platform=PlatformRegistry().get_thinking_platform(),
1198
+ platform=PlatformRegistry().get_normal_platform(),
1199
1199
  )
1200
1200
  ]
1201
1201
 
@@ -207,7 +207,7 @@ class GitCommitAnalyzer:
207
207
  [检查代码是否符合行业最佳实践和项目规范]
208
208
  {ct("REPORT")}""",
209
209
  output_handler=[tool_registry],
210
- platform=PlatformRegistry().get_thinking_platform(),
210
+ platform=PlatformRegistry().get_normal_platform(),
211
211
  auto_complete=True
212
212
  )
213
213
 
@@ -12,8 +12,7 @@ from yaspin import yaspin
12
12
 
13
13
  from jarvis.jarvis_platform.registry import PlatformRegistry
14
14
  from jarvis.jarvis_utils.config import get_git_commit_prompt
15
- from jarvis.jarvis_utils.git_utils import (find_git_root,
16
- has_uncommitted_changes)
15
+ from jarvis.jarvis_utils.git_utils import find_git_root, has_uncommitted_changes
17
16
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
18
17
  from jarvis.jarvis_utils.tag import ct, ot
19
18
  from jarvis.jarvis_utils.utils import init_env, is_context_overflow
@@ -22,48 +21,59 @@ from jarvis.jarvis_utils.utils import init_env, is_context_overflow
22
21
  class GitCommitTool:
23
22
  name = "git_commit_agent"
24
23
  description = "根据代码变更自动生成并执行Git提交"
25
- labels = ['git', 'version_control']
24
+ labels = ["git", "version_control"]
26
25
  parameters = {
27
26
  "type": "object",
28
27
  "properties": {
29
28
  "root_dir": {
30
29
  "type": "string",
31
30
  "description": "Git仓库的根目录路径(可选)",
32
- "default": "."
31
+ "default": ".",
33
32
  },
34
- "prefix": {
35
- "type": "string",
36
- "description": "提交信息前缀(可选)",
37
- "default": ""
38
- },
39
- "suffix": {
40
- "type": "string",
41
- "description": "提交信息后缀(可选)",
42
- "default": ""
43
- }
33
+ "prefix": {"type": "string", "description": "提交信息前缀(可选)", "default": ""},
34
+ "suffix": {"type": "string", "description": "提交信息后缀(可选)", "default": ""},
44
35
  },
45
- "required": []
36
+ "required": [],
46
37
  }
47
- def _extract_commit_message(self, message)->Optional[str]:
38
+
39
+ def _extract_commit_message(self, message) -> Optional[str]:
48
40
  """Raw extraction preserving all characters"""
49
41
  r = re.search(
50
42
  r"(?i)" + ot("COMMIT_MESSAGE") + r"\s*([\s\S]*?)\s*" + ct("COMMIT_MESSAGE"),
51
- message
43
+ message,
52
44
  )
53
45
  if r:
54
46
  # 直接返回原始内容,仅去除外围空白
55
47
  return r.group(1).strip()
56
48
  return None
57
49
 
58
- def _get_last_commit_hash(self):
50
+ def _get_last_commit_hash(self) -> str:
59
51
  process = subprocess.Popen(
60
52
  ["git", "log", "-1", "--pretty=%H"],
61
53
  stdout=subprocess.PIPE,
62
- stderr=subprocess.PIPE
54
+ stderr=subprocess.PIPE,
63
55
  )
64
56
  stdout, _ = process.communicate()
65
57
  return stdout.decode().strip()
66
58
 
59
+ def _prepare_git_environment(self, root_dir: str) -> Optional[str]:
60
+ """Prepare git environment by changing directory and checking for changes"""
61
+ original_dir = os.getcwd()
62
+ os.chdir(root_dir)
63
+ find_git_root()
64
+ if not has_uncommitted_changes():
65
+ PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
66
+ return None
67
+ return original_dir
68
+
69
+ def _stage_changes(self, spinner) -> None:
70
+ """Stage all changes for commit"""
71
+ spinner.text = "正在添加文件到提交..."
72
+ subprocess.Popen(
73
+ ["git", "add", "."], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
74
+ ).wait()
75
+ spinner.write("✅ 添加文件到提交")
76
+
67
77
  def execute(self, args: Dict) -> Dict[str, Any]:
68
78
  """Execute automatic commit process with support for multi-line messages and special characters"""
69
79
  try:
@@ -71,214 +81,240 @@ class GitCommitTool:
71
81
  prefix = args.get("prefix", "")
72
82
  suffix = args.get("suffix", "")
73
83
 
74
- # Store current directory
75
- original_dir = os.getcwd()
84
+ # Prepare git environment
85
+ result = self._prepare_git_environment(root_dir)
86
+ if result is None:
87
+ return {"success": True, "stdout": "No changes to commit", "stderr": ""}
88
+ original_dir = result
76
89
 
77
- try:
78
- # Change to root_dir
79
- os.chdir(root_dir)
90
+ with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
91
+ # 添加文件到暂存区
92
+ self._stage_changes(spinner)
80
93
 
81
- find_git_root()
82
- if not has_uncommitted_changes():
83
- PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
84
- return {"success": True, "stdout": "No changes to commit", "stderr": ""}
94
+ # 获取差异
95
+ spinner.text = "正在获取代码差异..."
96
+ # 获取文件列表
97
+ files_cmd = ["git", "diff", "--cached", "--name-only"]
98
+ process = subprocess.Popen(
99
+ files_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
100
+ )
101
+ files_output = process.communicate()[0].decode()
102
+ files = [f.strip() for f in files_output.split("\n") if f.strip()]
103
+ file_count = len(files)
85
104
 
86
- with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
87
- # 添加文件
88
- spinner.text = "正在添加文件到提交..."
89
- subprocess.Popen(
90
- ["git", "add", "."],
91
- stdout=subprocess.DEVNULL,
92
- stderr=subprocess.DEVNULL
93
- ).wait()
94
- spinner.write("✅ 添加文件到提交")
105
+ # 获取完整差异
106
+ process = subprocess.Popen(
107
+ ["git", "diff", "--cached", "--exit-code"],
108
+ stdout=subprocess.PIPE,
109
+ stderr=subprocess.PIPE,
110
+ )
111
+ diff = process.communicate()[0].decode()
112
+ spinner.write(f"✅ 获取差异 ({file_count} 个文件)")
113
+ try:
114
+ temp_diff_file_path = None
115
+ # 生成提交信息
116
+ spinner.text = "正在生成提交消息..."
95
117
 
96
- # 获取差异
97
- spinner.text = "正在获取代码差异..."
98
- # 获取文件列表
99
- files_cmd = ["git", "diff", "--cached", "--name-only"]
100
- process = subprocess.Popen(
101
- files_cmd,
102
- stdout=subprocess.PIPE,
103
- stderr=subprocess.PIPE
104
- )
105
- files_output = process.communicate()[0].decode()
106
- files = [f.strip() for f in files_output.split("\n") if f.strip()]
107
- file_count = len(files)
108
-
109
- # 获取完整差异
110
- process = subprocess.Popen(
111
- ["git", "diff", "--cached", "--exit-code"],
112
- stdout=subprocess.PIPE,
113
- stderr=subprocess.PIPE
118
+ # 准备提示信息
119
+ custom_prompt = get_git_commit_prompt()
120
+ base_prompt = (
121
+ custom_prompt
122
+ if custom_prompt
123
+ else f"""根据代码差异生成提交信息:
124
+ 提交信息应使用中文书写
125
+ # 格式模板
126
+ 必须使用以下格式:
127
+
128
+ <类型>(<范围>): <主题>
129
+
130
+ [可选] 详细描述变更内容和原因
131
+
132
+ # 格式规则
133
+ 1. 类型: fix(修复bug), feat(新功能), docs(文档), style(格式), refactor(重构), test(测试), chore(其他)
134
+ 2. 范围表示变更的模块或组件 (例如: auth, database, ui)
135
+ 3. 主题行不超过72个字符,不以句号结尾,使用祈使语气
136
+ 4. 如有详细描述,使用空行分隔主题和详细描述
137
+ 5. 详细描述部分应解释"是什么"和"为什么",而非"如何"
138
+ 6. 仅输出提交信息,不要输出其他内容
139
+ """
114
140
  )
115
- diff = process.communicate()[0].decode()
116
- spinner.write(f"✅ 获取差异 ({file_count} 个文件)")
117
- try:
118
- temp_diff_file_path = None
119
- # 生成提交信息
120
- spinner.text = "正在生成提交消息..."
121
-
122
- # 准备提示信息
123
- custom_prompt = get_git_commit_prompt()
124
- base_prompt = custom_prompt if custom_prompt else f'''根据代码差异生成提交信息:
125
- 提交信息应使用中文书写
126
- # 格式模板
127
- 必须使用以下格式:
141
+ base_prompt += f"""
142
+ # 输出格式
143
+ {ot("COMMIT_MESSAGE")}
144
+ commit信息
145
+ {ct("COMMIT_MESSAGE")}
146
+ """
128
147
 
129
- <类型>(<范围>): <主题>
130
-
131
- [可选] 详细描述变更内容和原因
148
+ # 获取模型并尝试上传文件
149
+ platform = PlatformRegistry().get_normal_platform()
150
+ upload_success = False
132
151
 
133
- # 格式规则
134
- 1. 类型: fix(修复bug), feat(新功能), docs(文档), style(格式), refactor(重构), test(测试), chore(其他)
135
- 2. 范围表示变更的模块或组件 (例如: auth, database, ui)
136
- 3. 主题行不超过72个字符,不以句号结尾,使用祈使语气
137
- 4. 如有详细描述,使用空行分隔主题和详细描述
138
- 5. 详细描述部分应解释"是什么"和"为什么",而非"如何"
139
- 6. 仅输出提交信息,不要输出其他内容
140
- '''
141
- base_prompt += f"""
142
- # 输出格式
143
- {ot("COMMIT_MESSAGE")}
144
- commit信息
145
- {ct("COMMIT_MESSAGE")}
146
- """
152
+ # Check if content is too large
153
+ is_large_content = is_context_overflow(diff)
147
154
 
148
- # 获取模型并尝试上传文件
149
- platform = PlatformRegistry().get_normal_platform()
150
- upload_success = False
151
-
152
- # Check if content is too large
153
- is_large_content = is_context_overflow(diff)
154
-
155
- if is_large_content and hasattr(platform, 'upload_files'):
156
- spinner.text = "正在上传代码差异文件..."
157
- try:
158
- with spinner.hidden():
159
- # 创建临时文件并写入差异内容
160
- with tempfile.NamedTemporaryFile(mode='w', suffix='.diff', delete=False) as temp_diff_file:
161
- temp_diff_file_path = temp_diff_file.name
162
- temp_diff_file.write(diff)
163
- temp_diff_file.flush()
164
- spinner.write(f"✅ 差异内容已写入临时文件")
165
- upload_success = platform.upload_files([temp_diff_file_path])
166
- if upload_success:
167
- spinner.write("✅ 成功上传代码差异文件")
168
- else:
169
- spinner.write("⚠️ 上传代码差异文件失败,将使用分块处理")
170
- except Exception as e:
171
- spinner.write(f"⚠️ 上传文件时出错: {str(e)}")
172
- upload_success = False
173
- # 根据上传状态准备完整的提示
155
+ if is_large_content:
156
+ if not platform.support_upload_files():
157
+ spinner.text = "差异文件太大,无法处理"
158
+ spinner.fail("❌")
159
+ return {
160
+ "success": False,
161
+ "stdout": "",
162
+ "stderr": "错误:差异文件太大,无法处理",
163
+ }
164
+ spinner.text = "正在上传代码差异文件..."
165
+ with spinner.hidden():
166
+ # 创建临时文件并写入差异内容
167
+ with tempfile.NamedTemporaryFile(
168
+ mode="w", suffix=".diff", delete=False
169
+ ) as temp_diff_file:
170
+ temp_diff_file_path = temp_diff_file.name
171
+ temp_diff_file.write(diff)
172
+ temp_diff_file.flush()
173
+ spinner.write(f"✅ 差异内容已写入临时文件")
174
+ upload_success = platform.upload_files(
175
+ [temp_diff_file_path]
176
+ )
174
177
  if upload_success:
175
- # 尝试生成提交信息
176
- spinner.text = "正在生成提交消息..."
177
- # 使用上传的文件
178
- prompt = base_prompt + f'''
179
- # 变更概述
180
- - 变更文件数量: {file_count} 个文件
181
- - 已上传包含完整代码差异的文件
182
-
183
- 请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
184
- '''
185
- commit_message = platform.chat_until_success(prompt)
178
+ spinner.write("✅ 成功上传代码差异文件")
186
179
  else:
187
- if is_large_content:
188
- return {
189
- "success": False,
190
- "stdout": "",
191
- "stderr": "错误:上传代码差异文件失败"
192
- }
193
- # 直接在提示中包含差异内容
194
- prompt = base_prompt + f'''
195
- # 分析材料
196
- {diff}
197
- '''
198
- commit_message = platform.chat_until_success(prompt)
199
-
200
- while True:
201
- # 只在特定情况下重新获取commit_message
202
- if not upload_success and not is_large_content and not commit_message:
203
- commit_message = platform.chat_until_success(prompt)
204
- extracted_message = self._extract_commit_message(commit_message)
205
- # 如果成功提取,就跳出循环
206
- if extracted_message:
207
- commit_message = extracted_message
208
- # 应用prefix和suffix
209
- if prefix:
210
- commit_message = f"{prefix} {commit_message}"
211
- if suffix:
212
- commit_message = f"{commit_message}\n{suffix}"
213
- break
214
- prompt = f"""格式错误,请按照以下格式重新生成提交信息:
215
- {ot("COMMIT_MESSAGE")}
216
- commit信息
217
- {ct("COMMIT_MESSAGE")}
218
- """
219
- commit_message = platform.chat_until_success(prompt)
220
- spinner.write("✅ 生成提交消息")
180
+ spinner.text = "上传代码差异文件失败"
181
+ spinner.fail("❌")
182
+ return {
183
+ "success": False,
184
+ "stdout": "",
185
+ "stderr": "错误:上传代码差异文件失败",
186
+ }
187
+ # 根据上传状态准备完整的提示
188
+ if is_large_content:
189
+ # 尝试生成提交信息
190
+ spinner.text = "正在生成提交消息..."
191
+ # 使用上传的文件
192
+ prompt = (
193
+ base_prompt
194
+ + f"""
195
+ # 变更概述
196
+ - 变更文件数量: {file_count} 个文件
197
+ - 已上传包含完整代码差异的文件
221
198
 
222
- # 执行提交
223
- spinner.text = "正在准备提交..."
224
- with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
225
- tmp_file.write(commit_message)
226
- tmp_file.flush()
227
- spinner.text = "正在执行提交..."
228
- commit_cmd = ["git", "commit", "-F", tmp_file.name]
229
- subprocess.Popen(
230
- commit_cmd,
231
- stdout=subprocess.DEVNULL,
232
- stderr=subprocess.DEVNULL
233
- ).wait()
234
- spinner.write("✅ 提交")
199
+ 请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
200
+ """
201
+ )
202
+ commit_message = platform.chat_until_success(prompt)
203
+ else:
204
+ prompt = (
205
+ base_prompt
206
+ + f"""
207
+ # 分析材料
208
+ {diff}
209
+ """
210
+ )
211
+ commit_message = platform.chat_until_success(prompt)
235
212
 
236
- commit_hash = self._get_last_commit_hash()
237
- spinner.text = "完成提交"
238
- spinner.ok("✅")
239
- finally:
240
- # 清理临时差异文件
241
- if temp_diff_file_path is not None and os.path.exists(temp_diff_file_path):
242
- try:
243
- os.unlink(temp_diff_file_path)
244
- except Exception as e:
245
- spinner.write(f"⚠️ 无法删除临时文件: {str(e)}")
213
+ while True:
214
+ # 只在特定情况下重新获取commit_message
215
+ if (
216
+ not upload_success
217
+ and not is_large_content
218
+ and not commit_message
219
+ ):
220
+ commit_message = platform.chat_until_success(prompt)
221
+ extracted_message = self._extract_commit_message(commit_message)
222
+ # 如果成功提取,就跳出循环
223
+ if extracted_message:
224
+ commit_message = extracted_message
225
+ # 应用prefix和suffix
226
+ if prefix:
227
+ commit_message = f"{prefix} {commit_message}"
228
+ if suffix:
229
+ commit_message = f"{commit_message}\n{suffix}"
230
+ break
231
+ prompt = f"""格式错误,请按照以下格式重新生成提交信息:
232
+ {ot("COMMIT_MESSAGE")}
233
+ commit信息
234
+ {ct("COMMIT_MESSAGE")}
235
+ """
236
+ commit_message = platform.chat_until_success(prompt)
237
+ spinner.write("✅ 生成提交消息")
246
238
 
247
- PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
239
+ # 执行提交
240
+ spinner.text = "正在准备提交..."
241
+ with tempfile.NamedTemporaryFile(mode="w", delete=True) as tmp_file:
242
+ tmp_file.write(commit_message)
243
+ tmp_file.flush()
244
+ spinner.text = "正在执行提交..."
245
+ commit_cmd = ["git", "commit", "-F", tmp_file.name]
246
+ subprocess.Popen(
247
+ commit_cmd,
248
+ stdout=subprocess.DEVNULL,
249
+ stderr=subprocess.DEVNULL,
250
+ ).wait()
251
+ spinner.write("✅ 提交")
248
252
 
249
- return {
250
- "success": True,
251
- "stdout": yaml.safe_dump({
252
- "commit_hash": commit_hash,
253
- "commit_message": commit_message
254
- }, allow_unicode=True),
255
- "stderr": ""
256
- }
257
- finally:
258
- # Always restore original directory
259
- os.chdir(original_dir)
253
+ commit_hash = self._get_last_commit_hash()
254
+ spinner.text = "完成提交"
255
+ spinner.ok("")
256
+ finally:
257
+ # 清理临时差异文件
258
+ if temp_diff_file_path is not None and os.path.exists(
259
+ temp_diff_file_path
260
+ ):
261
+ try:
262
+ os.unlink(temp_diff_file_path)
263
+ except Exception as e:
264
+ spinner.write(f"⚠️ 无法删除临时文件: {str(e)}")
260
265
 
266
+ PrettyOutput.print(
267
+ f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS
268
+ )
269
+
270
+ return {
271
+ "success": True,
272
+ "stdout": yaml.safe_dump(
273
+ {"commit_hash": commit_hash, "commit_message": commit_message},
274
+ allow_unicode=True,
275
+ ),
276
+ "stderr": "",
277
+ }
261
278
  except Exception as e:
262
279
  PrettyOutput.print(f"提交失败: {str(e)}", OutputType.ERROR)
263
280
  return {
264
281
  "success": False,
265
282
  "stdout": "",
266
- "stderr": f"Commit failed: {str(e)}"
283
+ "stderr": f"Commit failed: {str(e)}",
267
284
  }
285
+ finally:
286
+ # Always restore original directory
287
+ os.chdir(original_dir)
288
+
268
289
 
269
290
  def main():
270
291
  init_env("欢迎使用 Jarvis-GitCommitTool,您的Git提交助手已准备就绪!")
271
- parser = argparse.ArgumentParser(description='Git commit tool')
272
- parser.add_argument('--root-dir', type=str, default='.', help='Root directory of the Git repository')
273
- parser.add_argument('--prefix', type=str, default='', help='Prefix to prepend to commit message (separated by space)')
274
- parser.add_argument('--suffix', type=str, default='', help='Suffix to append to commit message (separated by newline)')
292
+ parser = argparse.ArgumentParser(description="Git commit tool")
293
+ parser.add_argument(
294
+ "--root-dir", type=str, default=".", help="Root directory of the Git repository"
295
+ )
296
+ parser.add_argument(
297
+ "--prefix",
298
+ type=str,
299
+ default="",
300
+ help="Prefix to prepend to commit message (separated by space)",
301
+ )
302
+ parser.add_argument(
303
+ "--suffix",
304
+ type=str,
305
+ default="",
306
+ help="Suffix to append to commit message (separated by newline)",
307
+ )
275
308
  args = parser.parse_args()
276
309
  tool = GitCommitTool()
277
- tool.execute({
278
- "root_dir": args.root_dir,
279
- "prefix": args.prefix if hasattr(args, 'prefix') else '',
280
- "suffix": args.suffix if hasattr(args, 'suffix') else ''
281
- })
310
+ tool.execute(
311
+ {
312
+ "root_dir": args.root_dir,
313
+ "prefix": args.prefix if hasattr(args, "prefix") else "",
314
+ "suffix": args.suffix if hasattr(args, "suffix") else "",
315
+ }
316
+ )
317
+
282
318
 
283
319
  if __name__ == "__main__":
284
- sys.exit(main())
320
+ sys.exit(main())
@@ -49,6 +49,10 @@ class BasePlatform(ABC):
49
49
  def upload_files(self, file_list: List[str]) -> bool:
50
50
  raise NotImplementedError("upload_files is not implemented")
51
51
 
52
+ @abstractmethod
53
+ def support_upload_files(self) -> bool:
54
+ """Check if platform supports upload files"""
55
+ return False
52
56
 
53
57
 
54
58
  def _chat(self, message: str):
@@ -56,9 +60,6 @@ class BasePlatform(ABC):
56
60
  start_time = time.time()
57
61
 
58
62
  input_token_count = get_context_token_count(message)
59
- if is_context_overflow(message):
60
- PrettyOutput.print("错误:输入内容超过最大限制", OutputType.WARNING)
61
- return "错误:输入内容超过最大限制"
62
63
 
63
64
  if input_token_count > get_max_input_token_count():
64
65
  max_chunk_size = get_max_input_token_count() - 1024 # 留出一些余量
@@ -90,6 +90,10 @@ class KimiModel(BasePlatform):
90
90
 
91
91
  response = while_success(lambda: requests.post(url, headers=headers, data=payload), sleep_time=5)
92
92
  return response.json()
93
+
94
+ def support_upload_files(self) -> bool:
95
+ """Check if platform supports upload files"""
96
+ return True
93
97
 
94
98
  def _upload_file(self, file_path: str, presigned_url: str) -> bool:
95
99
  """Upload file to presigned URL"""
@@ -67,6 +67,10 @@ class TongyiPlatform(BasePlatform):
67
67
  def _generate_request_id(self):
68
68
  self.request_id = str(uuid.uuid4()).replace("-", "")
69
69
 
70
+ def support_upload_files(self) -> bool:
71
+ """Check if platform supports upload files"""
72
+ return True
73
+
70
74
  def chat(self, message: str) -> Generator[str, None, None]:
71
75
  if not self.request_id:
72
76
  self._generate_request_id()
@@ -107,6 +107,10 @@ class YuanbaoPlatform(BasePlatform):
107
107
  PrettyOutput.print(f"错误:创建会话失败:{e}", OutputType.ERROR)
108
108
  return False
109
109
 
110
+ def support_upload_files(self) -> bool:
111
+ """Check if platform supports upload files"""
112
+ return True
113
+
110
114
  def upload_files(self, file_list: List[str]) -> bool:
111
115
  """上传文件到元宝平台
112
116
 
@@ -105,6 +105,10 @@ def chat_with_model(platform_name: str, model_name: str):
105
105
  # Remove quotes if present
106
106
  if (file_path.startswith('"') and file_path.endswith('"')) or (file_path.startswith("'") and file_path.endswith("'")):
107
107
  file_path = file_path[1:-1]
108
+
109
+ if not platform.support_upload_files():
110
+ PrettyOutput.print("平台不支持上传文件", OutputType.ERROR)
111
+ continue
108
112
 
109
113
  PrettyOutput.print(f"正在上传文件: {file_path}", OutputType.INFO)
110
114
  if platform.upload_files([file_path]):
@@ -286,11 +286,11 @@ def slow_edit(filepath: str, patch_content: str, spinner: Yaspin) -> Tuple[bool,
286
286
  model = PlatformRegistry().get_normal_platform()
287
287
  try:
288
288
  file_content = FileOperationTool().execute({"operation":"read", "files":[{"path":filepath}]})["stdout"]
289
- need_upload_file = is_context_overflow(file_content)
289
+ is_large_context = is_context_overflow(file_content)
290
290
  upload_success = False
291
291
  # 读取原始文件内容
292
292
  with spinner.hidden():
293
- if need_upload_file and model.upload_files([filepath]):
293
+ if is_large_context and model.support_upload_files() and model.upload_files([filepath]):
294
294
  upload_success = True
295
295
 
296
296
 
@@ -340,19 +340,21 @@ def slow_edit(filepath: str, patch_content: str, spinner: Yaspin) -> Tuple[bool,
340
340
  """
341
341
 
342
342
  for _ in range(3):
343
- file_prompt = ""
344
- if not need_upload_file:
343
+ if is_large_context:
344
+ if upload_success:
345
+ response = model.chat_until_success(main_prompt)
346
+ else:
347
+ file_prompt = f"""
348
+ # 原始代码
349
+ {file_content}
350
+ """
351
+ response = model.chat_until_success(main_prompt + file_prompt)
352
+ else:
345
353
  file_prompt = f"""
346
354
  # 原始代码
347
355
  {file_content}
348
356
  """
349
-
350
357
  response = model.chat_until_success(main_prompt + file_prompt)
351
- else:
352
- if upload_success:
353
- response = model.chat_until_success(main_prompt)
354
- else:
355
- return False, "文件上传失败"
356
358
 
357
359
  # 解析差异化补丁
358
360
  diff_blocks = re.finditer(ot("DIFF")+r'\s*>{4,} SEARCH\n?(.*?)\n?={4,}\n?(.*?)\s*<{4,} REPLACE\n?'+ct("DIFF"),
@@ -30,6 +30,10 @@ class FileAnalyzerTool:
30
30
  "required": ["file_paths", "prompt"]
31
31
  }
32
32
 
33
+ @staticmethod
34
+ def check() -> bool:
35
+ return PlatformRegistry().get_thinking_platform().support_upload_files()
36
+
33
37
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
34
38
  """执行文件分析操作
35
39
 
@@ -62,8 +66,7 @@ class FileAnalyzerTool:
62
66
  }
63
67
 
64
68
  # 创建thinking平台实例
65
- platform_registry = PlatformRegistry.get_global_platform_registry()
66
- platform = platform_registry.get_thinking_platform()
69
+ platform = PlatformRegistry().get_thinking_platform()
67
70
 
68
71
  if not platform:
69
72
  return {
@@ -7,6 +7,7 @@ import tempfile
7
7
  from pathlib import Path
8
8
  from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple
9
9
 
10
+ from numpy import place
10
11
  import yaml
11
12
 
12
13
  from jarvis.jarvis_mcp import McpClient
@@ -18,7 +19,7 @@ from jarvis.jarvis_tools.base import Tool
18
19
  from jarvis.jarvis_utils.config import get_data_dir
19
20
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
20
21
  from jarvis.jarvis_utils.tag import ct, ot
21
- from jarvis.jarvis_utils.utils import init_env, is_context_overflow
22
+ from jarvis.jarvis_utils.utils import is_context_overflow
22
23
 
23
24
  tool_call_help = f"""
24
25
  <tool_system_guide>
@@ -648,6 +649,9 @@ class ToolRegistry(OutputHandlerProtocol):
648
649
  want = tool_call["want"]
649
650
  args["agent"] = agent
650
651
 
652
+ from jarvis.jarvis_agent import Agent
653
+ agent_instance: Agent = agent
654
+
651
655
  if isinstance(args, str):
652
656
  try:
653
657
  args = json.loads(args)
@@ -676,23 +680,25 @@ class ToolRegistry(OutputHandlerProtocol):
676
680
  tmp_file.flush()
677
681
 
678
682
  try:
679
- # 获取平台实例
680
- platform = PlatformRegistry().get_normal_platform()
681
- if platform and hasattr(platform, 'upload_files'):
682
- platform.set_suppress_output(False)
683
- # 尝试上传文件
684
- upload_success = platform.upload_files([output_file])
685
-
683
+ if agent_instance.model and agent_instance.model.support_upload_files():
684
+ summary = agent_instance.generate_summary()
685
+ agent_instance.clear_history()
686
+ upload_success = agent_instance.model.upload_files([output_file])
686
687
  if upload_success:
687
- # 使用上传的文件生成摘要
688
- prompt = f"该文件为工具执行结果,请阅读文件内容,并根据文件提取出以下信息:{want}"
689
- return f"""工具调用原始输出过长,以下是根据输出提出的信息:
690
-
691
- {platform.chat_until_success(prompt)}"""
692
- else:
693
- return self._truncate_output(output)
694
-
695
- # 如果都不支持,返回截断的输出
688
+ prompt = f"""
689
+ 以下是之前对话的关键信息总结:
690
+
691
+ <content>
692
+ {summary}
693
+ </content>
694
+
695
+ 上传的文件是以下工具执行结果:
696
+ {yaml.safe_dump({"name":name, "arguments":args, "want":want})}
697
+
698
+ 请根据以上信息,继续完成任务。
699
+ """
700
+ return prompt
701
+ # 使用上传的文件生成摘要
696
702
  return self._truncate_output(output)
697
703
  finally:
698
704
  # 清理临时文件
@@ -203,7 +203,7 @@ def get_max_big_content_size() -> int:
203
203
  返回:
204
204
  int: 最大大内容大小
205
205
  """
206
- return int(GLOBAL_CONFIG_DATA.get('JARVIS_MAX_BIG_CONTENT_SIZE', '1024000'))
206
+ return int(GLOBAL_CONFIG_DATA.get('JARVIS_MAX_BIG_CONTENT_SIZE', '160000'))
207
207
 
208
208
  def get_pretty_output() -> bool:
209
209
  """
@@ -119,9 +119,8 @@ def upload_methodology(platform: BasePlatform) -> bool:
119
119
  return False
120
120
 
121
121
  try:
122
- if hasattr(platform, 'upload_files'):
123
- return platform.upload_files([temp_file_path])
124
- return False
122
+ return platform.upload_files([temp_file_path])
123
+
125
124
  finally:
126
125
  if temp_file_path and os.path.exists(temp_file_path):
127
126
  try:
@@ -214,12 +213,11 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
214
213
  spinner.ok("✅")
215
214
 
216
215
  # 尝试上传文件
217
- if hasattr(platform, 'upload_files'):
218
- upload_success = platform.upload_files([temp_file_path])
219
-
220
- if upload_success:
221
- # 使用上传的文件生成摘要
222
- return platform.chat_until_success(base_prompt + f"""
216
+ upload_success = platform.upload_files([temp_file_path])
217
+
218
+ if upload_success:
219
+ # 使用上传的文件生成摘要
220
+ return platform.chat_until_success(base_prompt + f"""
223
221
  请根据已上传的方法论和可调用的工具文件内容,规划/总结出以下用户需求的执行步骤: {user_input}
224
222
 
225
223
  请按以下格式回复:
@@ -234,8 +232,8 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
234
232
  如果没有匹配的方法论,请输出:没有历史方法论可参考
235
233
  除以上要求外,不要输出任何内容
236
234
  """)
237
- else:
238
- return "没有历史方法论可参考"
235
+ else:
236
+ return "没有历史方法论可参考"
239
237
  # 如果内容不大或上传失败,直接使用chat_until_success
240
238
  return platform.chat_until_success(full_content)
241
239
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.188
3
+ Version: 0.1.189
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
@@ -238,7 +238,7 @@ OPENAI_API_BASE: https://api.openai.com/v1 # 可选,默认为官方API地址
238
238
  | `JARVIS_CONFIRM_BEFORE_APPLY_PATCH` | true | 应用补丁前是否需要确认 |
239
239
  | `JARVIS_MAX_TOOL_CALL_COUNT` | 20 | 最大连续工具调用次数,如果是0表示无限制 |
240
240
  | `JARVIS_AUTO_UPDATE` | true | 是否自动更新Jarvis(仅在以git仓库方式安装时有效) |
241
- | `JARVIS_MAX_BIG_CONTENT_SIZE` | 1024000 | 最大大内容大小 |
241
+ | `JARVIS_MAX_BIG_CONTENT_SIZE` | 160000 | 最大大内容大小 |
242
242
  | `JARVIS_PRETTY_OUTPUT` | false | 是否启用PrettyOutput |
243
243
  | `JARVIS_GIT_COMMIT_PROMPT` | "" | 自定义git提交信息生成提示模板 |
244
244
  | `JARVIS_PRINT_PROMPT` | false | 是否打印提示 |
@@ -1,5 +1,5 @@
1
- jarvis/__init__.py,sha256=KuZvt3HQLtENkv0s1NLND9zxkPs9blE1UCYGe9GmPNw,74
2
- jarvis/jarvis_agent/__init__.py,sha256=76gF2jieAQjP3M6YlDxx2dzaE2XD95nfAFRMySP-Azs,30654
1
+ jarvis/__init__.py,sha256=3RRAnaRmOaQpveMGk6AbLpN-Ndluqiwh0tdrx6SLMdg,74
2
+ jarvis/jarvis_agent/__init__.py,sha256=utqI92rkiqiVR2zk5N-IQe2CeMSl-sNiLU429dLoGVw,30487
3
3
  jarvis/jarvis_agent/builtin_input_handler.py,sha256=f4DaEHPakXcAbgykFP-tiOQP6fh_yGFlZx_h91_j2tQ,1529
4
4
  jarvis/jarvis_agent/file_input_handler.py,sha256=OfoYI5on6w5BDUUg4OadFcfWzMsUF70GNrlt9QyauvA,4181
5
5
  jarvis/jarvis_agent/jarvis.py,sha256=gOZfTwVlG-GZxPjgCoSiIcFsl4RwwfPA0CGUjE5J7oU,6249
@@ -9,7 +9,7 @@ jarvis/jarvis_agent/shell_input_handler.py,sha256=pi3AtPKrkKc6K9e99S1djKXQ_XrxtP
9
9
  jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  jarvis/jarvis_code_agent/code_agent.py,sha256=2TG_Hi_2mbiZHUcWnxYs4C30eYpgSedtIYZLs7BbyUk,15827
11
11
  jarvis/jarvis_code_agent/lint.py,sha256=TZlhNbeaoLzO9DzExjN5GAjrt66owd8lyQV56LTfkrs,4370
12
- jarvis/jarvis_code_analysis/code_review.py,sha256=SEK5NOGDWgMNX3zmRMWrIOtq3Xr8cKt_asG51U8h6SA,30219
12
+ jarvis/jarvis_code_analysis/code_review.py,sha256=45MPcXullg55w6E0Xhm2dDj6TGmkUxNNI2LJWexnTKQ,30123
13
13
  jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=cKQ_FOGy5TQgM-YkRCqORo-mUOZaPAJ9VDmZoFX58us,78
14
14
  jarvis/jarvis_code_analysis/checklists/c_cpp.py,sha256=SXPpYCNeCtU1PpKdKPiYDuOybfY9vaL0ejDn4imxDwA,1317
15
15
  jarvis/jarvis_code_analysis/checklists/csharp.py,sha256=vS-cu6RCGg5SyK9MJ3RE381gt3xYl-yea3Bj2UQEcwQ,2420
@@ -30,15 +30,15 @@ jarvis/jarvis_code_analysis/checklists/shell.py,sha256=IXQkWHwA-4GUQz3WUs7l6hEy7
30
30
  jarvis/jarvis_code_analysis/checklists/sql.py,sha256=ecKKT6wJAibn8R0NxGZDNlm4teYXvF3CAJvVk8mmX7w,2355
31
31
  jarvis/jarvis_code_analysis/checklists/swift.py,sha256=YcsYFxAitHqOtBZjG-RV9-KNM7X5lIcl6zlEI9XfmfM,2566
32
32
  jarvis/jarvis_code_analysis/checklists/web.py,sha256=-Pnj1FQTsGVZUQK7-4ptDsGd7a22Cs0585jRAPT2SdQ,3943
33
- jarvis/jarvis_data/config_schema.json,sha256=Jx9RPeVdkV7xgGro-5B8MFpVDLFmI80d_deLNMiTSgM,6398
33
+ jarvis/jarvis_data/config_schema.json,sha256=u_I8KawgwUltW-tVw3t37rLv4TqdBynZaNGhOFH2Zf8,6397
34
34
  jarvis/jarvis_data/huggingface.tar.gz,sha256=dWKnc_tvyx-I_ZkXo91O0b38KxDmLW1ZbmJ3E6fCl_k,1120205
35
- jarvis/jarvis_dev/main.py,sha256=b-Sa5i5T3lcazg4GIMnECsZ3L9zTs7QCg_voWE4K0I8,40642
35
+ jarvis/jarvis_dev/main.py,sha256=MG2DhDwXsOgCya558o7TJRMZlN3Diprk7UjEEVNdm6A,40630
36
36
  jarvis/jarvis_event/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- jarvis/jarvis_git_details/main.py,sha256=MfR7feVVQ7Eo9eZk-wO2bFypnA6uRrYUQn6iTeoF0Os,9007
38
+ jarvis/jarvis_git_details/main.py,sha256=4L60eVDBMv6RbocnVlzfOx7JZkHTzop3q7qui9d9LuU,9005
39
39
  jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
40
  jarvis/jarvis_git_squash/main.py,sha256=q8-r0TtVOaCqY_uYwnWAY76k8YCDd5se_feB6ZWKo9M,2278
41
- jarvis/jarvis_git_utils/git_commiter.py,sha256=S8fplYbw5Nl3tj-R6Qqn94MV1bJKX8VAJsBqUX5XAiY,12958
41
+ jarvis/jarvis_git_utils/git_commiter.py,sha256=BpJ8py2JMnp8jcukyM3vxGNWtjOLTIvgqYOx-5OhvZo,13037
42
42
  jarvis/jarvis_mcp/__init__.py,sha256=NF_vqRxaNyz8ColcpRh0bOkinV90YLAKHEN--jkP-B8,2114
43
43
  jarvis/jarvis_mcp/sse_mcp_client.py,sha256=QNA7HqFvLbvhNaFp3ZsXzs2Rm6_gHUMcpd4t4qAzymY,23485
44
44
  jarvis/jarvis_mcp/stdio_mcp_client.py,sha256=IEkas4ojP5J0TdVaUglvlEp61RyezBtuejv4lN3n1I4,11831
@@ -47,15 +47,15 @@ jarvis/jarvis_methodology/main.py,sha256=HhEArlKI5PCpGnBCwVrXMuDn2z84LgpgK7-aGSQ
47
47
  jarvis/jarvis_multi_agent/__init__.py,sha256=Xab5sFltJmX_9MoXqanmZs6FqKfUb2v_pG29Vk8ZXaw,4311
48
48
  jarvis/jarvis_multi_agent/main.py,sha256=KeGv8sdpSgTjW6VE4-tQ8BWDC_a0aE_4R3OqzPBd5N4,1646
49
49
  jarvis/jarvis_platform/__init__.py,sha256=0YnsUoM4JkIBOtImFdjfuDbrqQZT3dEaAwSJ62DrpCc,104
50
- jarvis/jarvis_platform/base.py,sha256=HbE7BVh8F5F38rr9K9281h6Q11XyWgDGzyPXe-e_Th0,7086
50
+ jarvis/jarvis_platform/base.py,sha256=C_50l5kc2P1OP8NH4JbaMZdY-aWOfhfuECoUlRCriU8,7029
51
51
  jarvis/jarvis_platform/human.py,sha256=xwaTZ1zdrAYZZFXxkbHvUdECwCGsic0kgAFUncUr45g,2567
52
- jarvis/jarvis_platform/kimi.py,sha256=b3EpnmHseZwrfCc8sMmvwLJ6Jg2FWf8ATItSDz5G3eQ,11978
52
+ jarvis/jarvis_platform/kimi.py,sha256=5-LUcvBoL_1Y8HZom9pkNFHO7ghstNCPEobVrVESOi4,12101
53
53
  jarvis/jarvis_platform/openai.py,sha256=VyX3bR1rGxrJdWOtUBf8PgSL9n06KaNbOewL1urzOnk,4741
54
54
  jarvis/jarvis_platform/registry.py,sha256=3djxE8AB4gwrdAOvRSL0612Rt_CcsaZhzZ0_oXHu6xk,7820
55
- jarvis/jarvis_platform/tongyi.py,sha256=NhE8ssvTI_XoDkXhaGtrUJG6q6-0OApWvh8d7wuFZXg,20944
56
- jarvis/jarvis_platform/yuanbao.py,sha256=FDi-D9Jnw_MiwI0skPNMYz874o6GhWhdNRdZg-ECoUA,20632
55
+ jarvis/jarvis_platform/tongyi.py,sha256=1cecb2GofJ_7J3xEj_fBj4Ns7XuGIn5CpCi_DFmiP4s,21063
56
+ jarvis/jarvis_platform/yuanbao.py,sha256=yOj5T3lo45ULrFkwHXdAsiLhfv141V0sPQplHGeLKNg,20751
57
57
  jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
- jarvis/jarvis_platform_manager/main.py,sha256=OXWj18SqiV0Gl75YT6D9wspCCB4Nes04EY-ShI9kbpU,25677
58
+ jarvis/jarvis_platform_manager/main.py,sha256=7XfiP19Gv88sFkS__v83a-JTI-VUuyH3lWLr4_jTq1w,25863
59
59
  jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
60
  jarvis/jarvis_smart_shell/main.py,sha256=k59o5UD7merbsPhJQzae95ThTmZY2EcNHB3Ov6kb0PA,5291
61
61
  jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -65,15 +65,15 @@ jarvis/jarvis_tools/chdir.py,sha256=DNKVFrWqu6t_sZ2ipv99s6802QR4cSGlqKlmaI--arE,
65
65
  jarvis/jarvis_tools/code_plan.py,sha256=gWR0lzY62x2PxWKoMRBqW6jq7zQuO8vhpjC4TcHSYjk,7685
66
66
  jarvis/jarvis_tools/create_code_agent.py,sha256=-nHfo5O5pDIG5IX3w1ClQafGvGcdI2_w75-KGrD-gUQ,3458
67
67
  jarvis/jarvis_tools/create_sub_agent.py,sha256=lyFrrg4V0yXULmU3vldwGp_euZjwZzJcRU6mJ20zejY,3023
68
- jarvis/jarvis_tools/edit_file.py,sha256=lI6x2Vf7wrF-WdZN9qsmuiSm8jAUSyGSTk1mlGXq9FQ,18369
68
+ jarvis/jarvis_tools/edit_file.py,sha256=s8HqG8qHDrYjCwIioeBpGvw7Aw-iEEZoUyRJFqdjcQA,18453
69
69
  jarvis/jarvis_tools/execute_script.py,sha256=IA1SkcnwBB9PKG2voBNx5N9GXL303OC7OOtdqRfqWOk,6428
70
- jarvis/jarvis_tools/file_analyzer.py,sha256=7ILHkUFm8pPZn1y_s4uT0kaWHP-EmlHnpkovDdA1yRE,4872
70
+ jarvis/jarvis_tools/file_analyzer.py,sha256=UuQmti-eBocJB6ivMINmOvSuXxBxOqmbQ3RsQlyueWs,4918
71
71
  jarvis/jarvis_tools/file_operation.py,sha256=WloC1-oPJLwgICu4WBc9f7XA8N_Ggl73QQ5CxM2XTlE,9464
72
72
  jarvis/jarvis_tools/generate_new_tool.py,sha256=dLfOliIUm0ovLrHcZAhKm7lqhxwACv8mnGxxGtLJ--o,5960
73
73
  jarvis/jarvis_tools/methodology.py,sha256=m7cQmVhhQpUUl_uYTVvcW0JBovQLx5pWTXh_8K77HsU,5237
74
74
  jarvis/jarvis_tools/read_code.py,sha256=pL2SwZDsJbJMXo4stW96quFsLgbtPVIAW-h4sDKsLtM,6274
75
75
  jarvis/jarvis_tools/read_webpage.py,sha256=PFAYuKjay9j6phWzyuZ99ZfNaHJljmRWAgS0bsvbcvE,2219
76
- jarvis/jarvis_tools/registry.py,sha256=qdA0fgWeh_UG-_Rt5COnHTcKmOsYBiIU69uX4cLvfWI,25199
76
+ jarvis/jarvis_tools/registry.py,sha256=kSl41tvwdiHaE3nwR9BI94GibjsKWczogZ76y0nFycw,25058
77
77
  jarvis/jarvis_tools/rewrite_file.py,sha256=3V2l7kG5DG9iRimBce-1qCRuJPL0QM32SBTzOl2zCqM,7004
78
78
  jarvis/jarvis_tools/search_web.py,sha256=rzxrCOTEo-MmLQrKI4k-AbfidUfJUeCPK4f5ZJy48G8,952
79
79
  jarvis/jarvis_tools/virtual_tty.py,sha256=8E_n-eC-RRPTqYx6BI5Q2RnorY8dbhKFBfAjIiRQROA,16397
@@ -81,19 +81,19 @@ jarvis/jarvis_tools/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
81
81
  jarvis/jarvis_tools/cli/main.py,sha256=3UuU9tk5cQAS0rfNPXgdtnAd5uDB7v0Exo0_I9sJHRE,6355
82
82
  jarvis/jarvis_utils/__init__.py,sha256=x5lbQRH1uOulmWr1IEqNMLXNmDHbqQQot7d1uhKFg4M,851
83
83
  jarvis/jarvis_utils/builtin_replace_map.py,sha256=n4gBUwAJDABUhQu9qIiIHWNfPk_T7chfNk5ygCiOPtE,2931
84
- jarvis/jarvis_utils/config.py,sha256=2STTlI2Acy5TMHhLEZaz44MDsY4W9qSThI6tbwg7iSg,7105
84
+ jarvis/jarvis_utils/config.py,sha256=Z7pZsSYXJkc2RzUhJ-_VvQA3xOLo6LEo4nEE1ftyQY8,7104
85
85
  jarvis/jarvis_utils/embedding.py,sha256=J8YAqIEj16TJIPEG24uvUlPHeN-5zq0JW_hbNLizQug,3832
86
86
  jarvis/jarvis_utils/file_processors.py,sha256=G5kQI7vCGIDnjgAB5J1dYIR102u6WUv3IhcWFfDh_gs,2977
87
87
  jarvis/jarvis_utils/git_utils.py,sha256=k0rrMAbKwnD7hztmtegxtFFiCzyID4p2oHKTycE2Q-4,15070
88
88
  jarvis/jarvis_utils/globals.py,sha256=6JWtB1XoD-wEFiMzZNA790ixlZ_OsJEYUM_B8EwkOE8,2277
89
89
  jarvis/jarvis_utils/input.py,sha256=FkLW7MXL8awQUghFLQnW1r5F1wV8K3EZeVPwHFRHJTo,7458
90
- jarvis/jarvis_utils/methodology.py,sha256=A8pE8ZqNHvGKaDO4TFtg7Oz-hAXPBcQfhmSPWMr6vdg,8629
90
+ jarvis/jarvis_utils/methodology.py,sha256=6vf__ahwJZ2I62mWGAvh2C-G6pq930Dh_EkrY1VpduQ,8485
91
91
  jarvis/jarvis_utils/output.py,sha256=QboL42GtG_dnvd1O64sl8o72mEBhXNRADPXQMXgDE7Q,9661
92
92
  jarvis/jarvis_utils/tag.py,sha256=YJHmuedLb7_AiqvKQetHr4R1FxyzIh7HN0RRkWMmYbU,429
93
93
  jarvis/jarvis_utils/utils.py,sha256=dTFIN6EV48BuC4VOyvcVcj4P0tsWysc9ennbMRhLJjk,10960
94
- jarvis_ai_assistant-0.1.188.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
95
- jarvis_ai_assistant-0.1.188.dist-info/METADATA,sha256=rZMrwx4kWz3yKD4jlL5fqJw8L-zMYb8ZEhv3gIlmZMc,15923
96
- jarvis_ai_assistant-0.1.188.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
97
- jarvis_ai_assistant-0.1.188.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
98
- jarvis_ai_assistant-0.1.188.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
99
- jarvis_ai_assistant-0.1.188.dist-info/RECORD,,
94
+ jarvis_ai_assistant-0.1.189.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
95
+ jarvis_ai_assistant-0.1.189.dist-info/METADATA,sha256=5e88_48MijaBca9j4CP0kRRaAwtt6H6WSJOf0BsrYtQ,15922
96
+ jarvis_ai_assistant-0.1.189.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
97
+ jarvis_ai_assistant-0.1.189.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
98
+ jarvis_ai_assistant-0.1.189.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
99
+ jarvis_ai_assistant-0.1.189.dist-info/RECORD,,