jarvis-ai-assistant 0.1.178__py3-none-any.whl → 0.1.180__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (66) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +130 -79
  3. jarvis/jarvis_agent/builtin_input_handler.py +1 -1
  4. jarvis/jarvis_agent/jarvis.py +9 -13
  5. jarvis/jarvis_agent/main.py +4 -2
  6. jarvis/jarvis_code_agent/code_agent.py +34 -23
  7. jarvis/jarvis_code_agent/lint.py +164 -0
  8. jarvis/jarvis_code_analysis/checklists/loader.py +6 -20
  9. jarvis/jarvis_code_analysis/code_review.py +8 -6
  10. jarvis/jarvis_data/config_schema.json +260 -0
  11. jarvis/jarvis_dev/main.py +1 -8
  12. jarvis/jarvis_git_details/main.py +1 -1
  13. jarvis/jarvis_git_squash/main.py +5 -3
  14. jarvis/jarvis_git_utils/git_commiter.py +25 -24
  15. jarvis/jarvis_mcp/sse_mcp_client.py +6 -4
  16. jarvis/jarvis_mcp/stdio_mcp_client.py +5 -4
  17. jarvis/jarvis_mcp/streamable_mcp_client.py +404 -0
  18. jarvis/jarvis_methodology/main.py +10 -9
  19. jarvis/jarvis_multi_agent/main.py +3 -1
  20. jarvis/jarvis_platform/base.py +14 -8
  21. jarvis/jarvis_platform/human.py +3 -1
  22. jarvis/jarvis_platform/kimi.py +8 -27
  23. jarvis/jarvis_platform/openai.py +4 -16
  24. jarvis/jarvis_platform/registry.py +6 -2
  25. jarvis/jarvis_platform/yuanbao.py +9 -29
  26. jarvis/jarvis_platform_manager/main.py +11 -9
  27. jarvis/jarvis_smart_shell/main.py +7 -3
  28. jarvis/jarvis_tools/ask_codebase.py +4 -3
  29. jarvis/jarvis_tools/ask_user.py +2 -1
  30. jarvis/jarvis_tools/base.py +3 -1
  31. jarvis/jarvis_tools/chdir.py +2 -1
  32. jarvis/jarvis_tools/cli/main.py +1 -0
  33. jarvis/jarvis_tools/code_plan.py +5 -3
  34. jarvis/jarvis_tools/create_code_agent.py +5 -2
  35. jarvis/jarvis_tools/create_sub_agent.py +1 -3
  36. jarvis/jarvis_tools/edit_file.py +4 -4
  37. jarvis/jarvis_tools/execute_script.py +1 -1
  38. jarvis/jarvis_tools/file_analyzer.py +5 -3
  39. jarvis/jarvis_tools/file_operation.py +4 -7
  40. jarvis/jarvis_tools/find_methodology.py +4 -2
  41. jarvis/jarvis_tools/generate_new_tool.py +2 -1
  42. jarvis/jarvis_tools/methodology.py +3 -4
  43. jarvis/jarvis_tools/read_code.py +2 -1
  44. jarvis/jarvis_tools/read_webpage.py +3 -1
  45. jarvis/jarvis_tools/registry.py +60 -45
  46. jarvis/jarvis_tools/rewrite_file.py +2 -1
  47. jarvis/jarvis_tools/search_web.py +1 -0
  48. jarvis/jarvis_tools/virtual_tty.py +5 -4
  49. jarvis/jarvis_utils/__init__.py +2 -0
  50. jarvis/jarvis_utils/builtin_replace_map.py +1 -1
  51. jarvis/jarvis_utils/config.py +88 -17
  52. jarvis/jarvis_utils/embedding.py +4 -3
  53. jarvis/jarvis_utils/file_processors.py +1 -0
  54. jarvis/jarvis_utils/git_utils.py +83 -40
  55. jarvis/jarvis_utils/globals.py +4 -2
  56. jarvis/jarvis_utils/input.py +14 -7
  57. jarvis/jarvis_utils/methodology.py +6 -4
  58. jarvis/jarvis_utils/output.py +10 -6
  59. jarvis/jarvis_utils/utils.py +140 -24
  60. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/METADATA +66 -59
  61. jarvis_ai_assistant-0.1.180.dist-info/RECORD +99 -0
  62. jarvis_ai_assistant-0.1.178.dist-info/RECORD +0 -96
  63. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/WHEEL +0 -0
  64. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/entry_points.txt +0 -0
  65. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/licenses/LICENSE +0 -0
  66. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/top_level.txt +0 -0
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
2
+ import fcntl
3
3
  import os
