jarvis-ai-assistant 0.1.179__py3-none-any.whl → 0.1.181__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_code_agent/code_agent.py +34 -106
- jarvis/jarvis_data/config_schema.json +230 -0
- jarvis/jarvis_dev/main.py +66 -112
- jarvis/jarvis_git_utils/git_commiter.py +1 -1
- jarvis/jarvis_platform/base.py +4 -2
- jarvis/jarvis_platform/kimi.py +0 -22
- jarvis/jarvis_platform/openai.py +0 -15
- jarvis/jarvis_platform/yuanbao.py +0 -24
- jarvis/jarvis_smart_shell/main.py +6 -3
- jarvis/jarvis_tools/code_plan.py +1 -3
- jarvis/jarvis_tools/edit_file.py +1 -1
- jarvis/jarvis_tools/execute_script.py +31 -8
- jarvis/jarvis_tools/registry.py +41 -35
- jarvis/jarvis_utils/builtin_replace_map.py +0 -48
- jarvis/jarvis_utils/config.py +61 -20
- jarvis/jarvis_utils/git_utils.py +89 -16
- jarvis/jarvis_utils/utils.py +131 -62
- {jarvis_ai_assistant-0.1.179.dist-info → jarvis_ai_assistant-0.1.181.dist-info}/METADATA +45 -51
- {jarvis_ai_assistant-0.1.179.dist-info → jarvis_ai_assistant-0.1.181.dist-info}/RECORD +24 -25
- {jarvis_ai_assistant-0.1.179.dist-info → jarvis_ai_assistant-0.1.181.dist-info}/entry_points.txt +0 -2
- jarvis/jarvis_tools/ask_codebase.py +0 -294
- jarvis/jarvis_tools/find_methodology.py +0 -73
- {jarvis_ai_assistant-0.1.179.dist-info → jarvis_ai_assistant-0.1.181.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.179.dist-info → jarvis_ai_assistant-0.1.181.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.179.dist-info → jarvis_ai_assistant-0.1.181.dist-info}/top_level.txt +0 -0
jarvis/jarvis_utils/git_utils.py
CHANGED
|
@@ -12,7 +12,7 @@ Git工具模块
|
|
|
12
12
|
import os
|
|
13
13
|
import re
|
|
14
14
|
import subprocess
|
|
15
|
-
from typing import Dict, List, Tuple
|
|
15
|
+
from typing import Any, Dict, List, Tuple
|
|
16
16
|
|
|
17
17
|
from jarvis.jarvis_utils.config import (get_auto_update,
|
|
18
18
|
is_confirm_before_apply_patch)
|
|
@@ -139,7 +139,7 @@ def get_diff() -> str:
|
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
|
|
142
|
-
def revert_file(filepath: str):
|
|
142
|
+
def revert_file(filepath: str) -> None:
|
|
143
143
|
"""增强版git恢复,处理新文件"""
|
|
144
144
|
import subprocess
|
|
145
145
|
try:
|
|
@@ -162,7 +162,7 @@ def revert_file(filepath: str):
|
|
|
162
162
|
# 修改后的恢复函数
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
def revert_change():
|
|
165
|
+
def revert_change() -> None:
|
|
166
166
|
"""恢复所有未提交的修改到HEAD状态"""
|
|
167
167
|
import subprocess
|
|
168
168
|
try:
|
|
@@ -176,7 +176,7 @@ def revert_change():
|
|
|
176
176
|
subprocess.run(['git', 'reset', '--hard', 'HEAD'], check=True)
|
|
177
177
|
subprocess.run(['git', 'clean', '-fd'], check=True)
|
|
178
178
|
except subprocess.CalledProcessError as e:
|
|
179
|
-
|
|
179
|
+
PrettyOutput.print(f"恢复更改失败: {str(e)}", OutputType.ERROR)
|
|
180
180
|
|
|
181
181
|
|
|
182
182
|
def handle_commit_workflow() -> bool:
|
|
@@ -192,15 +192,15 @@ def handle_commit_workflow() -> bool:
|
|
|
192
192
|
import subprocess
|
|
193
193
|
try:
|
|
194
194
|
# 获取当前分支的提交总数
|
|
195
|
-
|
|
195
|
+
commit_result = subprocess.run(
|
|
196
196
|
['git', 'rev-list', '--count', 'HEAD'],
|
|
197
197
|
capture_output=True,
|
|
198
198
|
text=True
|
|
199
199
|
)
|
|
200
|
-
if
|
|
200
|
+
if commit_result.returncode != 0:
|
|
201
201
|
return False
|
|
202
202
|
|
|
203
|
-
commit_count = int(
|
|
203
|
+
commit_count = int(commit_result.stdout.strip())
|
|
204
204
|
|
|
205
205
|
# 暂存所有修改
|
|
206
206
|
subprocess.run(['git', 'add', '.'], check=True)
|
|
@@ -313,15 +313,28 @@ def check_and_update_git_repo(repo_path: str) -> bool:
|
|
|
313
313
|
if has_uncommitted_changes():
|
|
314
314
|
return False
|
|
315
315
|
|
|
316
|
-
#
|
|
317
|
-
subprocess.run(["git", "fetch"], cwd=git_root, check=True)
|
|
318
|
-
#
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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)
|
|
325
338
|
return True
|
|
326
339
|
return False
|
|
327
340
|
except Exception as e:
|
|
@@ -363,3 +376,63 @@ def get_diff_file_list() -> List[str]:
|
|
|
363
376
|
except Exception as e:
|
|
364
377
|
PrettyOutput.print(f"获取差异文件列表异常: {str(e)}", OutputType.ERROR)
|
|
365
378
|
return []
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def get_recent_commits_with_files() -> List[Dict[str, Any]]:
|
|
383
|
+
"""获取最近5次提交的commit信息和文件清单
|
|
384
|
+
|
|
385
|
+
返回:
|
|
386
|
+
List[Dict[str, Any]]: 包含commit信息和文件清单的字典列表,格式为:
|
|
387
|
+
[
|
|
388
|
+
{
|
|
389
|
+
'hash': 提交hash,
|
|
390
|
+
'message': 提交信息,
|
|
391
|
+
'author': 作者,
|
|
392
|
+
'date': 提交日期,
|
|
393
|
+
'files': [修改的文件列表] (最多20个文件)
|
|
394
|
+
},
|
|
395
|
+
...
|
|
396
|
+
]
|
|
397
|
+
失败时返回空列表
|
|
398
|
+
"""
|
|
399
|
+
try:
|
|
400
|
+
# 获取最近5次提交的基本信息
|
|
401
|
+
result = subprocess.run(
|
|
402
|
+
['git', 'log', '-5', '--pretty=format:%H%n%s%n%an%n%ad'],
|
|
403
|
+
capture_output=True,
|
|
404
|
+
text=True
|
|
405
|
+
)
|
|
406
|
+
if result.returncode != 0:
|
|
407
|
+
return []
|
|
408
|
+
|
|
409
|
+
# 解析提交信息
|
|
410
|
+
commits = []
|
|
411
|
+
lines = result.stdout.splitlines()
|
|
412
|
+
for i in range(0, len(lines), 4):
|
|
413
|
+
if i + 3 >= len(lines):
|
|
414
|
+
break
|
|
415
|
+
commit = {
|
|
416
|
+
'hash': lines[i],
|
|
417
|
+
'message': lines[i+1],
|
|
418
|
+
'author': lines[i+2],
|
|
419
|
+
'date': lines[i+3],
|
|
420
|
+
'files': []
|
|
421
|
+
}
|
|
422
|
+
commits.append(commit)
|
|
423
|
+
|
|
424
|
+
# 获取每个提交的文件修改清单
|
|
425
|
+
for commit in commits:
|
|
426
|
+
files_result = subprocess.run(
|
|
427
|
+
['git', 'show', '--name-only', '--pretty=format:', commit['hash']],
|
|
428
|
+
capture_output=True,
|
|
429
|
+
text=True
|
|
430
|
+
)
|
|
431
|
+
if files_result.returncode == 0:
|
|
432
|
+
files = list(set(filter(None, files_result.stdout.splitlines())))
|
|
433
|
+
commit['files'] = files[:20] # 限制最多20个文件
|
|
434
|
+
|
|
435
|
+
return commits
|
|
436
|
+
|
|
437
|
+
except subprocess.CalledProcessError:
|
|
438
|
+
return []
|
jarvis/jarvis_utils/utils.py
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import hashlib
|
|
3
3
|
import os
|
|
4
|
+
import subprocess
|
|
4
5
|
import tarfile
|
|
5
6
|
import time
|
|
6
|
-
from datetime import datetime
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import Any, Callable, Dict
|
|
9
9
|
|
|
10
10
|
import yaml
|
|
11
11
|
|
|
12
12
|
from jarvis import __version__
|
|
13
|
-
from jarvis.jarvis_utils.config import get_data_dir, get_max_big_content_size
|
|
13
|
+
from jarvis.jarvis_utils.config import get_data_dir, get_max_big_content_size, set_global_env_data
|
|
14
14
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
15
15
|
from jarvis.jarvis_utils.input import get_single_line_input
|
|
16
16
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
|
|
19
20
|
def init_env(welcome_str: str) -> None:
|
|
20
21
|
"""初始化环境变量从jarvis_data/env文件
|
|
21
22
|
功能:
|
|
@@ -43,15 +44,16 @@ def init_env(welcome_str: str) -> None:
|
|
|
43
44
|
PrettyOutput.print_gradient_text(jarvis_ascii_art, (0, 120, 255), (0, 255, 200))
|
|
44
45
|
|
|
45
46
|
jarvis_dir = Path(get_data_dir())
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
script_dir = Path(os.path.dirname(os.path.dirname(__file__)))
|
|
49
|
-
hf_archive = script_dir / "jarvis_data" / "huggingface.tar.gz"
|
|
47
|
+
config_file = jarvis_dir / "config.yaml"
|
|
50
48
|
|
|
51
49
|
# 检查jarvis_data目录是否存在
|
|
52
50
|
if not jarvis_dir.exists():
|
|
53
51
|
jarvis_dir.mkdir(parents=True)
|
|
54
52
|
|
|
53
|
+
script_dir = Path(os.path.dirname(os.path.dirname(__file__)))
|
|
54
|
+
hf_archive = script_dir / "jarvis_data" / "huggingface.tar.gz"
|
|
55
|
+
|
|
56
|
+
|
|
55
57
|
# 检查并解压huggingface模型
|
|
56
58
|
hf_dir = jarvis_dir / "huggingface" / "hub"
|
|
57
59
|
if not hf_dir.exists() and hf_archive.exists():
|
|
@@ -63,62 +65,103 @@ def init_env(welcome_str: str) -> None:
|
|
|
63
65
|
except Exception as e:
|
|
64
66
|
PrettyOutput.print(f"解压HuggingFace模型失败: {e}", OutputType.ERROR)
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
os.environ.update({str(k): str(v) for k, v in env_data.items() if v is not None})
|
|
74
|
-
return
|
|
75
|
-
except yaml.YAMLError:
|
|
76
|
-
pass
|
|
77
|
-
|
|
78
|
-
# 如果不是YAML格式,按旧格式处理
|
|
79
|
-
current_key = None
|
|
80
|
-
current_value = []
|
|
81
|
-
env_data = {}
|
|
82
|
-
with open(env_file, "r", encoding="utf-8", errors="ignore") as f:
|
|
83
|
-
for line in f:
|
|
84
|
-
line = line.rstrip()
|
|
85
|
-
if not line or line.startswith(("#", ";")):
|
|
86
|
-
continue
|
|
87
|
-
if "=" in line and not line.startswith((" ", "\t")):
|
|
88
|
-
# 处理之前收集的多行值
|
|
89
|
-
if current_key is not None:
|
|
90
|
-
env_data[current_key] = "\n".join(current_value).strip().strip("'").strip('"')
|
|
91
|
-
current_value = []
|
|
92
|
-
# 解析新的键值对
|
|
93
|
-
key, value = line.split("=", 1)
|
|
94
|
-
current_key = key.strip()
|
|
95
|
-
current_value.append(value.strip())
|
|
96
|
-
elif current_key is not None:
|
|
97
|
-
# 多行值的后续行
|
|
98
|
-
current_value.append(line.strip())
|
|
99
|
-
# 处理最后一个键值对
|
|
100
|
-
if current_key is not None:
|
|
101
|
-
env_data[current_key] = "\n".join(current_value).strip().strip("'").strip('"')
|
|
102
|
-
|
|
103
|
-
# 更新环境变量
|
|
104
|
-
os.environ.update(env_data)
|
|
105
|
-
|
|
106
|
-
# 如果是旧格式,转换为YAML并备份
|
|
107
|
-
backup_file = env_file.with_name(f"env.bak.{datetime.now().strftime('%Y%m%d%H%M%S')}")
|
|
108
|
-
env_file.rename(backup_file)
|
|
109
|
-
with open(env_file, "w", encoding="utf-8") as f:
|
|
110
|
-
yaml.dump(env_data, f, default_flow_style=False, allow_unicode=True)
|
|
111
|
-
|
|
112
|
-
PrettyOutput.print(f"检测到旧格式配置文件,已自动转换为YAML格式并备份到 {backup_file}", OutputType.INFO)
|
|
113
|
-
|
|
114
|
-
except Exception as e:
|
|
115
|
-
PrettyOutput.print(f"警告: 读取 {env_file} 失败: {e}", OutputType.WARNING)
|
|
68
|
+
|
|
69
|
+
if not config_file.exists():
|
|
70
|
+
old_config_file = jarvis_dir / "env"
|
|
71
|
+
if old_config_file.exists():# 旧的配置文件存在
|
|
72
|
+
_read_old_config_file(old_config_file)
|
|
73
|
+
else:
|
|
74
|
+
_read_config_file(jarvis_dir, config_file)
|
|
116
75
|
|
|
117
76
|
# 检查是否是git仓库并更新
|
|
118
77
|
from jarvis.jarvis_utils.git_utils import check_and_update_git_repo
|
|
119
78
|
|
|
120
79
|
check_and_update_git_repo(str(script_dir))
|
|
121
80
|
|
|
81
|
+
def _read_config_file(jarvis_dir, config_file):
|
|
82
|
+
"""读取并解析YAML格式的配置文件
|
|
83
|
+
|
|
84
|
+
功能:
|
|
85
|
+
1. 读取配置文件内容
|
|
86
|
+
2. 检查并添加schema声明(如果缺失)
|
|
87
|
+
3. 将配置数据保存到全局变量
|
|
88
|
+
4. 设置环境变量(如果配置中有ENV字段)
|
|
89
|
+
|
|
90
|
+
参数:
|
|
91
|
+
jarvis_dir: Jarvis数据目录路径
|
|
92
|
+
config_file: 配置文件路径
|
|
93
|
+
"""
|
|
94
|
+
with open(config_file, "r", encoding="utf-8") as f:
|
|
95
|
+
content = f.read()
|
|
96
|
+
config_data = yaml.safe_load(content) or {}
|
|
97
|
+
if isinstance(config_data, dict):
|
|
98
|
+
# 检查是否已有schema声明,没有则添加
|
|
99
|
+
if "# yaml-language-server: $schema=" not in content:
|
|
100
|
+
schema_path = Path(os.path.relpath(
|
|
101
|
+
Path(__file__).parent.parent / "jarvis_data" / "config_schema.json",
|
|
102
|
+
start=jarvis_dir
|
|
103
|
+
))
|
|
104
|
+
with open(config_file, "w", encoding="utf-8") as f:
|
|
105
|
+
f.write(f"# yaml-language-server: $schema={schema_path}\n")
|
|
106
|
+
f.write(content)
|
|
107
|
+
# 保存到全局变量
|
|
108
|
+
set_global_env_data(config_data)
|
|
109
|
+
# 如果配置中有ENV键值对,则设置环境变量
|
|
110
|
+
if "ENV" in config_data and isinstance(config_data["ENV"], dict):
|
|
111
|
+
os.environ.update({str(k): str(v) for k, v in config_data["ENV"].items() if v is not None})
|
|
112
|
+
|
|
113
|
+
def _read_old_config_file(config_file):
|
|
114
|
+
"""读取并解析旧格式的env配置文件
|
|
115
|
+
|
|
116
|
+
功能:
|
|
117
|
+
1. 解析键值对格式的旧配置文件
|
|
118
|
+
2. 支持多行值的处理
|
|
119
|
+
3. 自动去除值的引号和空格
|
|
120
|
+
4. 将配置数据保存到全局变量
|
|
121
|
+
5. 设置环境变量并显示迁移警告
|
|
122
|
+
|
|
123
|
+
参数:
|
|
124
|
+
config_file: 旧格式配置文件路径
|
|
125
|
+
"""
|
|
126
|
+
config_data = {}
|
|
127
|
+
current_key = None
|
|
128
|
+
current_value = []
|
|
129
|
+
with open(config_file, "r", encoding="utf-8", errors="ignore") as f:
|
|
130
|
+
for line in f:
|
|
131
|
+
line = line.rstrip()
|
|
132
|
+
if not line or line.startswith(("#", ";")):
|
|
133
|
+
continue
|
|
134
|
+
if "=" in line and not line.startswith((" ", "\t")):
|
|
135
|
+
# 处理之前收集的多行值
|
|
136
|
+
if current_key is not None:
|
|
137
|
+
value = "\n".join(current_value).strip().strip("'").strip('"')
|
|
138
|
+
# 将字符串"true"/"false"转换为bool类型
|
|
139
|
+
if value.lower() == "true":
|
|
140
|
+
value = True
|
|
141
|
+
elif value.lower() == "false":
|
|
142
|
+
value = False
|
|
143
|
+
config_data[current_key] = value
|
|
144
|
+
current_value = []
|
|
145
|
+
# 解析新的键值对
|
|
146
|
+
key, value = line.split("=", 1)
|
|
147
|
+
current_key = key.strip()
|
|
148
|
+
current_value.append(value.strip())
|
|
149
|
+
elif current_key is not None:
|
|
150
|
+
# 多行值的后续行
|
|
151
|
+
current_value.append(line.strip())
|
|
152
|
+
# 处理最后一个键值对
|
|
153
|
+
if current_key is not None:
|
|
154
|
+
value = "\n".join(current_value).strip().strip("'").strip('"')
|
|
155
|
+
# 将字符串"true"/"false"转换为bool类型
|
|
156
|
+
if value.lower() == "true":
|
|
157
|
+
value = True
|
|
158
|
+
elif value.lower() == "false":
|
|
159
|
+
value = False
|
|
160
|
+
config_data[current_key] = value
|
|
161
|
+
os.environ.update({str(k): str(v) for k, v in config_data.items() if v is not None})
|
|
162
|
+
set_global_env_data(config_data)
|
|
163
|
+
PrettyOutput.print(f"检测到旧格式配置文件,旧格式以后将不再支持,请尽快迁移到新格式", OutputType.WARNING)
|
|
164
|
+
|
|
122
165
|
|
|
123
166
|
def while_success(func: Callable[[], Any], sleep_time: float = 0.1) -> Any:
|
|
124
167
|
"""循环执行函数直到成功
|
|
@@ -138,7 +181,19 @@ def while_success(func: Callable[[], Any], sleep_time: float = 0.1) -> Any:
|
|
|
138
181
|
time.sleep(sleep_time)
|
|
139
182
|
continue
|
|
140
183
|
def while_true(func: Callable[[], bool], sleep_time: float = 0.1) -> Any:
|
|
141
|
-
"""循环执行函数直到返回True
|
|
184
|
+
"""循环执行函数直到返回True
|
|
185
|
+
|
|
186
|
+
参数:
|
|
187
|
+
func: 要执行的函数,必须返回布尔值
|
|
188
|
+
sleep_time: 每次失败后的等待时间(秒)
|
|
189
|
+
|
|
190
|
+
返回:
|
|
191
|
+
函数最终返回的True值
|
|
192
|
+
|
|
193
|
+
注意:
|
|
194
|
+
与while_success不同,此函数只检查返回是否为True,
|
|
195
|
+
不捕获异常,异常会直接抛出
|
|
196
|
+
"""
|
|
142
197
|
while True:
|
|
143
198
|
ret = func()
|
|
144
199
|
if ret:
|
|
@@ -206,7 +261,7 @@ def _update_cmd_stats(cmd_name: str) -> None:
|
|
|
206
261
|
stats_file = Path(get_data_dir()) / "cmd_stat.yaml"
|
|
207
262
|
try:
|
|
208
263
|
with open(stats_file, "w", encoding="utf-8") as f:
|
|
209
|
-
yaml.safe_dump(stats, f)
|
|
264
|
+
yaml.safe_dump(stats, f, allow_unicode=True)
|
|
210
265
|
except Exception as e:
|
|
211
266
|
PrettyOutput.print(
|
|
212
267
|
f"保存命令调用统计失败: {str(e)}", OutputType.WARNING
|
|
@@ -215,10 +270,24 @@ def _update_cmd_stats(cmd_name: str) -> None:
|
|
|
215
270
|
def count_cmd_usage() -> None:
|
|
216
271
|
"""统计当前命令的使用次数"""
|
|
217
272
|
import sys
|
|
218
|
-
|
|
219
|
-
cmd_name = sys.argv[1]
|
|
220
|
-
_update_cmd_stats(cmd_name)
|
|
273
|
+
_update_cmd_stats(sys.argv[0])
|
|
221
274
|
|
|
222
275
|
def is_context_overflow(content: str) -> bool:
|
|
223
276
|
"""判断文件内容是否超出上下文限制"""
|
|
224
|
-
return get_context_token_count(content) > get_max_big_content_size()
|
|
277
|
+
return get_context_token_count(content) > get_max_big_content_size()
|
|
278
|
+
|
|
279
|
+
def get_loc_stats() -> str:
|
|
280
|
+
"""使用loc命令获取当前目录的代码统计信息
|
|
281
|
+
|
|
282
|
+
返回:
|
|
283
|
+
str: loc命令输出的原始字符串,失败时返回空字符串
|
|
284
|
+
"""
|
|
285
|
+
try:
|
|
286
|
+
result = subprocess.run(
|
|
287
|
+
['loc'],
|
|
288
|
+
capture_output=True,
|
|
289
|
+
text=True
|
|
290
|
+
)
|
|
291
|
+
return result.stdout if result.returncode == 0 else ""
|
|
292
|
+
except FileNotFoundError:
|
|
293
|
+
return ""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.181
|
|
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
|
|
@@ -55,6 +55,7 @@ Requires-Dist: python-Levenshtein==0.25.1
|
|
|
55
55
|
Requires-Dist: pillow==10.2.0
|
|
56
56
|
Requires-Dist: openai==1.78.1
|
|
57
57
|
Requires-Dist: tabulate==0.9.0
|
|
58
|
+
Requires-Dist: pyte==0.8.2
|
|
58
59
|
Provides-Extra: dev
|
|
59
60
|
Requires-Dist: pytest; extra == "dev"
|
|
60
61
|
Requires-Dist: black; extra == "dev"
|
|
@@ -114,7 +115,7 @@ pip3 install jarvis-ai-assistant
|
|
|
114
115
|
|
|
115
116
|
### 最小化配置
|
|
116
117
|
|
|
117
|
-
将以下配置写入到`~/.jarvis/
|
|
118
|
+
将以下配置写入到`~/.jarvis/config.yaml`文件中。
|
|
118
119
|
|
|
119
120
|
#### 腾讯元宝
|
|
120
121
|
```yaml
|
|
@@ -122,9 +123,9 @@ JARVIS_PLATFORM: yuanbao
|
|
|
122
123
|
JARVIS_MODEL: deep_seek_v3
|
|
123
124
|
JARVIS_THINKING_PLATFORM: yuanbao
|
|
124
125
|
JARVIS_THINKING_MODEL: deep_seek
|
|
125
|
-
|
|
126
|
-
YUANBAO_COOKIES: <元宝cookies>
|
|
127
|
-
YUANBAO_AGENT_ID: <元宝AgentID>
|
|
126
|
+
ENV:
|
|
127
|
+
YUANBAO_COOKIES: <元宝cookies>
|
|
128
|
+
YUANBAO_AGENT_ID: <元宝AgentID>
|
|
128
129
|
```
|
|
129
130
|
|
|
130
131
|
元宝cookies以及AgentID获取方式:
|
|
@@ -141,7 +142,8 @@ JARVIS_MODEL: kimi
|
|
|
141
142
|
JARVIS_THINKING_PLATFORM: kimi
|
|
142
143
|
JARVIS_THINKING_MODEL: k1
|
|
143
144
|
|
|
144
|
-
|
|
145
|
+
ENV:
|
|
146
|
+
KIMI_API_KEY: <Kimi API KEY>
|
|
145
147
|
```
|
|
146
148
|
|
|
147
149
|
Kimi API Key获取方式:
|
|
@@ -166,7 +168,7 @@ OPENAI_API_BASE: https://api.openai.com/v1 # 可选,默认为官方API地址
|
|
|
166
168
|
1. `OPENAI_API_KEY`: 必填。
|
|
167
169
|
2. `OPENAI_API_BASE`: 可选,用于自定义API端点
|
|
168
170
|
|
|
169
|
-
以上配置编写到`~/.jarvis/
|
|
171
|
+
以上配置编写到`~/.jarvis/config.yaml`文件中。
|
|
170
172
|
|
|
171
173
|
支持的模型可通过`jarvis-platform-manager --list-models`查看完整列表。
|
|
172
174
|
|
|
@@ -191,27 +193,10 @@ OPENAI_API_BASE: https://api.openai.com/v1 # 可选,默认为官方API地址
|
|
|
191
193
|
---
|
|
192
194
|
|
|
193
195
|
## ⚙️ 配置说明 <a id="configuration"></a>
|
|
194
|
-
###
|
|
195
|
-
配置文件支持两种格式:
|
|
196
|
-
1. **YAML格式(推荐)**:
|
|
197
|
-
```yaml
|
|
198
|
-
JARVIS_PLATFORM: yuanbao
|
|
199
|
-
JARVIS_MODEL: deep_seek_v3
|
|
200
|
-
YUANBAO_COOKIES: "your_cookies_here"
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
2. **传统键值对格式**:
|
|
204
|
-
```
|
|
205
|
-
JARVIS_PLATFORM=yuanbao
|
|
206
|
-
JARVIS_MODEL=deep_seek_v3
|
|
207
|
-
YUANBAO_COOKIES=your_cookies_here
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
系统会自动检测格式并处理。当检测到传统格式时,会自动转换为YAML格式并备份原文件。
|
|
211
|
-
|
|
212
|
-
### 环境变量配置
|
|
196
|
+
### 配置项
|
|
213
197
|
| 变量名称 | 默认值 | 说明 |
|
|
214
198
|
|----------|--------|------|
|
|
199
|
+
| `ENV` | {} | 环境变量配置,用于设置系统环境变量 |
|
|
215
200
|
| `JARVIS_MAX_TOKEN_COUNT` | 960000 | 上下文窗口的最大token数量 |
|
|
216
201
|
| `JARVIS_MAX_INPUT_TOKEN_COUNT` | 32000 | 输入的最大token数量 |
|
|
217
202
|
| `JARVIS_AUTO_COMPLETE` | false | 是否启用自动完成功能(任务判定完成的时候会自动终止) |
|
|
@@ -228,16 +213,26 @@ OPENAI_API_BASE: https://api.openai.com/v1 # 可选,默认为官方API地址
|
|
|
228
213
|
| `JARVIS_PRETTY_OUTPUT` | false | 是否启用PrettyOutput |
|
|
229
214
|
| `JARVIS_GIT_COMMIT_PROMPT` | "" | 自定义git提交信息生成提示模板 |
|
|
230
215
|
| `JARVIS_PRINT_PROMPT` | false | 是否打印提示 |
|
|
216
|
+
| `JARVIS_USE_METHODOLOGY` | true | 是否启用方法论功能 |
|
|
217
|
+
| `JARVIS_USE_ANALYSIS` | true | 是否启用任务分析功能 |
|
|
218
|
+
| `JARVIS_DATA_PATH` | ~/.jarvis | Jarvis数据存储目录路径 |
|
|
231
219
|
|
|
232
|
-
所有配置编写到`~/.jarvis/
|
|
220
|
+
所有配置编写到`~/.jarvis/config.yaml`文件中即可生效。
|
|
233
221
|
|
|
222
|
+
### 配置文件格式
|
|
223
|
+
配置文件仅支持YAML格式:
|
|
224
|
+
```yaml
|
|
225
|
+
JARVIS_PLATFORM: yuanbao
|
|
226
|
+
JARVIS_MODEL: deep_seek_v3
|
|
227
|
+
ENV:
|
|
228
|
+
YUANBAO_COOKIES: "your_cookies_here"
|
|
229
|
+
```
|
|
234
230
|
|
|
235
231
|
---
|
|
236
232
|
## 🛠️ 工具说明 <a id="tools"></a>
|
|
237
233
|
### 内置工具
|
|
238
234
|
| 工具名称 | 描述 |
|
|
239
235
|
|----------|------|
|
|
240
|
-
| ask_codebase | 智能代码库查询和分析,用于定位功能所在文件和理解单点实现,适合查询特定功能位置和实现原理 |
|
|
241
236
|
| ask_user | 交互式用户输入收集 |
|
|
242
237
|
| chdir | 更改当前工作目录 |
|
|
243
238
|
| rewrite_file | 文件重写工具,用于完全重写或创建文件,提供完整的文件内容替换 |
|
|
@@ -248,7 +243,6 @@ OPENAI_API_BASE: https://api.openai.com/v1 # 可选,默认为官方API地址
|
|
|
248
243
|
| execute_script | 执行脚本并返回结果,支持任意解释器。 |
|
|
249
244
|
| file_analyzer | 分析文件内容并提取关键信息。支持的文件:文本文件、word文档、pdf文件、图片 |
|
|
250
245
|
| file_operation | 文件批量操作工具,可批量读写多个文件,支持文本文件,适用于需要同时处理多个文件的场景(读取配置文件、保存生成内容等) |
|
|
251
|
-
| find_methodology | 方法论查找工具,用于在执行过程中查看历史方法论辅助决策 |
|
|
252
246
|
| methodology | 方法论管理工具,支持添加、更新和删除操作 |
|
|
253
247
|
| read_code | 代码阅读与分析工具,用于读取源代码文件并添加行号,针对代码文件优化,提供更好的格式化输出和行号显示,适用于代码分析、审查和理解代码实现的场景 |
|
|
254
248
|
| read_webpage | 读取网页内容并分析 |
|
|
@@ -274,15 +268,20 @@ Jarvis支持使用特殊标记`'<tag>'`来触发命令替换功能,其中`tag`
|
|
|
274
268
|
| `'Fix'` | 修复问题 |
|
|
275
269
|
|
|
276
270
|
#### 自定义替换
|
|
277
|
-
|
|
271
|
+
可以通过以下方式配置自定义替换规则:
|
|
272
|
+
|
|
273
|
+
**配置文件**:
|
|
274
|
+
在`~/.jarvis/config.yaml`中添加`JARVIS_REPLACE_MAP`配置项:
|
|
278
275
|
```yaml
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
276
|
+
JARVIS_REPLACE_MAP:
|
|
277
|
+
tag_name:
|
|
278
|
+
template: "替换后的内容"
|
|
279
|
+
description: "标记描述"
|
|
280
|
+
append: false # 可选,true表示追加到输入末尾,false表示直接替换
|
|
283
281
|
```
|
|
284
282
|
|
|
285
283
|
|
|
284
|
+
|
|
286
285
|
#### 文件路径补全
|
|
287
286
|
在交互式输入中,输入`@`可以触发文件路径补全功能,支持模糊匹配。
|
|
288
287
|
|
|
@@ -342,27 +341,22 @@ class CustomTool:
|
|
|
342
341
|
|
|
343
342
|
|
|
344
343
|
### 添加MCP
|
|
345
|
-
MCP(模型上下文协议)
|
|
344
|
+
MCP(模型上下文协议)支持以下配置方式:
|
|
346
345
|
|
|
347
|
-
####
|
|
346
|
+
#### 配置文件
|
|
347
|
+
在`~/.jarvis/config.yaml`中添加`JARVIS_MCP`配置项:
|
|
348
348
|
```yaml
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
349
|
+
JARVIS_MCP:
|
|
350
|
+
- type: stdio # 或 sse/streamable
|
|
351
|
+
name: MCP名称
|
|
352
|
+
command: 可执行命令 # stdio模式必填
|
|
353
|
+
base_url: http://example.com/api # sse/streamable模式必填
|
|
354
|
+
args: [参数列表] # 可选
|
|
355
|
+
env: # 可选环境变量
|
|
356
|
+
KEY: VALUE
|
|
357
|
+
enable: true # 可选,默认为true
|
|
355
358
|
```
|
|
356
359
|
|
|
357
|
-
#### 远程MCP配置(`sse`模式)
|
|
358
|
-
```yaml
|
|
359
|
-
type: sse
|
|
360
|
-
name: MCP名称
|
|
361
|
-
base_url: http://example.com/api
|
|
362
|
-
auth_token: 认证令牌 # 可选
|
|
363
|
-
headers: # 可选HTTP头
|
|
364
|
-
X-Custom-Header: value
|
|
365
|
-
```
|
|
366
360
|
|
|
367
361
|
|
|
368
362
|
### 添加新大模型平台
|