jarvis-ai-assistant 0.1.154__py3-none-any.whl → 0.1.156__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_agent/__init__.py +1 -1
- jarvis/jarvis_agent/builtin_input_handler.py +21 -105
- jarvis/jarvis_agent/jarvis.py +6 -0
- jarvis/jarvis_agent/patch.py +65 -37
- jarvis/jarvis_code_agent/code_agent.py +6 -1
- jarvis/jarvis_code_analysis/code_review.py +5 -5
- jarvis/jarvis_git_utils/git_commiter.py +2 -1
- jarvis/jarvis_platform/base.py +2 -1
- jarvis/jarvis_platform_manager/main.py +41 -0
- jarvis/jarvis_smart_shell/main.py +68 -27
- jarvis/jarvis_tools/create_code_agent.py +0 -20
- jarvis/jarvis_tools/find_methodology.py +2 -1
- jarvis/jarvis_tools/registry.py +2 -1
- jarvis/jarvis_utils/builtin_replace_map.py +133 -0
- jarvis/jarvis_utils/config.py +26 -8
- jarvis/jarvis_utils/input.py +34 -20
- jarvis/jarvis_utils/tag.py +21 -0
- jarvis/jarvis_utils/utils.py +0 -22
- {jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/METADATA +45 -14
- {jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/RECORD +25 -23
- {jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/WHEEL +1 -1
- {jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/entry_points.txt +1 -0
- {jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_agent/__init__.py
CHANGED
|
@@ -15,7 +15,7 @@ from jarvis.jarvis_utils.methodology import load_methodology
|
|
|
15
15
|
from jarvis.jarvis_utils.globals import make_agent_name, set_agent, delete_agent
|
|
16
16
|
from jarvis.jarvis_utils.input import get_multiline_input
|
|
17
17
|
from jarvis.jarvis_utils.config import get_max_token_count
|
|
18
|
-
from jarvis.jarvis_utils.
|
|
18
|
+
from jarvis.jarvis_utils.tag import ct, ot
|
|
19
19
|
from jarvis.jarvis_utils.utils import user_confirm
|
|
20
20
|
|
|
21
21
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import re
|
|
2
2
|
from typing import Any, Tuple
|
|
3
|
-
from jarvis.jarvis_utils.
|
|
3
|
+
from jarvis.jarvis_utils.config import get_replace_map
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
@@ -21,115 +21,31 @@ def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
|
21
21
|
if not special_tags:
|
|
22
22
|
return user_input, False
|
|
23
23
|
|
|
24
|
-
#
|
|
25
|
-
|
|
24
|
+
# 获取替换映射表
|
|
25
|
+
replace_map = get_replace_map()
|
|
26
26
|
# 处理每个标记
|
|
27
27
|
for tag in special_tags:
|
|
28
|
-
if tag in processed_tags:
|
|
29
|
-
continue
|
|
30
|
-
processed_tags.add(tag)
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
user_input += f"""
|
|
35
|
-
请使用ask_codebase工具查询代码库,必须严格遵守以下工具调用格式:
|
|
36
|
-
|
|
37
|
-
{ot("TOOL_CALL")}
|
|
38
|
-
want: 想要从执行结果中获取到的信息
|
|
39
|
-
name: ask_codebase
|
|
40
|
-
arguments:
|
|
41
|
-
question: "与xxx功能相关的文件有哪些?"
|
|
42
|
-
{ct("TOOL_CALL")}
|
|
43
|
-
|
|
44
|
-
可以使用的提问格式包括:
|
|
45
|
-
1. 与xxx功能相关的文件有哪些?
|
|
46
|
-
2. 要实现xxx,应该要修改哪些文件?
|
|
47
|
-
3. xxx功能是怎么实现的?
|
|
48
|
-
4. xxx模块的入口函数是什么?
|
|
49
|
-
5. xxx功能的测试用例在哪里?
|
|
50
|
-
"""
|
|
51
|
-
elif tag == "Web":
|
|
52
|
-
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
53
|
-
agent.set_addon_prompt(f"""
|
|
54
|
-
请使用search_web工具进行网页搜索,必须严格遵守以下工具调用格式:
|
|
55
|
-
|
|
56
|
-
{ot("TOOL_CALL")}
|
|
57
|
-
want: 想要从执行结果中获取到的信息
|
|
58
|
-
name: search_web
|
|
59
|
-
arguments:
|
|
60
|
-
query: "xxx技术的最新发展是什么?"
|
|
61
|
-
{ct("TOOL_CALL")}
|
|
62
|
-
|
|
63
|
-
可以使用的提问格式包括:
|
|
64
|
-
1. xxx技术的最新发展是什么?
|
|
65
|
-
2. xxx框架的官方文档在哪里?
|
|
66
|
-
3. xxx库的GitHub仓库地址是什么?
|
|
67
|
-
4. xxx问题的解决方案有哪些?
|
|
68
|
-
5. xxx概念的详细解释是什么?
|
|
69
|
-
""")
|
|
70
|
-
elif tag == "Summary":
|
|
71
|
-
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
29
|
+
# 优先处理特殊标记
|
|
30
|
+
if tag == "Summary":
|
|
72
31
|
agent._summarize_and_clear_history()
|
|
73
|
-
|
|
74
|
-
return "", True
|
|
32
|
+
return "", True
|
|
75
33
|
elif tag == "Clear":
|
|
76
|
-
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
77
34
|
agent.clear()
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
1. 关于xxx的方法论有哪些?
|
|
94
|
-
2. 如何解决xxx问题?
|
|
95
|
-
3. xxx的最佳实践是什么?
|
|
96
|
-
4. 处理xxx的标准流程是什么?
|
|
97
|
-
5. 实现xxx的参考方案有哪些?
|
|
98
|
-
""")
|
|
99
|
-
elif tag == "Plan":
|
|
100
|
-
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
101
|
-
agent.set_addon_prompt(f"""
|
|
102
|
-
请使用code_plan工具生成代码修改计划,必须严格遵守以下工具调用格式:
|
|
103
|
-
|
|
104
|
-
{ot("TOOL_CALL")}
|
|
105
|
-
want: 想要从执行结果中获取到的信息
|
|
106
|
-
name: code_plan
|
|
107
|
-
arguments:
|
|
108
|
-
requirement: "需要实现用户登录功能,包括用户名密码验证和JWT生成"
|
|
109
|
-
{ct("TOOL_CALL")}
|
|
110
|
-
|
|
111
|
-
请提供详细的需求描述和完整上下文信息:
|
|
112
|
-
|
|
113
|
-
必须包含的上下文信息:
|
|
114
|
-
1. 当前会话状态 - 当前正在处理的任务和进度
|
|
115
|
-
2. 用户历史请求 - 与本任务相关的历史请求
|
|
116
|
-
3. 系统状态 - 相关的系统配置和环境状态
|
|
117
|
-
4. 已确定的相关文件 - 已经分析出的需要修改的文件列表
|
|
118
|
-
|
|
119
|
-
示例:
|
|
120
|
-
1. 需要实现用户登录功能,包括用户名密码验证和JWT生成
|
|
121
|
-
2. 重构订单处理模块以提高性能
|
|
122
|
-
3. 优化数据库查询性能,减少响应时间
|
|
123
|
-
4. 添加支付网关集成功能
|
|
124
|
-
5. 修改用户权限管理系统
|
|
125
|
-
|
|
126
|
-
code_plan工具将:
|
|
127
|
-
1. 分析项目结构确定相关文件
|
|
128
|
-
2. 理解需求后制定详细修改步骤
|
|
129
|
-
3. 按功能模块分组修改内容
|
|
130
|
-
4. 评估修改影响范围
|
|
131
|
-
5. 生成可执行的开发计划
|
|
132
|
-
""")
|
|
133
|
-
# 移除对未知标记的警告输出
|
|
35
|
+
return "", True
|
|
36
|
+
|
|
37
|
+
processed_tag = set()
|
|
38
|
+
add_on_prompt = ""
|
|
39
|
+
|
|
40
|
+
# 处理普通替换标记
|
|
41
|
+
if tag in replace_map:
|
|
42
|
+
processed_tag.add(tag)
|
|
43
|
+
if "append" in replace_map[tag] and replace_map[tag]["append"] and tag not in processed_tag:
|
|
44
|
+
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
45
|
+
add_on_prompt += replace_map[tag]["template"] + "\n"
|
|
46
|
+
else:
|
|
47
|
+
user_input = user_input.replace(f"'<{tag}>'", replace_map[tag]["template"])
|
|
48
|
+
|
|
49
|
+
agent.set_addon_prompt(add_on_prompt)
|
|
134
50
|
|
|
135
51
|
return user_input, False
|
jarvis/jarvis_agent/jarvis.py
CHANGED
|
@@ -114,6 +114,7 @@ def main() -> None:
|
|
|
114
114
|
parser = argparse.ArgumentParser(description='Jarvis AI assistant')
|
|
115
115
|
parser.add_argument('-p', '--platform', type=str, help='Platform to use')
|
|
116
116
|
parser.add_argument('-m', '--model', type=str, help='Model to use')
|
|
117
|
+
parser.add_argument('-t', '--task', type=str, help='Directly input task content from command line')
|
|
117
118
|
args = parser.parse_args()
|
|
118
119
|
|
|
119
120
|
try:
|
|
@@ -126,6 +127,11 @@ def main() -> None:
|
|
|
126
127
|
need_summary=False
|
|
127
128
|
)
|
|
128
129
|
|
|
130
|
+
# 优先处理命令行直接传入的任务
|
|
131
|
+
if args.task:
|
|
132
|
+
agent.run(args.task)
|
|
133
|
+
sys.exit(0)
|
|
134
|
+
|
|
129
135
|
tasks = _load_tasks()
|
|
130
136
|
if tasks and (selected_task := _select_task(tasks)):
|
|
131
137
|
PrettyOutput.print(f"执行任务: {selected_task}", OutputType.INFO)
|
jarvis/jarvis_agent/patch.py
CHANGED
|
@@ -15,7 +15,8 @@ from jarvis.jarvis_utils.git_utils import get_commits_between, get_latest_commit
|
|
|
15
15
|
from jarvis.jarvis_utils.globals import add_read_file_record, has_read_file
|
|
16
16
|
from jarvis.jarvis_utils.input import get_multiline_input
|
|
17
17
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
18
|
-
from jarvis.jarvis_utils.utils import
|
|
18
|
+
from jarvis.jarvis_utils.utils import get_file_line_count, user_confirm
|
|
19
|
+
from jarvis.jarvis_utils.tag import ot, ct
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
class PatchOutputHandler(OutputHandler):
|
|
@@ -153,6 +154,13 @@ def apply_patch(output_str: str, agent: Any) -> str:
|
|
|
153
154
|
spinner.fail("❌")
|
|
154
155
|
return f"以下文件未读取: {not_read_file},应用补丁存在风险,请先读取文件后再生成补丁"
|
|
155
156
|
|
|
157
|
+
# 检查是否有文件在Git仓库外
|
|
158
|
+
in_git_repo = True
|
|
159
|
+
for filepath in patches.keys():
|
|
160
|
+
if not _is_file_in_git_repo(filepath):
|
|
161
|
+
in_git_repo = False
|
|
162
|
+
break
|
|
163
|
+
|
|
156
164
|
# 按文件逐个处理
|
|
157
165
|
for filepath, patch_content in patches.items():
|
|
158
166
|
try:
|
|
@@ -177,46 +185,50 @@ def apply_patch(output_str: str, agent: Any) -> str:
|
|
|
177
185
|
spinner.write(f"✅ 文件 {filepath} 回滚完成")
|
|
178
186
|
|
|
179
187
|
final_ret = ""
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
188
|
+
if in_git_repo:
|
|
189
|
+
diff = get_diff()
|
|
190
|
+
if diff:
|
|
191
|
+
PrettyOutput.print(diff, OutputType.CODE, lang="diff")
|
|
192
|
+
with spinner.hidden():
|
|
193
|
+
commited = handle_commit_workflow()
|
|
194
|
+
if commited:
|
|
195
|
+
# 获取提交信息
|
|
196
|
+
end_hash = get_latest_commit_hash()
|
|
197
|
+
commits = get_commits_between(start_hash, end_hash)
|
|
198
|
+
|
|
199
|
+
# 添加提交信息到final_ret
|
|
200
|
+
if commits:
|
|
201
|
+
final_ret += "✅ 补丁已应用\n"
|
|
202
|
+
final_ret += "# 提交信息:\n"
|
|
203
|
+
for commit_hash, commit_message in commits:
|
|
204
|
+
final_ret += f"- {commit_hash[:7]}: {commit_message}\n"
|
|
205
|
+
|
|
206
|
+
final_ret += f"# 应用补丁:\n```diff\n{diff}\n```"
|
|
207
|
+
|
|
208
|
+
# 增加代码变更分析和错误提示
|
|
209
|
+
addon_prompt = "1. 请调用静态检查工具(如有)检查以上变更是否引入了潜在错误\n"
|
|
210
|
+
addon_prompt += "2. 如果发现致命的代码错误,请立即开始修复\n"
|
|
211
|
+
addon_prompt += "3. 如果发现性能、风格等问题,要询问用户是否需要立即修复\n"
|
|
212
|
+
addon_prompt += "\n\n"
|
|
213
|
+
addon_prompt += "如果没有问题,请继续进行下一步修改\n"
|
|
214
|
+
addon_prompt += f"如果用户的需求已经完成,请终止,不要输出新的 {ot('PATCH')},不要实现任何超出用户需求外的内容\n"
|
|
215
|
+
addon_prompt += "如果有任何信息不清楚,调用工具获取信息\n"
|
|
216
|
+
addon_prompt += "每次响应必须且只能包含一个操作\n"
|
|
217
|
+
|
|
218
|
+
agent.set_addon_prompt(addon_prompt)
|
|
211
219
|
|
|
220
|
+
else:
|
|
221
|
+
final_ret += "✅ 补丁已应用(没有新的提交)"
|
|
212
222
|
else:
|
|
213
|
-
final_ret += "
|
|
223
|
+
final_ret += "❌ 补丁应用被拒绝\n"
|
|
224
|
+
final_ret += f"# 补丁预览:\n```diff\n{diff}\n```"
|
|
214
225
|
else:
|
|
215
|
-
|
|
216
|
-
final_ret +=
|
|
226
|
+
commited = False
|
|
227
|
+
final_ret += "❌ 没有要提交的更改\n"
|
|
217
228
|
else:
|
|
218
|
-
|
|
219
|
-
final_ret += "
|
|
229
|
+
# 对于Git仓库外的文件,直接返回成功
|
|
230
|
+
final_ret += "✅ 补丁已应用(文件不在Git仓库中)"
|
|
231
|
+
commited = True
|
|
220
232
|
# 用户确认最终结果
|
|
221
233
|
with spinner.hidden():
|
|
222
234
|
if commited:
|
|
@@ -231,6 +243,22 @@ def apply_patch(output_str: str, agent: Any) -> str:
|
|
|
231
243
|
return final_ret
|
|
232
244
|
|
|
233
245
|
|
|
246
|
+
def _is_file_in_git_repo(filepath: str) -> bool:
|
|
247
|
+
"""检查文件是否在当前Git仓库中"""
|
|
248
|
+
import subprocess
|
|
249
|
+
try:
|
|
250
|
+
# 获取Git仓库根目录
|
|
251
|
+
repo_root = subprocess.run(
|
|
252
|
+
['git', 'rev-parse', '--show-toplevel'],
|
|
253
|
+
capture_output=True,
|
|
254
|
+
text=True
|
|
255
|
+
).stdout.strip()
|
|
256
|
+
|
|
257
|
+
# 检查文件路径是否在仓库根目录下
|
|
258
|
+
return os.path.abspath(filepath).startswith(os.path.abspath(repo_root))
|
|
259
|
+
except:
|
|
260
|
+
return False
|
|
261
|
+
|
|
234
262
|
def revert_file(filepath: str):
|
|
235
263
|
"""增强版git恢复,处理新文件"""
|
|
236
264
|
import subprocess
|
|
@@ -354,6 +354,8 @@ def main() -> None:
|
|
|
354
354
|
help='Target platform name', default=None)
|
|
355
355
|
parser.add_argument('-m', '--model', type=str,
|
|
356
356
|
help='Model name to use', default=None)
|
|
357
|
+
parser.add_argument('-r', '--requirement', type=str,
|
|
358
|
+
help='Requirement to process', default=None)
|
|
357
359
|
args = parser.parse_args()
|
|
358
360
|
|
|
359
361
|
curr_dir = os.getcwd()
|
|
@@ -361,7 +363,10 @@ def main() -> None:
|
|
|
361
363
|
PrettyOutput.print(f"当前目录: {git_dir}", OutputType.INFO)
|
|
362
364
|
|
|
363
365
|
try:
|
|
364
|
-
|
|
366
|
+
if args.requirement:
|
|
367
|
+
user_input = args.requirement
|
|
368
|
+
else:
|
|
369
|
+
user_input = get_multiline_input("请输入你的需求(输入空行退出):")
|
|
365
370
|
if not user_input:
|
|
366
371
|
sys.exit(0)
|
|
367
372
|
agent = CodeAgent(platform=args.platform,
|
|
@@ -13,7 +13,8 @@ from jarvis.jarvis_agent import Agent
|
|
|
13
13
|
from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_token_count
|
|
14
14
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
15
15
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
16
|
-
from jarvis.jarvis_utils.utils import
|
|
16
|
+
from jarvis.jarvis_utils.utils import init_env
|
|
17
|
+
from jarvis.jarvis_utils.tag import ot, ct
|
|
17
18
|
from jarvis.jarvis_code_analysis.checklists.loader import get_language_checklist
|
|
18
19
|
|
|
19
20
|
class CodeReviewTool:
|
|
@@ -559,7 +560,7 @@ class CodeReviewTool:
|
|
|
559
560
|
{ct("REPORT")}""",
|
|
560
561
|
output_handler=[tool_registry],
|
|
561
562
|
platform=PlatformRegistry().get_thinking_platform(),
|
|
562
|
-
auto_complete=
|
|
563
|
+
auto_complete=False
|
|
563
564
|
)
|
|
564
565
|
|
|
565
566
|
# Determine if we need to split the diff due to size
|
|
@@ -616,9 +617,8 @@ class CodeReviewTool:
|
|
|
616
617
|
complete_prompt = user_prompt + "\n\n代码差异内容:\n```diff\n" + diff_output + "\n```"
|
|
617
618
|
|
|
618
619
|
# Run the agent with the prompt
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
spinner.ok("✅")
|
|
620
|
+
|
|
621
|
+
result = agent.run(complete_prompt)
|
|
622
622
|
finally:
|
|
623
623
|
# Clean up the temporary file
|
|
624
624
|
if os.path.exists(temp_file_path):
|
|
@@ -14,7 +14,8 @@ from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_
|
|
|
14
14
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
15
15
|
from jarvis.jarvis_utils.git_utils import find_git_root, has_uncommitted_changes
|
|
16
16
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
17
|
-
from jarvis.jarvis_utils.utils import
|
|
17
|
+
from jarvis.jarvis_utils.utils import init_env
|
|
18
|
+
from jarvis.jarvis_utils.tag import ot, ct
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
class GitCommitTool:
|
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -3,7 +3,8 @@ import re
|
|
|
3
3
|
from typing import List, Tuple
|
|
4
4
|
from jarvis.jarvis_utils.globals import clear_read_file_record
|
|
5
5
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
|
-
from jarvis.jarvis_utils.utils import
|
|
6
|
+
from jarvis.jarvis_utils.utils import get_context_token_count, while_success, while_true
|
|
7
|
+
from jarvis.jarvis_utils.tag import ot, ct
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class BasePlatform(ABC):
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
2
3
|
import asyncio
|
|
3
4
|
from fastapi import FastAPI, HTTPException
|
|
@@ -61,6 +62,7 @@ def chat_with_model(platform_name: str, model_name: str):
|
|
|
61
62
|
platform.set_model_name(model_name)
|
|
62
63
|
platform.set_suppress_output(False)
|
|
63
64
|
PrettyOutput.print(f"连接到 {platform_name} 平台 {model_name} 模型", OutputType.SUCCESS)
|
|
65
|
+
PrettyOutput.print("可用命令: /bye - 退出聊天, /clear - 清除会话, /upload - 上传文件, /shell - 执行shell命令", OutputType.INFO)
|
|
64
66
|
|
|
65
67
|
# Start conversation loop
|
|
66
68
|
while True:
|
|
@@ -86,6 +88,45 @@ def chat_with_model(platform_name: str, model_name: str):
|
|
|
86
88
|
PrettyOutput.print(f"清除会话失败: {str(e)}", OutputType.ERROR)
|
|
87
89
|
continue
|
|
88
90
|
|
|
91
|
+
# Check if it is an upload command
|
|
92
|
+
if user_input.strip().startswith("/upload"):
|
|
93
|
+
try:
|
|
94
|
+
file_path = user_input.strip()[8:].strip()
|
|
95
|
+
if not file_path:
|
|
96
|
+
PrettyOutput.print("请指定要上传的文件路径,例如: /upload /path/to/file 或 /upload \"/path/with spaces/file\"", OutputType.WARNING)
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
# Remove quotes if present
|
|
100
|
+
if (file_path.startswith('"') and file_path.endswith('"')) or (file_path.startswith("'") and file_path.endswith("'")):
|
|
101
|
+
file_path = file_path[1:-1]
|
|
102
|
+
|
|
103
|
+
PrettyOutput.print(f"正在上传文件: {file_path}", OutputType.INFO)
|
|
104
|
+
if platform.upload_files([file_path]):
|
|
105
|
+
PrettyOutput.print("文件上传成功", OutputType.SUCCESS)
|
|
106
|
+
else:
|
|
107
|
+
PrettyOutput.print("文件上传失败", OutputType.ERROR)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
PrettyOutput.print(f"上传文件失败: {str(e)}", OutputType.ERROR)
|
|
110
|
+
continue
|
|
111
|
+
|
|
112
|
+
# Check if it is a shell command
|
|
113
|
+
if user_input.strip().startswith("/shell"):
|
|
114
|
+
try:
|
|
115
|
+
command = user_input.strip()[6:].strip()
|
|
116
|
+
if not command:
|
|
117
|
+
PrettyOutput.print("请指定要执行的shell命令,例如: /shell ls -l", OutputType.WARNING)
|
|
118
|
+
continue
|
|
119
|
+
|
|
120
|
+
PrettyOutput.print(f"执行命令: {command}", OutputType.INFO)
|
|
121
|
+
return_code = os.system(command)
|
|
122
|
+
if return_code == 0:
|
|
123
|
+
PrettyOutput.print("命令执行完成", OutputType.SUCCESS)
|
|
124
|
+
else:
|
|
125
|
+
PrettyOutput.print(f"命令执行失败(返回码: {return_code})", OutputType.ERROR)
|
|
126
|
+
except Exception as ex:
|
|
127
|
+
PrettyOutput.print(f"执行命令失败: {str(ex)}", OutputType.ERROR)
|
|
128
|
+
continue
|
|
129
|
+
|
|
89
130
|
try:
|
|
90
131
|
# Send to model and get reply
|
|
91
132
|
response = platform.chat_until_success(user_input)
|
|
@@ -2,33 +2,63 @@
|
|
|
2
2
|
import argparse
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
|
-
import readline
|
|
6
5
|
from typing import Optional
|
|
7
6
|
|
|
8
|
-
from yaspin import yaspin
|
|
9
|
-
|
|
10
7
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
11
8
|
from jarvis.jarvis_utils.config import get_shell_name
|
|
12
9
|
from jarvis.jarvis_utils.input import get_multiline_input
|
|
13
|
-
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
14
10
|
from jarvis.jarvis_utils.utils import init_env
|
|
15
11
|
|
|
16
|
-
def execute_command(command: str) -> None:
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
12
|
+
def execute_command(command: str, should_run: bool) -> None:
|
|
13
|
+
"""Print command without execution"""
|
|
14
|
+
print(command)
|
|
15
|
+
if should_run:
|
|
16
|
+
os.system(command)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def install_fish_completion() -> int:
|
|
20
|
+
"""Install fish shell command completion if not already installed
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
int: 0 if success, 1 if failed
|
|
24
|
+
"""
|
|
25
|
+
if get_shell_name() != "fish":
|
|
26
|
+
print("当前不是fish shell,无需安装")
|
|
27
|
+
return 0
|
|
28
|
+
|
|
29
|
+
# 使用fish命令检查函数是否已加载
|
|
30
|
+
check_cmd = 'functions --names | grep fish_command_not_found > /dev/null && echo "defined" || echo "undefined"'
|
|
31
|
+
result = os.popen(f'fish -c \'{check_cmd}\'').read().strip()
|
|
32
|
+
|
|
33
|
+
if result == "defined":
|
|
34
|
+
print("fish_command_not_found函数已加载,无需安装")
|
|
35
|
+
return 0
|
|
36
|
+
|
|
37
|
+
config_file = os.path.expanduser("~/.config/fish/config.fish")
|
|
38
|
+
|
|
39
|
+
# 检查文件内容是否已定义但未加载
|
|
40
|
+
if os.path.exists(config_file):
|
|
41
|
+
with open(config_file, 'r') as config:
|
|
42
|
+
if "function fish_command_not_found" in config.read():
|
|
43
|
+
print("fish_command_not_found函数已定义但未加载,请执行: source ~/.config/fish/config.fish")
|
|
44
|
+
return 0
|
|
45
|
+
|
|
46
|
+
# 创建config.fish文件如果不存在
|
|
47
|
+
os.makedirs(os.path.dirname(config_file), exist_ok=True)
|
|
48
|
+
|
|
49
|
+
# 追加函数定义到config.fish
|
|
50
|
+
with open(config_file, 'a') as config:
|
|
51
|
+
config.write("""
|
|
52
|
+
function fish_command_not_found
|
|
53
|
+
commandline -r (jss $argv)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
function __fish_command_not_found_handler --on-event fish_command_not_found
|
|
57
|
+
fish_command_not_found $argv
|
|
58
|
+
end
|
|
59
|
+
""")
|
|
60
|
+
print("Fish shell命令补全功能已安装到config.fish,请执行: source ~/.config/fish/config.fish")
|
|
61
|
+
return 0
|
|
32
62
|
|
|
33
63
|
|
|
34
64
|
def process_request(request: str) -> Optional[str]:
|
|
@@ -97,9 +127,7 @@ Output: find . -name "*.py"
|
|
|
97
127
|
prefix = f"Current path: {current_path}\n"
|
|
98
128
|
prefix += f"Current shell: {shell}\n"
|
|
99
129
|
|
|
100
|
-
|
|
101
|
-
result = model.chat_until_success(prefix + request)
|
|
102
|
-
spinner.ok("✅ 命令生成成功")
|
|
130
|
+
result = model.chat_until_success(prefix + request)
|
|
103
131
|
|
|
104
132
|
# 提取命令
|
|
105
133
|
if result and isinstance(result, str):
|
|
@@ -108,8 +136,7 @@ Output: find . -name "*.py"
|
|
|
108
136
|
|
|
109
137
|
return None
|
|
110
138
|
|
|
111
|
-
except Exception
|
|
112
|
-
PrettyOutput.print(f"处理请求失败: {str(e)}", OutputType.WARNING)
|
|
139
|
+
except Exception:
|
|
113
140
|
return None
|
|
114
141
|
|
|
115
142
|
def main():
|
|
@@ -123,6 +150,7 @@ Example:
|
|
|
123
150
|
%(prog)s "Find all Python files in the current directory"
|
|
124
151
|
%(prog)s "Compress all jpg images"
|
|
125
152
|
%(prog)s "Find documents modified in the last week"
|
|
153
|
+
%(prog)s install
|
|
126
154
|
""")
|
|
127
155
|
|
|
128
156
|
# 修改为可选参数,添加从stdin读取的支持
|
|
@@ -131,21 +159,34 @@ Example:
|
|
|
131
159
|
nargs='?', # 设置为可选参数
|
|
132
160
|
help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取"
|
|
133
161
|
)
|
|
162
|
+
|
|
163
|
+
# 添加install子命令
|
|
164
|
+
parser.add_argument(
|
|
165
|
+
"--install",
|
|
166
|
+
action="store_true",
|
|
167
|
+
help="安装fish shell的命令补全功能"
|
|
168
|
+
)
|
|
134
169
|
|
|
135
170
|
# 解析参数
|
|
136
171
|
args = parser.parse_args()
|
|
137
172
|
|
|
173
|
+
# 处理install命令
|
|
174
|
+
if args.install:
|
|
175
|
+
return install_fish_completion()
|
|
176
|
+
|
|
177
|
+
should_run = False
|
|
178
|
+
|
|
138
179
|
# 添加标准输入处理
|
|
139
180
|
if not args.request:
|
|
140
181
|
# 检查是否在交互式终端中运行
|
|
141
182
|
args.request = get_multiline_input(tip="请输入您要执行的功能:")
|
|
142
|
-
|
|
183
|
+
should_run = True
|
|
143
184
|
# 处理请求
|
|
144
185
|
command = process_request(args.request)
|
|
145
186
|
|
|
146
187
|
# 输出结果
|
|
147
188
|
if command:
|
|
148
|
-
execute_command(command) # 显示并执行命令
|
|
189
|
+
execute_command(command, should_run) # 显示并执行命令
|
|
149
190
|
return 0
|
|
150
191
|
else:
|
|
151
192
|
return 1
|
|
@@ -2,7 +2,6 @@ from typing import Dict, Any
|
|
|
2
2
|
import os
|
|
3
3
|
from jarvis.jarvis_code_agent.code_agent import CodeAgent
|
|
4
4
|
from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
|
|
5
|
-
from jarvis.jarvis_code_analysis.code_review import CodeReviewTool, extract_code_report
|
|
6
5
|
from jarvis.jarvis_utils.git_utils import get_latest_commit_hash, has_uncommitted_changes
|
|
7
6
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
8
7
|
|
|
@@ -69,23 +68,6 @@ class CreateCodeAgentTool:
|
|
|
69
68
|
# Get new commit hash after development
|
|
70
69
|
end_commit = get_latest_commit_hash()
|
|
71
70
|
|
|
72
|
-
# Step 3: Code Review
|
|
73
|
-
PrettyOutput.print("开始代码审查...", OutputType.INFO)
|
|
74
|
-
reviewer = CodeReviewTool()
|
|
75
|
-
review_result = reviewer.execute({
|
|
76
|
-
"review_type": "range",
|
|
77
|
-
"start_commit": start_commit,
|
|
78
|
-
"end_commit": end_commit,
|
|
79
|
-
"root_dir": root_dir
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
if not review_result["success"]:
|
|
83
|
-
return {
|
|
84
|
-
"success": False,
|
|
85
|
-
"stderr": "Code review failed: " + review_result["stderr"],
|
|
86
|
-
"stdout": ""
|
|
87
|
-
}
|
|
88
|
-
|
|
89
71
|
# Step 4: Generate Summary
|
|
90
72
|
summary = f"""开发总结:
|
|
91
73
|
|
|
@@ -95,8 +77,6 @@ class CreateCodeAgentTool:
|
|
|
95
77
|
需求:
|
|
96
78
|
{requirement}
|
|
97
79
|
|
|
98
|
-
代码审查结果:
|
|
99
|
-
{extract_code_report(review_result["stdout"])}
|
|
100
80
|
"""
|
|
101
81
|
|
|
102
82
|
return {
|
|
@@ -36,7 +36,8 @@ class FindMethodologyTool:
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
with yaspin(text="搜索相关方法论...", color="cyan") as spinner:
|
|
39
|
-
|
|
39
|
+
with spinner.hidden():
|
|
40
|
+
methodology_prompt = load_methodology(args["query"])
|
|
40
41
|
|
|
41
42
|
if methodology_prompt:
|
|
42
43
|
spinner.text = "找到相关方法论"
|
jarvis/jarvis_tools/registry.py
CHANGED
|
@@ -17,7 +17,8 @@ from jarvis.jarvis_utils.config import (
|
|
|
17
17
|
)
|
|
18
18
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
19
19
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
20
|
-
from jarvis.jarvis_utils.utils import
|
|
20
|
+
from jarvis.jarvis_utils.utils import init_env
|
|
21
|
+
from jarvis.jarvis_utils.tag import ot, ct
|
|
21
22
|
from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
|
|
22
23
|
from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
|
|
23
24
|
from jarvis.jarvis_mcp import McpClient
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""内置替换映射表模块。
|
|
2
|
+
|
|
3
|
+
该模块定义了Jarvis系统内置的默认替换映射表。
|
|
4
|
+
格式: {"标记名": {"template": "替换模板", "description": "描述信息"}}
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .tag import ot, ct
|
|
8
|
+
|
|
9
|
+
BUILTIN_REPLACE_MAP = {
|
|
10
|
+
"CodeBase": {
|
|
11
|
+
"append": True,
|
|
12
|
+
"template": f"""
|
|
13
|
+
请使用ask_codebase工具查询代码库,必须严格遵守以下工具调用格式:
|
|
14
|
+
|
|
15
|
+
{ot("TOOL_CALL")}
|
|
16
|
+
want: 想要从执行结果中获取到的信息
|
|
17
|
+
name: ask_codebase
|
|
18
|
+
arguments:
|
|
19
|
+
question: "与xxx功能相关的文件有哪些?"
|
|
20
|
+
{ct("TOOL_CALL")}
|
|
21
|
+
|
|
22
|
+
可以使用的提问格式包括:
|
|
23
|
+
1. 与xxx功能相关的文件有哪些?
|
|
24
|
+
2. 要实现xxx,应该要修改哪些文件?
|
|
25
|
+
3. xxx功能是怎么实现的?
|
|
26
|
+
4. xxx模块的入口函数是什么?
|
|
27
|
+
5. xxx功能的测试用例在哪里?
|
|
28
|
+
""",
|
|
29
|
+
"description": "查询代码库"
|
|
30
|
+
},
|
|
31
|
+
"Web": {
|
|
32
|
+
"append": True,
|
|
33
|
+
"template": f"""
|
|
34
|
+
请使用search_web工具进行网页搜索,必须严格遵守以下工具调用格式:
|
|
35
|
+
|
|
36
|
+
{ot("TOOL_CALL")}
|
|
37
|
+
want: 想要从执行结果中获取到的信息
|
|
38
|
+
name: search_web
|
|
39
|
+
arguments:
|
|
40
|
+
query: "xxx技术的最新发展是什么?"
|
|
41
|
+
{ct("TOOL_CALL")}
|
|
42
|
+
|
|
43
|
+
可以使用的提问格式包括:
|
|
44
|
+
1. xxx技术的最新发展是什么?
|
|
45
|
+
2. xxx框架的官方文档在哪里?
|
|
46
|
+
3. xxx库的GitHub仓库地址是什么?
|
|
47
|
+
4. xxx问题的解决方案有哪些?
|
|
48
|
+
5. xxx概念的详细解释是什么?
|
|
49
|
+
""",
|
|
50
|
+
"description": "网页搜索"
|
|
51
|
+
},
|
|
52
|
+
"Methodology": {
|
|
53
|
+
"append": True,
|
|
54
|
+
"template": f"""
|
|
55
|
+
请使用find_methodology工具查找相关方法论,必须严格遵守以下工具调用格式:
|
|
56
|
+
|
|
57
|
+
{ot("TOOL_CALL")}
|
|
58
|
+
want: 想要从执行结果中获取到的信息
|
|
59
|
+
name: find_methodology
|
|
60
|
+
arguments:
|
|
61
|
+
query: "关于xxx的方法论有哪些?"
|
|
62
|
+
{ct("TOOL_CALL")}
|
|
63
|
+
|
|
64
|
+
可以使用的提问格式包括:
|
|
65
|
+
1. 关于xxx的方法论有哪些?
|
|
66
|
+
2. 如何解决xxx问题?
|
|
67
|
+
3. xxx的最佳实践是什么?
|
|
68
|
+
4. 处理xxx的标准流程是什么?
|
|
69
|
+
5. 实现xxx的参考方案有哪些?
|
|
70
|
+
""",
|
|
71
|
+
"description": "查找相关方法论"
|
|
72
|
+
},
|
|
73
|
+
"Plan": {
|
|
74
|
+
"append": True,
|
|
75
|
+
"template": f"""
|
|
76
|
+
请使用code_plan工具生成代码修改计划,必须严格遵守以下工具调用格式:
|
|
77
|
+
|
|
78
|
+
{ot("TOOL_CALL")}
|
|
79
|
+
want: 想要从执行结果中获取到的信息
|
|
80
|
+
name: code_plan
|
|
81
|
+
arguments:
|
|
82
|
+
requirement: "需要实现用户登录功能,包括用户名密码验证和JWT生成"
|
|
83
|
+
{ct("TOOL_CALL")}
|
|
84
|
+
|
|
85
|
+
请提供详细的需求描述和完整上下文信息:
|
|
86
|
+
|
|
87
|
+
必须包含的上下文信息:
|
|
88
|
+
1. 当前会话状态 - 当前正在处理的任务和进度
|
|
89
|
+
2. 用户历史请求 - 与本任务相关的历史请求
|
|
90
|
+
3. 系统状态 - 相关的系统配置和环境状态
|
|
91
|
+
4. 已确定的相关文件 - 已经分析出的需要修改的文件列表
|
|
92
|
+
|
|
93
|
+
示例:
|
|
94
|
+
1. 需要实现用户登录功能,包括用户名密码验证和JWT生成
|
|
95
|
+
2. 重构订单处理模块以提高性能
|
|
96
|
+
3. 优化数据库查询性能,减少响应时间
|
|
97
|
+
4. 添加支付网关集成功能
|
|
98
|
+
5. 修改用户权限管理系统
|
|
99
|
+
|
|
100
|
+
code_plan工具将:
|
|
101
|
+
1. 分析项目结构确定相关文件
|
|
102
|
+
2. 理解需求后制定详细修改步骤
|
|
103
|
+
3. 按功能模块分组修改内容
|
|
104
|
+
4. 评估修改影响范围
|
|
105
|
+
5. 生成可执行的开发计划
|
|
106
|
+
""",
|
|
107
|
+
"description": "生成代码修改计划"
|
|
108
|
+
},
|
|
109
|
+
"FindRelatedFiles": {
|
|
110
|
+
"append": False,
|
|
111
|
+
"template": f"""
|
|
112
|
+
请使用工具在当前目录下查找与以下功能相关的文件:
|
|
113
|
+
"""
|
|
114
|
+
},
|
|
115
|
+
"FindMethodology": {
|
|
116
|
+
"append": False,
|
|
117
|
+
"template": f"""
|
|
118
|
+
请使用find_methodology工具查找相关方法论:
|
|
119
|
+
"""
|
|
120
|
+
},
|
|
121
|
+
"Dev": {
|
|
122
|
+
"append": False,
|
|
123
|
+
"template": f"""
|
|
124
|
+
请调用create_code_agent开发以下需求:
|
|
125
|
+
"""
|
|
126
|
+
},
|
|
127
|
+
"Fix": {
|
|
128
|
+
"append": False,
|
|
129
|
+
"template": f"""
|
|
130
|
+
请修复以下问题:
|
|
131
|
+
"""
|
|
132
|
+
}
|
|
133
|
+
}
|
jarvis/jarvis_utils/config.py
CHANGED
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
import os
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
from functools import lru_cache
|
|
3
|
+
import yaml
|
|
4
|
+
from .builtin_replace_map import BUILTIN_REPLACE_MAP
|
|
5
|
+
"""配置管理模块。
|
|
6
|
+
|
|
4
7
|
该模块提供了获取Jarvis系统各种配置设置的函数。
|
|
5
8
|
所有配置都从环境变量中读取,带有回退默认值。
|
|
6
|
-
该模块组织为以下几个类别:
|
|
7
|
-
- 系统配置
|
|
8
|
-
- 模型配置
|
|
9
|
-
- 执行配置
|
|
10
|
-
- 文本处理配置
|
|
11
9
|
"""
|
|
12
10
|
|
|
13
11
|
# 输出窗口预留大小
|
|
14
12
|
INPUT_WINDOW_REVERSE_SIZE = 2048
|
|
15
13
|
|
|
14
|
+
@lru_cache(maxsize=None)
|
|
15
|
+
def get_replace_map() -> dict:
|
|
16
|
+
"""
|
|
17
|
+
获取替换映射表。
|
|
18
|
+
|
|
19
|
+
从数据目录下的replace_map.yaml文件中读取替换映射表,
|
|
20
|
+
如果文件不存在则返回内置替换映射表。
|
|
21
|
+
|
|
22
|
+
返回:
|
|
23
|
+
dict: 合并后的替换映射表字典(内置+文件中的映射表)
|
|
24
|
+
"""
|
|
25
|
+
replace_map_path = os.path.join(get_data_dir(), 'replace_map.yaml')
|
|
26
|
+
if not os.path.exists(replace_map_path):
|
|
27
|
+
return BUILTIN_REPLACE_MAP.copy()
|
|
28
|
+
|
|
29
|
+
with open(replace_map_path, 'r', encoding='utf-8', errors='ignore') as file:
|
|
30
|
+
file_map = yaml.safe_load(file) or {}
|
|
31
|
+
return {**BUILTIN_REPLACE_MAP, **file_map}
|
|
32
|
+
|
|
16
33
|
def get_max_token_count() -> int:
|
|
17
34
|
"""
|
|
18
35
|
获取模型允许的最大token数量。
|
|
@@ -49,7 +66,8 @@ def get_shell_name() -> str:
|
|
|
49
66
|
返回:
|
|
50
67
|
str: Shell名称(例如bash, zsh),默认为bash
|
|
51
68
|
"""
|
|
52
|
-
|
|
69
|
+
shell_path = os.getenv('SHELL', '/bin/bash')
|
|
70
|
+
return os.path.basename(shell_path)
|
|
53
71
|
def get_normal_platform_name() -> str:
|
|
54
72
|
"""
|
|
55
73
|
获取正常操作的平台名称。
|
jarvis/jarvis_utils/input.py
CHANGED
|
@@ -16,6 +16,8 @@ from prompt_toolkit.key_binding import KeyBindings
|
|
|
16
16
|
from fuzzywuzzy import process
|
|
17
17
|
from colorama import Fore, Style as ColoramaStyle
|
|
18
18
|
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
19
|
+
from jarvis.jarvis_utils.tag import ot
|
|
20
|
+
from jarvis.jarvis_utils.config import get_replace_map
|
|
19
21
|
def get_single_line_input(tip: str) -> str:
|
|
20
22
|
"""
|
|
21
23
|
获取支持历史记录的单行输入。
|
|
@@ -45,6 +47,7 @@ class FileCompleter(Completer):
|
|
|
45
47
|
self.path_completer = PathCompleter()
|
|
46
48
|
self.max_suggestions = 10
|
|
47
49
|
self.min_score = 10
|
|
50
|
+
self.replace_map = get_replace_map()
|
|
48
51
|
def get_completions(self, document: Document, complete_event) -> Completion: # type: ignore
|
|
49
52
|
"""
|
|
50
53
|
生成带有模糊匹配的文件路径补全建议。
|
|
@@ -71,30 +74,35 @@ class FileCompleter(Completer):
|
|
|
71
74
|
text_after_at = text[current_at_pos + 1:cursor_pos]
|
|
72
75
|
if ' ' in text_after_at:
|
|
73
76
|
return
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
from jarvis.jarvis_utils.utils import ot
|
|
78
|
-
default_suggestions = [
|
|
79
|
-
(ot("CodeBase"), '查询代码库'),
|
|
80
|
-
(ot("Web"), '网页搜索'),
|
|
81
|
-
(ot("Summary"), '总结'),
|
|
82
|
-
(ot("Clear"), '清除历史'),
|
|
83
|
-
(ot("Methodology"), '查找相关方法论'),
|
|
84
|
-
(ot("Plan"), '生成代码修改计划'),
|
|
85
|
-
]
|
|
86
|
-
for name, desc in default_suggestions:
|
|
87
|
-
yield Completion(
|
|
88
|
-
text=f"'{name}'",
|
|
89
|
-
start_position=-1,
|
|
90
|
-
display=name,
|
|
91
|
-
display_meta=desc
|
|
92
|
-
) # type: ignore
|
|
93
|
-
return
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
94
80
|
# 获取当前@之后的文本
|
|
95
81
|
file_path = text_after_at.strip()
|
|
96
82
|
# 计算替换长度
|
|
97
83
|
replace_length = len(text_after_at) + 1
|
|
84
|
+
|
|
85
|
+
# 从replace_map获取建议列表
|
|
86
|
+
default_suggestions = [
|
|
87
|
+
(ot(tag), desc) for tag, desc in [
|
|
88
|
+
(tag, self._get_description(tag))
|
|
89
|
+
for tag in self.replace_map.keys()
|
|
90
|
+
]
|
|
91
|
+
]
|
|
92
|
+
# 添加特殊标记
|
|
93
|
+
default_suggestions.extend([
|
|
94
|
+
(ot("Summary"), '总结'),
|
|
95
|
+
(ot("Clear"), '清除历史'),
|
|
96
|
+
])
|
|
97
|
+
for name, desc in default_suggestions:
|
|
98
|
+
yield Completion(
|
|
99
|
+
text=f"'{name}'",
|
|
100
|
+
start_position=-replace_length,
|
|
101
|
+
display=name,
|
|
102
|
+
display_meta=desc
|
|
103
|
+
) # type: ignore
|
|
104
|
+
|
|
105
|
+
|
|
98
106
|
# 使用git ls-files获取所有可能的文件
|
|
99
107
|
all_files = []
|
|
100
108
|
try:
|
|
@@ -127,6 +135,12 @@ class FileCompleter(Completer):
|
|
|
127
135
|
display=display_text,
|
|
128
136
|
display_meta="File"
|
|
129
137
|
) # type: ignore
|
|
138
|
+
|
|
139
|
+
def _get_description(self, tag: str) -> str:
|
|
140
|
+
"""获取标记的描述信息"""
|
|
141
|
+
if tag in self.replace_map:
|
|
142
|
+
return self.replace_map[tag].get("description", tag) + "(Append)" if "append" in self.replace_map[tag] and self.replace_map[tag]["append"] else "(Replace)"
|
|
143
|
+
return tag
|
|
130
144
|
def get_multiline_input(tip: str) -> str:
|
|
131
145
|
"""
|
|
132
146
|
获取带有增强补全和确认功能的多行输入。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
def ot(tag_name: str) -> str:
|
|
2
|
+
"""生成HTML标签开始标记
|
|
3
|
+
|
|
4
|
+
参数:
|
|
5
|
+
tag_name -- HTML标签名称
|
|
6
|
+
|
|
7
|
+
返回:
|
|
8
|
+
格式化的开始标签字符串
|
|
9
|
+
"""
|
|
10
|
+
return f"<{tag_name}>"
|
|
11
|
+
|
|
12
|
+
def ct(tag_name: str) -> str:
|
|
13
|
+
"""生成HTML标签结束标记
|
|
14
|
+
|
|
15
|
+
参数:
|
|
16
|
+
tag_name -- HTML标签名称
|
|
17
|
+
|
|
18
|
+
返回:
|
|
19
|
+
格式化的结束标签字符串
|
|
20
|
+
"""
|
|
21
|
+
return f"</{tag_name}>"
|
jarvis/jarvis_utils/utils.py
CHANGED
|
@@ -130,25 +130,3 @@ def is_long_context(files: List[str]) -> bool:
|
|
|
130
130
|
return total_tokens > threshold
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
def ot(tag_name: str) -> str:
|
|
134
|
-
"""生成HTML标签开始标记
|
|
135
|
-
|
|
136
|
-
参数:
|
|
137
|
-
tag_name -- HTML标签名称
|
|
138
|
-
|
|
139
|
-
返回:
|
|
140
|
-
格式化的开始标签字符串
|
|
141
|
-
"""
|
|
142
|
-
return f"<{tag_name}>"
|
|
143
|
-
|
|
144
|
-
def ct(tag_name: str) -> str:
|
|
145
|
-
"""生成HTML标签结束标记
|
|
146
|
-
|
|
147
|
-
参数:
|
|
148
|
-
tag_name -- HTML标签名称
|
|
149
|
-
|
|
150
|
-
返回:
|
|
151
|
-
格式化的结束标签字符串
|
|
152
|
-
"""
|
|
153
|
-
return f"</{tag_name}>"
|
|
154
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jarvis-ai-assistant
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.156
|
|
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
|
|
@@ -189,19 +189,19 @@ jarvis-methodology --help
|
|
|
189
189
|
|
|
190
190
|
## ⚙️ 配置说明 <a id="configuration"></a>
|
|
191
191
|
### 环境变量配置
|
|
192
|
-
|
|
|
193
|
-
|
|
194
|
-
|
|
|
195
|
-
|
|
|
196
|
-
|
|
|
197
|
-
|
|
|
198
|
-
|
|
|
199
|
-
|
|
|
200
|
-
|
|
|
201
|
-
|
|
|
202
|
-
|
|
|
203
|
-
|
|
|
204
|
-
|
|
|
192
|
+
| 变量名称 | 默认值 | 说明 |
|
|
193
|
+
|----------|--------|------|
|
|
194
|
+
| `JARVIS_MAX_TOKEN_COUNT` | 102400000 | 上下文窗口的最大token数量 |
|
|
195
|
+
| `JARVIS_MAX_INPUT_TOKEN_COUNT` | 32000 | 输入的最大token数量 |
|
|
196
|
+
| `JARVIS_AUTO_COMPLETE` | false | 是否启用自动完成功能(任务判定完成的时候会自动终止) |
|
|
197
|
+
| `JARVIS_SHELL_NAME` | bash | 系统shell名称 |
|
|
198
|
+
| `JARVIS_PLATFORM` | yuanbao | 默认AI平台 |
|
|
199
|
+
| `JARVIS_MODEL` | deep_seek_v3 | 默认模型 |
|
|
200
|
+
| `JARVIS_THINKING_PLATFORM` | JARVIS_PLATFORM | 推理任务使用的平台 |
|
|
201
|
+
| `JARVIS_THINKING_MODEL` | JARVIS_MODEL | 推理任务使用的模型 |
|
|
202
|
+
| `JARVIS_EXECUTE_TOOL_CONFIRM` | false | 执行工具前是否需要确认 |
|
|
203
|
+
| `JARVIS_CONFIRM_BEFORE_APPLY_PATCH` | true | 应用补丁前是否需要确认 |
|
|
204
|
+
| `JARVIS_MAX_TOOL_CALL_COUNT` | 20 | 最大连续工具调用次数 |
|
|
205
205
|
|
|
206
206
|
|
|
207
207
|
---
|
|
@@ -227,6 +227,37 @@ jarvis-methodology --help
|
|
|
227
227
|
| virtual_tty | 控制虚拟终端执行各种操作,如启动终端、输入命令、获取输出等。 |
|
|
228
228
|
|
|
229
229
|
|
|
230
|
+
### 命令替换功能
|
|
231
|
+
Jarvis支持使用特殊标记`'<tag>'`来触发命令替换功能,其中`tag`是预定义的标记名称。系统会自动将这些标记替换为预定义的模板内容。
|
|
232
|
+
|
|
233
|
+
#### 内置标记
|
|
234
|
+
| 标记 | 功能 |
|
|
235
|
+
|------|------|
|
|
236
|
+
| `'Summary'` | 总结当前会话并清空历史记录 |
|
|
237
|
+
| `'Clear'` | 清空当前会话 |
|
|
238
|
+
| `'CodeBase'` | 查询代码库 |
|
|
239
|
+
| `'Web'` | 网页搜索 |
|
|
240
|
+
| `'Methodology'` | 查找相关方法论 |
|
|
241
|
+
| `'Plan'` | 生成代码修改计划 |
|
|
242
|
+
| `'FindRelatedFiles'` | 查找相关文件 |
|
|
243
|
+
| `'FindMethodology'` | 查找方法论 |
|
|
244
|
+
| `'Dev'` | 调用create_code_agent开发需求 |
|
|
245
|
+
| `'Fix'` | 修复问题 |
|
|
246
|
+
|
|
247
|
+
#### 自定义替换
|
|
248
|
+
可以通过在`~/.jarvis/replace_map.yaml`文件中添加自定义替换规则:
|
|
249
|
+
```yaml
|
|
250
|
+
tag_name:
|
|
251
|
+
template: "替换后的内容"
|
|
252
|
+
description: "标记描述"
|
|
253
|
+
append: false # 可选,true表示追加到输入末尾,false表示直接替换
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
#### 文件路径补全
|
|
258
|
+
在交互式输入中,输入`@`可以触发文件路径补全功能,支持模糊匹配。
|
|
259
|
+
|
|
260
|
+
|
|
230
261
|
### 工具位置
|
|
231
262
|
- 内置工具:`src/jarvis/tools/`
|
|
232
263
|
- 用户工具:`~/.jarvis/tools/`
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
jarvis/__init__.py,sha256=
|
|
2
|
-
jarvis/jarvis_agent/__init__.py,sha256=
|
|
3
|
-
jarvis/jarvis_agent/builtin_input_handler.py,sha256=
|
|
1
|
+
jarvis/__init__.py,sha256=zOb8b4lhgGPfSpvH6W1CW1ovF70mzNUb0nufgXh-ZTw,50
|
|
2
|
+
jarvis/jarvis_agent/__init__.py,sha256=Ur28Tb8oCS8wXWRdRevf1TJOyVb-xycCIJ_KoscIQMw,25336
|
|
3
|
+
jarvis/jarvis_agent/builtin_input_handler.py,sha256=3rRA-7v_VUSFG1s7tTKhriq9vv0nsa3t69ReV0xH5gs,1505
|
|
4
4
|
jarvis/jarvis_agent/file_input_handler.py,sha256=auBbBfS4Ux5ksczeRe9LtsmMm4hKrPxinW5leE9Rtyc,3575
|
|
5
|
-
jarvis/jarvis_agent/jarvis.py,sha256=
|
|
5
|
+
jarvis/jarvis_agent/jarvis.py,sha256=6Bp_Y-E3RN6bDmDs5lN3uALL_Dhq-p_aIuVNELG1vtw,5898
|
|
6
6
|
jarvis/jarvis_agent/main.py,sha256=Jlw_Tofh2C-sMVnkeOZBrwWJOWNH3IhsKDUn-WBlgU8,2602
|
|
7
7
|
jarvis/jarvis_agent/output_handler.py,sha256=4limQ-Kf-YYvQjT5SMjJIyyvD1DVG8tINv1A_qbv4ho,405
|
|
8
|
-
jarvis/jarvis_agent/patch.py,sha256=
|
|
8
|
+
jarvis/jarvis_agent/patch.py,sha256=nbfR_qmt3P5nUzZC-h6ypX4UQ6Aoj2QiNyq_Hy7e6-U,23619
|
|
9
9
|
jarvis/jarvis_agent/shell_input_handler.py,sha256=9IoGQCe6FF4HA2V5S11q63AtnWDZFpNeRd3hcqCAlBw,1237
|
|
10
10
|
jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
jarvis/jarvis_code_agent/code_agent.py,sha256=
|
|
12
|
-
jarvis/jarvis_code_analysis/code_review.py,sha256=
|
|
11
|
+
jarvis/jarvis_code_agent/code_agent.py,sha256=vi_g-LWdD5nn3RQsC1X8G2iNK8SrBADwFLUkflqtvKE,13723
|
|
12
|
+
jarvis/jarvis_code_analysis/code_review.py,sha256=4e6PVxt7LwAqvKNI2VeOTH3iUFGXb7Fkm5GqtT5RTtQ,29767
|
|
13
13
|
jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=PCjlyxLa939613cAzS7pfEPgP57setO-1RvcdzzPivw,54
|
|
14
14
|
jarvis/jarvis_code_analysis/checklists/c_cpp.py,sha256=8lfWmhImAxeTBdHPOgVXDjMllaq280Qki1ZOOSDBnvk,1293
|
|
15
15
|
jarvis/jarvis_code_analysis/checklists/csharp.py,sha256=fg35Iima2nIsirEmAjianfAybVjwRYml9BtbSQFff7w,2396
|
|
@@ -35,7 +35,7 @@ jarvis/jarvis_git_details/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
|
35
35
|
jarvis/jarvis_git_details/main.py,sha256=YowncVxYyJ3y2EvGrZhAJeR4yizXp6aB3dqvoYTepFY,6117
|
|
36
36
|
jarvis/jarvis_git_squash/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
37
|
jarvis/jarvis_git_squash/main.py,sha256=xBNkAl7_8_pQC-C6RcUImA1mEU4KTqhjtA57rG_mMJ8,2179
|
|
38
|
-
jarvis/jarvis_git_utils/git_commiter.py,sha256=
|
|
38
|
+
jarvis/jarvis_git_utils/git_commiter.py,sha256=YjDPJEVhBkbg961s1T5fMtof5TFVeJqy6MvDotCt3CY,11131
|
|
39
39
|
jarvis/jarvis_lsp/base.py,sha256=f-76xgNijfQ4G3Q0t8IfOGtCu-q2TSQ7a_in6XwDb_8,2030
|
|
40
40
|
jarvis/jarvis_lsp/cpp.py,sha256=ekci2M9_UtkCSEe9__72h26Gat93r9_knL2VmFr8X5M,3141
|
|
41
41
|
jarvis/jarvis_lsp/go.py,sha256=sSypuQSP5X2YtrVMC8XCc5nXkgfG93SO7sC89lHzoR8,3458
|
|
@@ -49,46 +49,48 @@ jarvis/jarvis_methodology/main.py,sha256=IBv87UOmdCailgooMtWEcqZcQHmNLhZD-kkGw5j
|
|
|
49
49
|
jarvis/jarvis_multi_agent/__init__.py,sha256=SX8lBErhltKyYRM-rymrMz3sJ0Zl3hBXrpsPdFgzkQc,4399
|
|
50
50
|
jarvis/jarvis_multi_agent/main.py,sha256=aGuUC3YQmahabqwDwZXJjfQLYsZ3KIZdf8DZDlVNMe4,1543
|
|
51
51
|
jarvis/jarvis_platform/__init__.py,sha256=WIJtD5J7lOrWLX2bsgZGkmlMcN0NOJsnh_reybmHPjg,58
|
|
52
|
-
jarvis/jarvis_platform/base.py,sha256=
|
|
52
|
+
jarvis/jarvis_platform/base.py,sha256=AKsqWU7K4LdVw5JldFKpgTUyQc28mnWoRDQAUnDbihE,3263
|
|
53
53
|
jarvis/jarvis_platform/kimi.py,sha256=h1BP0vey30upZ9g-b8pU87rQGd3fHcgAQo_51Nv9DZY,16697
|
|
54
54
|
jarvis/jarvis_platform/registry.py,sha256=wvXTKXqAoW6GPaLKCPYhRB9QhVe1xfoVbVPBZAxl_uA,7716
|
|
55
55
|
jarvis/jarvis_platform/yuanbao.py,sha256=X2lYZ3SxBzdaCwd5ooq9fxYbu14RUpeDILYg0W5W7Xc,21902
|
|
56
56
|
jarvis/jarvis_platform_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
|
-
jarvis/jarvis_platform_manager/main.py,sha256=
|
|
57
|
+
jarvis/jarvis_platform_manager/main.py,sha256=xJM86DQFyYDysMyQEJDAwB2oSYcWg_zi1mFld0zyquM,22572
|
|
58
58
|
jarvis/jarvis_smart_shell/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
59
|
-
jarvis/jarvis_smart_shell/main.py,sha256=
|
|
59
|
+
jarvis/jarvis_smart_shell/main.py,sha256=COktOt0BJCFLsftP1T-1LzJ-oUpjOojfCydOQF-A2OI,5590
|
|
60
60
|
jarvis/jarvis_tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
61
61
|
jarvis/jarvis_tools/ask_codebase.py,sha256=S6NArvKZyK8WEbsEgeGCljjg4D9mteWrq9m352V58jU,9635
|
|
62
62
|
jarvis/jarvis_tools/ask_user.py,sha256=NjxTCHGKo4nthbEQD-isvPCW4PQhTcekEferjnukX70,2143
|
|
63
63
|
jarvis/jarvis_tools/base.py,sha256=vskI4czVdlhbo38ODuF9rFrnWBYQIhJSPAqAkLVcyTs,1165
|
|
64
64
|
jarvis/jarvis_tools/chdir.py,sha256=do_OdtabiH3lZcT_ynjSAX66XgH2gPl9mYiS7dMMDa8,2682
|
|
65
65
|
jarvis/jarvis_tools/code_plan.py,sha256=jNa2rs4J3Fam8Q_RHE2_QvVch21TPp-Zfv-W6iQ3D_0,7729
|
|
66
|
-
jarvis/jarvis_tools/create_code_agent.py,sha256=
|
|
66
|
+
jarvis/jarvis_tools/create_code_agent.py,sha256=SRiQXZf57ViIDh6YSEmJkcoSKft0-y3iDfWF8f1bvZU,3387
|
|
67
67
|
jarvis/jarvis_tools/create_sub_agent.py,sha256=wGiHukvi58wb1AKW5beP7R8VvApOn8TOeGmtXsmcETE,3001
|
|
68
68
|
jarvis/jarvis_tools/execute_script.py,sha256=3sR_u6-SLbzmcUbXjHLN-rGjoelIj4uAefys5la_x7o,6759
|
|
69
69
|
jarvis/jarvis_tools/file_analyzer.py,sha256=XCsFB4dZ9qy2q929hqi1rTngj6AtRtIaPx_W7lJAcpQ,4814
|
|
70
70
|
jarvis/jarvis_tools/file_operation.py,sha256=sB1x0zI1dULXV7FG17wkiMQ7mQAEnXVd_5rakQ0Thik,9109
|
|
71
|
-
jarvis/jarvis_tools/find_methodology.py,sha256=
|
|
71
|
+
jarvis/jarvis_tools/find_methodology.py,sha256=TIUrezAql6wY3-wqnOPfGrO0tqS5N_-eU6YimCzaepM,2268
|
|
72
72
|
jarvis/jarvis_tools/lsp_get_diagnostics.py,sha256=IYqv8jQwSK71sZpDBRolSDnYii8t0M7fzLthhMYTeGk,5322
|
|
73
73
|
jarvis/jarvis_tools/methodology.py,sha256=gnlJojY4Dg5v9AAB5xcpKqpPIHs0tOYVtzTHkwOrWk0,5214
|
|
74
74
|
jarvis/jarvis_tools/read_code.py,sha256=_X6D3AIgRD9YplSDnFhXOm8wQAZMA3pkkXy31SG33l0,6041
|
|
75
75
|
jarvis/jarvis_tools/read_webpage.py,sha256=2QF0zAyApl0bOr9604aml_uuqBZcPefVuHvRfWzrnzk,2598
|
|
76
|
-
jarvis/jarvis_tools/registry.py,sha256=
|
|
76
|
+
jarvis/jarvis_tools/registry.py,sha256=82rsRFNWJkijH9YP3t4yt6eUs3KgIp633R5goVLUcTQ,25650
|
|
77
77
|
jarvis/jarvis_tools/search_web.py,sha256=kWW9K2QUR2AxPq6gcyx4Bgy-0Y4gzcdErq1DNT1EYM4,1333
|
|
78
78
|
jarvis/jarvis_tools/virtual_tty.py,sha256=Rpn9VXUG17LQsY87F_O6UCjN_opXB05mpwozxYf-xVI,16372
|
|
79
79
|
jarvis/jarvis_utils/__init__.py,sha256=KMg-KY5rZIhGTeOD5e2Xo5CU7DX1DUz4ULWAaTQ-ZNw,825
|
|
80
|
-
jarvis/jarvis_utils/
|
|
80
|
+
jarvis/jarvis_utils/builtin_replace_map.py,sha256=UnpD0_dS_lhSOVGuEmdVOLtb_e8XKXGycyq8GO6QMDw,3835
|
|
81
|
+
jarvis/jarvis_utils/config.py,sha256=40ODLYVysDiuVN2avlGKILaCIJB1_iOWReWoKYwuniM,4040
|
|
81
82
|
jarvis/jarvis_utils/embedding.py,sha256=_Q-VurYHQZSsyISClTFjadDaNqNPBMqJe58lMM6bsVs,6991
|
|
82
83
|
jarvis/jarvis_utils/file_processors.py,sha256=oNtVlz2JHcQ60NS6sgI-VsvYXOnsQgFUEVenznCXHC4,2952
|
|
83
84
|
jarvis/jarvis_utils/git_utils.py,sha256=j_Jw6h7JD91XhMf0WD3MAH4URkLUBrrYCLnuLm1GeN4,5630
|
|
84
85
|
jarvis/jarvis_utils/globals.py,sha256=Ed2d6diWXCgI74HVV_tI4qW7yXxLpNvQKN2yG0IH9hc,3388
|
|
85
|
-
jarvis/jarvis_utils/input.py,sha256=
|
|
86
|
+
jarvis/jarvis_utils/input.py,sha256=zvL-JQSJvkmsZB7ApJsaVpk46BkpmJA3I_BnWSl_D-4,7299
|
|
86
87
|
jarvis/jarvis_utils/methodology.py,sha256=XayEVGXP5RfDBWj4bMOVFWplyrSp4GsXHwOTWoR4BLk,6418
|
|
87
88
|
jarvis/jarvis_utils/output.py,sha256=BmWdB1bmizv0xfU4Z___9p_xQodorriIcEgADVq9fk0,8416
|
|
88
|
-
jarvis/jarvis_utils/
|
|
89
|
-
|
|
90
|
-
jarvis_ai_assistant-0.1.
|
|
91
|
-
jarvis_ai_assistant-0.1.
|
|
92
|
-
jarvis_ai_assistant-0.1.
|
|
93
|
-
jarvis_ai_assistant-0.1.
|
|
94
|
-
jarvis_ai_assistant-0.1.
|
|
89
|
+
jarvis/jarvis_utils/tag.py,sha256=YtXBYuZWy8j8YbeQX2qRrHRQl6Gp2Vt7W4p-2yjo0a4,405
|
|
90
|
+
jarvis/jarvis_utils/utils.py,sha256=fNZjDj-qP0cum1RfWmI8D5VVgqT-tBUPsc8n_XPGLQY,4246
|
|
91
|
+
jarvis_ai_assistant-0.1.156.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
|
92
|
+
jarvis_ai_assistant-0.1.156.dist-info/METADATA,sha256=9SIN10_orqLOnBlxHwILAPhiVxZMVu91zz_waOEl4KM,12438
|
|
93
|
+
jarvis_ai_assistant-0.1.156.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
|
|
94
|
+
jarvis_ai_assistant-0.1.156.dist-info/entry_points.txt,sha256=cKz_9SEpOvElTubKPMZMAdskD4GHz-NyKWRNssIVAWE,973
|
|
95
|
+
jarvis_ai_assistant-0.1.156.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
|
96
|
+
jarvis_ai_assistant-0.1.156.dist-info/RECORD,,
|
{jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{jarvis_ai_assistant-0.1.154.dist-info → jarvis_ai_assistant-0.1.156.dist-info}/top_level.txt
RENAMED
|
File without changes
|