4
- import time
5
4
  import pty
6
- import fcntl
7
- import signal
8
5
  import select
6
+ import signal
7
+ import time
8
+ from typing import Any, Dict
9
+
9
10
 
10
11
  class VirtualTTYTool:
11
12
  name = "virtual_tty"
@@ -13,8 +13,10 @@ Jarvis工具模块
13
13
  - utils: 通用工具
14
14
  """
15
15
  import os
16
+
16
17
  import colorama
17
18
  from rich.traceback import install as install_rich_traceback
19
+
18
20
  # 从新模块重新导出
19
21
  # 这些导入是项目功能所必需的,可能会被动态使用
20
22
  # 初始化colorama以支持跨平台的彩色文本
@@ -5,7 +5,7 @@
5
5
  格式: {"标记名": {"template": "替换模板", "description": "描述信息"}}
6
6
  """
7
7
 
8
- from jarvis.jarvis_utils.tag import ot, ct
8
+ from jarvis.jarvis_utils.tag import ct, ot
9
9
 
10
10
  BUILTIN_REPLACE_MAP = {
11
11
  "CodeBase": {
@@ -1,14 +1,46 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import os
3
3
  from functools import lru_cache
4
+
5
+ from typing import Any, Dict, List
6
+
7
+
4
8
  import yaml
9
+
10
+
5
11
  from jarvis.jarvis_utils.builtin_replace_map import BUILTIN_REPLACE_MAP
12
+
13
+
14
+ # 全局环境变量存储
15
+
16
+ GLOBAL_CONFIG_DATA: Dict[str, Any] = {}
17
+
18
+
19
+ def set_global_env_data(env_data: Dict[str, Any]) -> None:
20
+ """设置全局环境变量数据"""
21
+ global GLOBAL_CONFIG_DATA
22
+ GLOBAL_CONFIG_DATA = env_data
23
+
24
+ def set_config(key: str, value: Any) -> None:
25
+ """设置配置"""
26
+ GLOBAL_CONFIG_DATA[key] = value
27
+
28
+
6
29
  """配置管理模块。
7
30
 
8
31
  该模块提供了获取Jarvis系统各种配置设置的函数。
9
32
  所有配置都从环境变量中读取,带有回退默认值。
10
33
  """
11
34
 
35
+ def get_git_commit_prompt() -> str:
36
+ """
37
+ 获取Git提交提示模板
38
+
39
+ 返回:
40
+ str: Git提交信息生成提示模板,如果未配置则返回空字符串
41
+ """
42
+ return GLOBAL_CONFIG_DATA.get("JARVIS_GIT_COMMIT_PROMPT", "")
43
+
12
44
  # 输出窗口预留大小
13
45
  INPUT_WINDOW_REVERSE_SIZE = 2048
14
46
 
@@ -17,16 +49,27 @@ def get_replace_map() -> dict:
17
49
  """
18
50
  获取替换映射表。
19
51
 
20
- 从数据目录下的replace_map.yaml文件中读取替换映射表,
52
+ 优先使用GLOBAL_CONFIG_DATA['JARVIS_REPLACE_MAP']的配置,
53
+ 如果没有则从数据目录下的replace_map.yaml文件中读取替换映射表,
21
54
  如果文件不存在则返回内置替换映射表。
22
55
 
23
56
  返回:
24
57
  dict: 合并后的替换映射表字典(内置+文件中的映射表)
25
58
  """
59
+ if 'JARVIS_REPLACE_MAP' in GLOBAL_CONFIG_DATA:
60
+ return {**BUILTIN_REPLACE_MAP, **GLOBAL_CONFIG_DATA['JARVIS_REPLACE_MAP']}
61
+
26
62
  replace_map_path = os.path.join(get_data_dir(), 'replace_map.yaml')
27
63
  if not os.path.exists(replace_map_path):
28
64
  return BUILTIN_REPLACE_MAP.copy()
29
65
 
66
+ from jarvis.jarvis_utils.output import PrettyOutput, OutputType
67
+ PrettyOutput.print(
68
+ "警告:使用replace_map.yaml进行配置的方式已被弃用,将在未来版本中移除。"
69
+ "请迁移到使用GLOBAL_CONFIG_DATA中的JARVIS_REPLACE_MAP配置。",
70
+ output_type=OutputType.WARNING
71
+ )
72
+
30
73
  with open(replace_map_path, 'r', encoding='utf-8', errors='ignore') as file:
31
74
  file_map = yaml.safe_load(file) or {}
32
75
  return {**BUILTIN_REPLACE_MAP, **file_map}
@@ -38,7 +81,7 @@ def get_max_token_count() -> int:
38
81
  返回:
39
82
  int: 模型能处理的最大token数量。
40
83
  """
41
- return int(os.getenv('JARVIS_MAX_TOKEN_COUNT', '960000'))
84
+ return int(GLOBAL_CONFIG_DATA.get('JARVIS_MAX_TOKEN_COUNT', '960000'))
42
85
 
43
86
  def get_max_input_token_count() -> int:
44
87
  """
@@ -47,7 +90,7 @@ def get_max_input_token_count() -> int:
47
90
  返回:
48
91
  int: 模型能处理的最大输入token数量。
49
92
  """
50
- return int(os.getenv('JARVIS_MAX_INPUT_TOKEN_COUNT', '32000'))
93
+ return int(GLOBAL_CONFIG_DATA.get('JARVIS_MAX_INPUT_TOKEN_COUNT', '32000'))
51
94
 
52
95
 
53
96
  def is_auto_complete() -> bool:
@@ -57,7 +100,7 @@ def is_auto_complete() -> bool:
57
100
  返回:
58
101
  bool: 如果启用了自动补全则返回True,默认为False
59
102
  """
60
- return os.getenv('JARVIS_AUTO_COMPLETE', 'false') == 'true'
103
+ return GLOBAL_CONFIG_DATA.get('JARVIS_AUTO_COMPLETE', 'false') == 'true'
61
104
 
62
105
 
63
106
  def get_shell_name() -> str:
@@ -67,7 +110,7 @@ def get_shell_name() -> str:
67
110
  返回:
68
111
  str: Shell名称(例如bash, zsh),默认为bash
69
112
  """
70
- shell_path = os.getenv('SHELL', '/bin/bash')
113
+ shell_path = GLOBAL_CONFIG_DATA.get('SHELL', '/bin/bash')
71
114
  return os.path.basename(shell_path)
72
115
  def get_normal_platform_name() -> str:
73
116
  """
@@ -76,7 +119,7 @@ def get_normal_platform_name() -> str:
76
119
  返回:
77
120
  str: 平台名称,默认为'yuanbao'
78
121
  """
79
- return os.getenv('JARVIS_PLATFORM', 'yuanbao')
122
+ return GLOBAL_CONFIG_DATA.get('JARVIS_PLATFORM', 'yuanbao')
80
123
  def get_normal_model_name() -> str:
81
124
  """
82
125
  获取正常操作的模型名称。
@@ -84,7 +127,7 @@ def get_normal_model_name() -> str:
84
127
  返回:
85
128
  str: 模型名称,默认为'deep_seek'
86
129
  """
87
- return os.getenv('JARVIS_MODEL', 'deep_seek_v3')
130
+ return GLOBAL_CONFIG_DATA.get('JARVIS_MODEL', 'deep_seek_v3')
88
131
 
89
132
 
90
133
  def get_thinking_platform_name() -> str:
@@ -94,7 +137,7 @@ def get_thinking_platform_name() -> str:
94
137
  返回:
95
138
  str: 平台名称,默认为'yuanbao'
96
139
  """
97
- return os.getenv('JARVIS_THINKING_PLATFORM', os.getenv('JARVIS_PLATFORM', 'yuanbao'))
140
+ return GLOBAL_CONFIG_DATA.get('JARVIS_THINKING_PLATFORM', GLOBAL_CONFIG_DATA.get('JARVIS_PLATFORM', 'yuanbao'))
98
141
  def get_thinking_model_name() -> str:
99
142
  """
100
143
  获取思考操作的模型名称。
@@ -102,7 +145,7 @@ def get_thinking_model_name() -> str:
102
145
  返回:
103
146
  str: 模型名称,默认为'deep_seek'
104
147
  """
105
- return os.getenv('JARVIS_THINKING_MODEL', os.getenv('JARVIS_MODEL', 'deep_seek'))
148
+ return GLOBAL_CONFIG_DATA.get('JARVIS_THINKING_MODEL', GLOBAL_CONFIG_DATA.get('JARVIS_MODEL', 'deep_seek'))
106
149
 
107
150
  def is_execute_tool_confirm() -> bool:
108
151
  """
@@ -111,7 +154,7 @@ def is_execute_tool_confirm() -> bool:
111
154
  返回:
112
155
  bool: 如果需要确认则返回True,默认为False
113
156
  """
114
- return os.getenv('JARVIS_EXECUTE_TOOL_CONFIRM', 'false') == 'true'
157
+ return GLOBAL_CONFIG_DATA.get('JARVIS_EXECUTE_TOOL_CONFIRM', 'false') == 'true'
115
158
  def is_confirm_before_apply_patch() -> bool:
116
159
  """
117
160
  检查应用补丁前是否需要确认。
@@ -119,7 +162,7 @@ def is_confirm_before_apply_patch() -> bool:
119
162
  返回:
120
163
  bool: 如果需要确认则返回True,默认为False
121
164
  """
122
- return os.getenv('JARVIS_CONFIRM_BEFORE_APPLY_PATCH', 'true') == 'true'
165
+ return GLOBAL_CONFIG_DATA.get('JARVIS_CONFIRM_BEFORE_APPLY_PATCH', 'true') == 'true'
123
166
 
124
167
  def get_max_tool_call_count() -> int:
125
168
  """
@@ -128,7 +171,7 @@ def get_max_tool_call_count() -> int:
128
171
  返回:
129
172
  int: 最大连续工具调用次数,默认为20
130
173
  """
131
- return int(os.getenv('JARVIS_MAX_TOOL_CALL_COUNT', '20'))
174
+ return int(GLOBAL_CONFIG_DATA.get('JARVIS_MAX_TOOL_CALL_COUNT', '20'))
132
175
 
133
176
 
134
177
  def get_data_dir() -> str:
@@ -139,7 +182,7 @@ def get_data_dir() -> str:
139
182
  str: 数据目录路径,优先从JARVIS_DATA_PATH环境变量获取,
140
183
  如果未设置或为空,则使用~/.jarvis作为默认值
141
184
  """
142
- data_path = os.getenv('JARVIS_DATA_PATH', '').strip()
185
+ data_path = GLOBAL_CONFIG_DATA.get('JARVIS_DATA_PATH', '').strip()
143
186
  if not data_path:
144
187
  return os.path.expanduser('~/.jarvis')
145
188
  return data_path
@@ -151,7 +194,7 @@ def get_auto_update() -> bool:
151
194
  返回:
152
195
  bool: 如果需要自动更新则返回True,默认为True
153
196
  """
154
- return os.getenv('JARVIS_AUTO_UPDATE', 'true') == 'true'
197
+ return GLOBAL_CONFIG_DATA.get('JARVIS_AUTO_UPDATE', 'true') == 'true'
155
198
 
156
199
  def get_max_big_content_size() -> int:
157
200
  """
@@ -160,7 +203,7 @@ def get_max_big_content_size() -> int:
160
203
  返回:
161
204
  int: 最大大内容大小
162
205
  """
163
- return int(os.getenv('JARVIS_MAX_BIG_CONTENT_SIZE', '1024000'))
206
+ return int(GLOBAL_CONFIG_DATA.get('JARVIS_MAX_BIG_CONTENT_SIZE', '1024000'))
164
207
 
165
208
  def get_pretty_output() -> bool:
166
209
  """
@@ -169,7 +212,7 @@ def get_pretty_output() -> bool:
169
212
  返回:
170
213
  bool: 如果启用PrettyOutput则返回True,默认为True
171
214
  """
172
- return os.getenv('JARVIS_PRETTY_OUTPUT', 'false') == 'true'
215
+ return GLOBAL_CONFIG_DATA.get('JARVIS_PRETTY_OUTPUT', 'false') == 'true'
173
216
 
174
217
  def is_use_methodology() -> bool:
175
218
  """
@@ -178,4 +221,32 @@ def is_use_methodology() -> bool:
178
221
  返回:
179
222
  bool: 如果启用方法论则返回True,默认为True
180
223
  """
181
- return os.getenv('JARVIS_USE_METHODOLOGY', 'true') == 'true'
224
+ return GLOBAL_CONFIG_DATA.get('JARVIS_USE_METHODOLOGY', 'false') == 'true'
225
+
226
+ def is_use_analysis() -> bool:
227
+ """
228
+ 获取是否启用任务分析。
229
+
230
+ 返回:
231
+ bool: 如果启用任务分析则返回True,默认为True
232
+ """
233
+ return GLOBAL_CONFIG_DATA.get('JARVIS_USE_ANALYSIS', 'false') == 'true'
234
+
235
+ def is_print_prompt() -> bool:
236
+ """
237
+ 获取是否打印提示。
238
+
239
+ 返回:
240
+ bool: 如果打印提示则返回True,默认为True
241
+ """
242
+ return GLOBAL_CONFIG_DATA.get('JARVIS_PRINT_PROMPT', 'false') == 'true'
243
+
244
+
245
+ def get_mcp_config() -> List[Dict[str, Any]]:
246
+ """
247
+ 获取MCP配置列表。
248
+
249
+ 返回:
250
+ List[Dict[str, Any]]: MCP配置项列表,如果未配置则返回空列表
251
+ """
252
+ return GLOBAL_CONFIG_DATA.get("JARVIS_MCP", [])
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
+ import functools
2
3
  import os
3
- from transformers import AutoTokenizer
4
4
  from typing import List
5
- import functools
6
5
 
7
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
6
+ from transformers import AutoTokenizer
7
+
8
8
  from jarvis.jarvis_utils.config import get_data_dir
9
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
10
 
10
11
  # 全局缓存,避免重复加载模型
11
12
  _global_tokenizers = {}
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import unicodedata
3
3
 
4
+
4
5
  class FileProcessor:
5
6
  """Base class for file processor"""
6
7
  @staticmethod
@@ -12,10 +12,14 @@ Git工具模块
12
12
  import os
13
13
  import re
14
14
  import subprocess
15
- from typing import List, Tuple, Dict
16
- from jarvis.jarvis_utils.config import get_auto_update, is_confirm_before_apply_patch
17
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
15
+ from typing import Dict, List, Tuple
16
+
17
+ from jarvis.jarvis_utils.config import (get_auto_update,
18
+ is_confirm_before_apply_patch)
19
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
18
20
  from jarvis.jarvis_utils.utils import user_confirm
21
+
22
+
19
23
  def find_git_root(start_dir: str = ".") -> str:
20
24
  """
21
25
  切换到给定路径的Git根目录,如果不是Git仓库则初始化。
@@ -101,49 +105,41 @@ def get_commits_between(start_hash: str, end_hash: str) -> List[Tuple[str, str]]
101
105
 
102
106
 
103
107
  def get_diff() -> str:
104
- """使用git获取暂存区差异"""
105
- import subprocess
106
-
107
- # 初始化状态
108
- need_reset = False
108
+ """使用git获取工作区差异,包括修改和新增的文件内容
109
109
 
110
+ 返回:
111
+ str: 差异内容或错误信息
112
+ """
110
113
  try:
111
- # 暂存所有修改
112
- subprocess.run(['git', 'add', '.'], check=True)
113
- need_reset = True
114
+ # 暂存新增文件
115
+ subprocess.run(['git', 'add', '-N', '.'], check=True)
114
116
 
115
- # 获取差异
117
+ # 获取所有差异(包括新增文件)
116
118
  result = subprocess.run(
117
- ['git', 'diff', '--cached'],
119
+ ['git', 'diff', 'HEAD'],
118
120
  capture_output=True,
119
121
  text=False,
120
122
  check=True
121
123
  )
122
124
 
123
- # 解码输出
124
- try:
125
- ret = result.stdout.decode('utf-8')
126
- except UnicodeDecodeError:
127
- ret = result.stdout.decode('utf-8', errors='replace')
128
-
129
125
  # 重置暂存区
130
- subprocess.run(['git', "reset", "--mixed"], check=False)
131
- return ret
126
+ subprocess.run(['git', 'reset'], check=True)
132
127
 
128
+ try:
129
+ return result.stdout.decode('utf-8')
130
+ except UnicodeDecodeError:
131
+ return result.stdout.decode('utf-8', errors='replace')
132
+
133
133
  except subprocess.CalledProcessError as e:
134
- if need_reset:
135
- subprocess.run(['git', "reset", "--mixed"], check=False)
136
134
  return f"获取差异失败: {str(e)}"
137
135
  except Exception as e:
138
- if need_reset:
139
- subprocess.run(['git', "reset", "--mixed"], check=False)
140
136
  return f"发生意外错误: {str(e)}"
141
137
 
142
138
 
143
139
 
144
140
 
145
141
 
146
- def revert_file(filepath: str):
142
+ def revert_file(filepath: str) -> None:
147
143
  """增强版git恢复,处理新文件"""
148
144
  import subprocess
149
145
  try:
@@ -166,7 +162,7 @@ def revert_file(filepath: str):
166
162
  # 修改后的恢复函数
167
163
 
168
164
 
169
- def revert_change():
165
+ def revert_change() -> None:
170
166
  """恢复所有未提交的修改到HEAD状态"""
171
167
  import subprocess
172
168
  try:
@@ -180,7 +176,7 @@ def revert_change():
180
176
  subprocess.run(['git', 'reset', '--hard', 'HEAD'], check=True)
181
177
  subprocess.run(['git', 'clean', '-fd'], check=True)
182
178
  except subprocess.CalledProcessError as e:
183
- return f"恢复更改失败: {str(e)}"
179
+ PrettyOutput.print(f"恢复更改失败: {str(e)}", OutputType.ERROR)
184
180
 
185
181
 
186
182
  def handle_commit_workflow() -> bool:
@@ -196,15 +192,15 @@ def handle_commit_workflow() -> bool:
196
192
  import subprocess
197
193
  try:
198
194
  # 获取当前分支的提交总数
199
- commit_count = subprocess.run(
195
+ commit_result = subprocess.run(
200
196
  ['git', 'rev-list', '--count', 'HEAD'],
201
197
  capture_output=True,
202
198
  text=True
203
199
  )
204
- if commit_count.returncode != 0:
200
+ if commit_result.returncode != 0:
205
201
  return False
206
202
 
207
- commit_count = int(commit_count.stdout.strip())
203
+ commit_count = int(commit_result.stdout.strip())
208
204
 
209
205
  # 暂存所有修改
210
206
  subprocess.run(['git', 'add', '.'], check=True)
@@ -317,15 +313,28 @@ def check_and_update_git_repo(repo_path: str) -> bool:
317
313
  if has_uncommitted_changes():
318
314
  return False
319
315
 
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)
316
+ # 获取远程tag更新
317
+ subprocess.run(["git", "fetch", "--tags"], cwd=git_root, check=True)
318
+ # 获取最新本地tag
319
+ local_tag_result = subprocess.run(["git", "describe", "--tags", "--abbrev=0"],
320
+ cwd=git_root, capture_output=True, text=True)
321
+ # 获取最新远程tag
322
+ remote_tag_result = subprocess.run(
323
+ ["git", "ls-remote", "--tags", "--refs", "origin"],
324
+ cwd=git_root, capture_output=True, text=True
325
+ )
326
+ if remote_tag_result.returncode == 0:
327
+ # 提取最新的tag名称
328
+ tags = [ref.split("/")[-1] for ref in remote_tag_result.stdout.splitlines()]
329
+ tags = sorted(tags, key=lambda x: [int(i) if i.isdigit() else i for i in re.split(r'([0-9]+)', x)])
330
+ remote_tag = tags[-1] if tags else ""
331
+ remote_tag_result.stdout = remote_tag
332
+
333
+ if (local_tag_result.returncode == 0 and remote_tag_result.returncode == 0 and
334
+ local_tag_result.stdout.strip() != remote_tag_result.stdout.strip()):
335
+ PrettyOutput.print(f"检测到新版本tag {remote_tag_result.stdout.strip()},正在更新Jarvis...", OutputType.INFO)
336
+ subprocess.run(["git", "checkout", remote_tag_result.stdout.strip()], cwd=git_root, check=True)
337
+ PrettyOutput.print(f"Jarvis已更新到tag {remote_tag_result.stdout.strip()}", OutputType.SUCCESS)
329
338
  return True
330
339
  return False
331
340
  except Exception as e:
@@ -333,3 +342,37 @@ def check_and_update_git_repo(repo_path: str) -> bool:
333
342
  return False
334
343
  finally:
335
344
  os.chdir(curr_dir)
345
+
346
+
347
+ def get_diff_file_list() -> List[str]:
348
+ """获取HEAD到当前变更的文件列表,包括修改和新增的文件
349
+
350
+ 返回:
351
+ List[str]: 修改和新增的文件路径列表
352
+ """
353
+ try:
354
+ # 暂存新增文件
355
+ subprocess.run(['git', 'add', '-N', '.'], check=True)
356
+
357
+ # 获取所有差异文件(包括新增文件)
358
+ result = subprocess.run(
359
+ ['git', 'diff', '--name-only', 'HEAD'],
360
+ capture_output=True,
361
+ text=True
362
+ )
363
+
364
+ # 重置暂存区
365
+ subprocess.run(['git', 'reset'], check=True)
366
+
367
+ if result.returncode != 0:
368
+ PrettyOutput.print(f"获取差异文件列表失败: {result.stderr}", OutputType.ERROR)
369
+ return []
370
+
371
+ return [f for f in result.stdout.splitlines() if f]
372
+
373
+ except subprocess.CalledProcessError as e:
374
+ PrettyOutput.print(f"获取差异文件列表失败: {str(e)}", OutputType.ERROR)
375
+ return []
376
+ except Exception as e:
377
+ PrettyOutput.print(f"获取差异文件列表异常: {str(e)}", OutputType.ERROR)
378
+ return []
@@ -7,11 +7,13 @@
7
7
  - 带有自定义主题的控制台配置
8
8
  - 环境初始化
9
9
  """
10
- from typing import Any, Set, Dict
11
- import colorama
12
10
  import os
11
+ from typing import Any, Dict, Set
12
+
13
+ import colorama
13
14
  from rich.console import Console
14
15
  from rich.theme import Theme
16
+
15
17
  # 初始化colorama以支持跨平台的彩色文本
16
18
  colorama.init()
17
19
  # 禁用tokenizers并行以避免多进程问题
@@ -8,17 +8,21 @@
8
8
  - 带有模糊匹配的文件路径补全
9
9
  - 用于输入控制的自定义键绑定
10
10
  """
11
+ from colorama import Fore
12
+ from colorama import Style as ColoramaStyle
13
+ from fuzzywuzzy import process
11
14
  from prompt_toolkit import PromptSession
12
- from prompt_toolkit.styles import Style as PromptStyle
13
- from prompt_toolkit.formatted_text import FormattedText
14
15
  from prompt_toolkit.completion import Completer, Completion, PathCompleter
15
16
  from prompt_toolkit.document import Document
17
+ from prompt_toolkit.formatted_text import FormattedText
16
18
  from prompt_toolkit.key_binding import KeyBindings
17
- from fuzzywuzzy import process
18
- from colorama import Fore, Style as ColoramaStyle
19
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
20
- from jarvis.jarvis_utils.tag import ot
19
+ from prompt_toolkit.styles import Style as PromptStyle
20
+
21
21
  from jarvis.jarvis_utils.config import get_replace_map
22
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
23
+ from jarvis.jarvis_utils.tag import ot
24
+
25
+
22
26
  def get_single_line_input(tip: str) -> str:
23
27
  """
24
28
  获取支持历史记录的单行输入。
@@ -176,9 +180,12 @@ def get_multiline_input(tip: str) -> str:
176
180
  'prompt': 'ansicyan',
177
181
  })
178
182
  try:
183
+ import os
184
+
179
185
  from prompt_toolkit.history import FileHistory
186
+
180
187
  from jarvis.jarvis_utils.config import get_data_dir
181
- import os
188
+
182
189
  # 获取数据目录路径
183
190
  history_dir = get_data_dir()
184
191
  # 初始化带历史记录的会话
@@ -7,17 +7,18 @@
7
7
  - 生成方法论临时文件
8
8
  - 上传方法论文件到大模型
9
9
  """
10
- import os
11
10
  import json
11
+ import os
12
12
  import tempfile
13
13
  from typing import Any, Dict, Optional
14
14
 
15
15
  from jarvis.jarvis_platform.base import BasePlatform
16
- from jarvis.jarvis_utils.config import get_data_dir
17
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
18
16
  from jarvis.jarvis_platform.registry import PlatformRegistry
17
+ from jarvis.jarvis_utils.config import get_data_dir
18
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
19
19
  from jarvis.jarvis_utils.utils import is_context_overflow
20
20
 
21
+
21
22
  def _get_methodology_directory() -> str:
22
23
  """
23
24
  获取方法论目录路径,如果不存在则创建
@@ -139,7 +140,8 @@ def load_methodology(user_input: str, tool_registery: Optional[Any] = None) -> s
139
140
  返回:
140
141
  str: 相关的方法论提示,如果未找到方法论则返回空字符串
141
142
  """
142
- from yaspin import yaspin # type: ignore
143
+ from yaspin import yaspin # type: ignore
144
+
143
145
  from jarvis.jarvis_tools.registry import ToolRegistry
144
146
 
145
147
  prompt = tool_registery.prompt() if tool_registery else ""
@@ -8,18 +8,22 @@
8
8
  - 多种编程语言的语法高亮支持
9
9
  - 结构化输出的面板显示
10
10
  """
11
- from enum import Enum
12
11
  from datetime import datetime
12
+ from enum import Enum
13
13
  from typing import Optional, Tuple
14
- from rich.panel import Panel
15
- from rich.text import Text
16
- from rich.syntax import Syntax
17
- from rich.style import Style as RichStyle
14
+
18
15
  from pygments.lexers import guess_lexer
19
16
  from pygments.util import ClassNotFound
17
+ from rich.box import SIMPLE
18
+ from rich.panel import Panel
19
+ from rich.style import Style as RichStyle
20
+ from rich.syntax import Syntax
21
+ from rich.text import Text
22
+
20
23
  from jarvis.jarvis_utils.config import get_pretty_output
21
24
  from jarvis.jarvis_utils.globals import console, get_agent_list
22
- from rich.box import SIMPLE
25
+
26
+
23
27
  class OutputType(Enum):
24
28
  """
25
29
  输出类型枚举,用于分类和样式化不同类型的消息。