jarvis-ai-assistant 0.1.125__py3-none-any.whl → 0.1.128__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 +205 -187
- jarvis/jarvis_code_agent/code_agent.py +116 -109
- jarvis/jarvis_code_agent/patch.py +157 -138
- jarvis/jarvis_code_agent/shell_input_handler.py +22 -0
- jarvis/jarvis_codebase/main.py +314 -288
- jarvis/jarvis_dev/main.py +695 -716
- jarvis/jarvis_lsp/base.py +0 -12
- jarvis/jarvis_lsp/cpp.py +0 -9
- jarvis/jarvis_lsp/go.py +0 -9
- jarvis/jarvis_lsp/python.py +0 -28
- jarvis/jarvis_lsp/registry.py +0 -1
- jarvis/jarvis_lsp/rust.py +0 -9
- jarvis/jarvis_multi_agent/__init__.py +52 -52
- jarvis/jarvis_platform/base.py +6 -5
- jarvis/jarvis_platform_manager/main.py +1 -1
- jarvis/jarvis_rag/main.py +250 -186
- jarvis/jarvis_smart_shell/main.py +0 -1
- jarvis/jarvis_tools/ask_codebase.py +10 -9
- jarvis/jarvis_tools/ask_user.py +2 -2
- jarvis/jarvis_tools/base.py +4 -4
- jarvis/jarvis_tools/chdir.py +28 -28
- jarvis/jarvis_tools/code_review.py +44 -39
- jarvis/jarvis_tools/create_code_agent.py +4 -4
- jarvis/jarvis_tools/create_sub_agent.py +7 -7
- jarvis/jarvis_tools/execute_shell.py +53 -23
- jarvis/jarvis_tools/execute_shell_script.py +3 -3
- jarvis/jarvis_tools/file_operation.py +70 -41
- jarvis/jarvis_tools/git_commiter.py +61 -51
- jarvis/jarvis_tools/lsp_find_definition.py +7 -7
- jarvis/jarvis_tools/lsp_prepare_rename.py +7 -7
- jarvis/jarvis_tools/methodology.py +6 -6
- jarvis/jarvis_tools/rag.py +5 -5
- jarvis/jarvis_tools/read_webpage.py +52 -32
- jarvis/jarvis_tools/registry.py +167 -180
- jarvis/jarvis_tools/search_web.py +66 -41
- jarvis/jarvis_tools/select_code_files.py +3 -3
- jarvis/jarvis_tools/tool_generator.py +68 -55
- jarvis/jarvis_utils/methodology.py +77 -59
- jarvis/jarvis_utils/output.py +1 -0
- {jarvis_ai_assistant-0.1.125.dist-info → jarvis_ai_assistant-0.1.128.dist-info}/METADATA +31 -17
- jarvis_ai_assistant-0.1.128.dist-info/RECORD +74 -0
- {jarvis_ai_assistant-0.1.125.dist-info → jarvis_ai_assistant-0.1.128.dist-info}/WHEEL +1 -1
- jarvis/jarvis_tools/lsp_validate_edit.py +0 -141
- jarvis/jarvis_tools/read_code.py +0 -192
- jarvis_ai_assistant-0.1.125.dist-info/RECORD +0 -75
- {jarvis_ai_assistant-0.1.125.dist-info → jarvis_ai_assistant-0.1.128.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.125.dist-info → jarvis_ai_assistant-0.1.128.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.125.dist-info → jarvis_ai_assistant-0.1.128.dist-info}/top_level.txt +0 -0
|
@@ -4,6 +4,7 @@ import subprocess
|
|
|
4
4
|
from typing import Dict, Any
|
|
5
5
|
import tempfile
|
|
6
6
|
import yaml
|
|
7
|
+
from yaspin import yaspin
|
|
7
8
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
8
9
|
import sys
|
|
9
10
|
import argparse
|
|
@@ -15,13 +16,13 @@ from jarvis.jarvis_utils.utils import init_env
|
|
|
15
16
|
|
|
16
17
|
class GitCommitTool:
|
|
17
18
|
name = "git_commit_agent"
|
|
18
|
-
description = "
|
|
19
|
+
description = "根据代码变更自动生成并执行Git提交"
|
|
19
20
|
parameters = {
|
|
20
21
|
"type": "object",
|
|
21
22
|
"properties": {
|
|
22
23
|
"lang": {
|
|
23
24
|
"type": "string",
|
|
24
|
-
"description": "
|
|
25
|
+
"description": "提交信息的语言",
|
|
25
26
|
"default": "Chinese"
|
|
26
27
|
}
|
|
27
28
|
},
|
|
@@ -54,59 +55,68 @@ class GitCommitTool:
|
|
|
54
55
|
PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
|
|
55
56
|
return {"success": True, "stdout": "No changes to commit", "stderr": ""}
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
stdout=subprocess.DEVNULL,
|
|
61
|
-
stderr=subprocess.DEVNULL
|
|
62
|
-
).wait()
|
|
63
|
-
|
|
64
|
-
PrettyOutput.print("获取差异...", OutputType.SYSTEM)
|
|
65
|
-
process = subprocess.Popen(
|
|
66
|
-
["git", "diff", "--cached", "--exit-code"],
|
|
67
|
-
stdout=subprocess.PIPE,
|
|
68
|
-
stderr=subprocess.PIPE
|
|
69
|
-
)
|
|
70
|
-
diff = process.communicate()[0].decode()
|
|
71
|
-
PrettyOutput.print(diff, OutputType.CODE, lang="diff")
|
|
72
|
-
|
|
73
|
-
prompt = f'''Generate commit message by the following rules:
|
|
74
|
-
You should write commit message in {args.get('lang', 'Chinese')}
|
|
75
|
-
# Required Structure
|
|
76
|
-
YOU MUST USE EXACTLY THIS FORMAT:
|
|
77
|
-
<COMMIT_MESSAGE>
|
|
78
|
-
<type>(<scope>): <subject>
|
|
79
|
-
Body description in imperative mood
|
|
80
|
-
</COMMIT_MESSAGE>
|
|
81
|
-
# Format Rules
|
|
82
|
-
1. Types: fix, feat, docs, style, refactor, test, chore
|
|
83
|
-
2. Scope indicates module (e.g. auth, database)
|
|
84
|
-
3. Subject line <= 72 chars, no period
|
|
85
|
-
4. Body explains WHAT and WHY for every change, using present tense
|
|
86
|
-
5. Do not omit any changes
|
|
87
|
-
# Analysis Material
|
|
88
|
-
{diff}
|
|
89
|
-
'''
|
|
90
|
-
|
|
91
|
-
PrettyOutput.print("生成提交消息...", OutputType.SYSTEM)
|
|
92
|
-
platform = PlatformRegistry().get_codegen_platform()
|
|
93
|
-
platform.set_suppress_output(True)
|
|
94
|
-
commit_message = platform.chat_until_success(prompt)
|
|
95
|
-
commit_message = self._extract_commit_message(commit_message)
|
|
96
|
-
|
|
97
|
-
# 使用临时文件处理提交消息
|
|
98
|
-
with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
|
|
99
|
-
tmp_file.write(commit_message)
|
|
100
|
-
tmp_file.flush() # 确保内容写入文件
|
|
101
|
-
commit_cmd = ["git", "commit", "-F", tmp_file.name]
|
|
102
|
-
PrettyOutput.print("提交...", OutputType.INFO)
|
|
58
|
+
with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
|
|
59
|
+
# 添加文件
|
|
60
|
+
spinner.text = "正在添加文件到提交..."
|
|
103
61
|
subprocess.Popen(
|
|
104
|
-
|
|
62
|
+
["git", "add", "."],
|
|
105
63
|
stdout=subprocess.DEVNULL,
|
|
106
64
|
stderr=subprocess.DEVNULL
|
|
107
65
|
).wait()
|
|
66
|
+
spinner.write("✅ 添加文件到提交")
|
|
67
|
+
|
|
68
|
+
# 获取差异
|
|
69
|
+
spinner.text = "正在获取代码差异..."
|
|
70
|
+
process = subprocess.Popen(
|
|
71
|
+
["git", "diff", "--cached", "--exit-code"],
|
|
72
|
+
stdout=subprocess.PIPE,
|
|
73
|
+
stderr=subprocess.PIPE
|
|
74
|
+
)
|
|
75
|
+
diff = process.communicate()[0].decode()
|
|
76
|
+
spinner.write("✅ 获取差异")
|
|
77
|
+
|
|
78
|
+
# 生成提交信息
|
|
79
|
+
spinner.text = "正在生成提交消息..."
|
|
80
|
+
prompt = f'''根据以下规则生成提交信息:
|
|
81
|
+
提交信息应使用{args.get('lang', '中文')}书写
|
|
82
|
+
# 必需结构
|
|
83
|
+
必须使用以下格式:
|
|
84
|
+
<COMMIT_MESSAGE>
|
|
85
|
+
<类型>(<范围>): <主题>
|
|
86
|
+
使用祈使语气描述变更内容
|
|
87
|
+
</COMMIT_MESSAGE>
|
|
88
|
+
# 格式规则
|
|
89
|
+
1. 类型: fix, feat, docs, style, refactor, test, chore
|
|
90
|
+
2. 范围表示模块 (例如: auth, database)
|
|
91
|
+
3. 主题行 <= 72个字符,不以句号结尾
|
|
92
|
+
4. 正文使用现在时态解释每个变更的内容和原因
|
|
93
|
+
5. 不要遗漏任何变更
|
|
94
|
+
# 分析材料
|
|
95
|
+
{diff}
|
|
96
|
+
'''
|
|
97
|
+
platform = PlatformRegistry().get_codegen_platform()
|
|
98
|
+
commit_message = platform.chat_until_success(prompt)
|
|
99
|
+
commit_message = self._extract_commit_message(commit_message)
|
|
100
|
+
spinner.write("✅ 生成提交消息")
|
|
101
|
+
|
|
102
|
+
# 执行提交
|
|
103
|
+
spinner.text = "正在准备提交..."
|
|
104
|
+
with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
|
|
105
|
+
tmp_file.write(commit_message)
|
|
106
|
+
tmp_file.flush()
|
|
107
|
+
spinner.text = "正在执行提交..."
|
|
108
|
+
commit_cmd = ["git", "commit", "-F", tmp_file.name]
|
|
109
|
+
subprocess.Popen(
|
|
110
|
+
commit_cmd,
|
|
111
|
+
stdout=subprocess.DEVNULL,
|
|
112
|
+
stderr=subprocess.DEVNULL
|
|
113
|
+
).wait()
|
|
114
|
+
spinner.write("✅ 提交")
|
|
115
|
+
|
|
116
|
+
commit_hash = self._get_last_commit_hash()
|
|
117
|
+
spinner.text = "完成提交"
|
|
118
|
+
spinner.ok("✅")
|
|
108
119
|
|
|
109
|
-
commit_hash = self._get_last_commit_hash()
|
|
110
120
|
PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
|
|
111
121
|
|
|
112
122
|
return {
|
|
@@ -116,7 +126,7 @@ Body description in imperative mood
|
|
|
116
126
|
"commit_message": commit_message
|
|
117
127
|
}),
|
|
118
128
|
"stderr": ""
|
|
119
|
-
|
|
129
|
+
}
|
|
120
130
|
|
|
121
131
|
except Exception as e:
|
|
122
132
|
return {
|
|
@@ -3,15 +3,15 @@ from typing import Dict, Any
|
|
|
3
3
|
from jarvis.jarvis_lsp.registry import LSPRegistry
|
|
4
4
|
|
|
5
5
|
class LSPFindDefinitionTool:
|
|
6
|
-
"""
|
|
6
|
+
"""使用LSP在代码中查找符号定义的工具"""
|
|
7
7
|
|
|
8
8
|
name = "lsp_find_definition"
|
|
9
|
-
description = "
|
|
9
|
+
description = "在代码中查找符号的定义"
|
|
10
10
|
parameters = {
|
|
11
|
-
"file_path": "
|
|
12
|
-
"line": "
|
|
13
|
-
"character": "
|
|
14
|
-
"language": f"
|
|
11
|
+
"file_path": "包含符号的文件路径",
|
|
12
|
+
"line": "符号所在的行号(从0开始)",
|
|
13
|
+
"character": "符号在行中的字符位置",
|
|
14
|
+
"language": f"文件的编程语言({', '.join(LSPRegistry.get_global_lsp_registry().get_supported_languages())})"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
@staticmethod
|
|
@@ -131,4 +131,4 @@ class LSPFindDefinitionTool:
|
|
|
131
131
|
}
|
|
132
132
|
finally:
|
|
133
133
|
if lsp:
|
|
134
|
-
lsp.shutdown()
|
|
134
|
+
lsp.shutdown()
|
|
@@ -3,15 +3,15 @@ from typing import Dict, Any
|
|
|
3
3
|
from jarvis.jarvis_lsp.registry import LSPRegistry
|
|
4
4
|
|
|
5
5
|
class LSPPrepareRenameTool:
|
|
6
|
-
"""
|
|
6
|
+
"""使用LSP检查符号是否可以安全重命名并显示所有受影响位置的工具"""
|
|
7
7
|
|
|
8
8
|
name = "lsp_prepare_rename"
|
|
9
|
-
description = "
|
|
9
|
+
description = "检查符号是否可以安全重命名,并显示所有受影响的位置"
|
|
10
10
|
parameters = {
|
|
11
|
-
"file_path": "
|
|
12
|
-
"line": "
|
|
13
|
-
"character": "
|
|
14
|
-
"language": f"
|
|
11
|
+
"file_path": "包含符号的文件路径",
|
|
12
|
+
"line": "符号所在的行号(从0开始)",
|
|
13
|
+
"character": "符号在行中的字符位置",
|
|
14
|
+
"language": f"文件的编程语言({', '.join(LSPRegistry.get_global_lsp_registry().get_supported_languages())})"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
@staticmethod
|
|
@@ -127,4 +127,4 @@ class LSPPrepareRenameTool:
|
|
|
127
127
|
}
|
|
128
128
|
finally:
|
|
129
129
|
if lsp:
|
|
130
|
-
lsp.shutdown()
|
|
130
|
+
lsp.shutdown()
|
|
@@ -8,25 +8,25 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class MethodologyTool:
|
|
11
|
-
"""
|
|
11
|
+
"""经验管理工具"""
|
|
12
12
|
|
|
13
13
|
name = "methodology"
|
|
14
|
-
description = "
|
|
14
|
+
description = "管理问题解决方法论,支持添加、更新和删除操作"
|
|
15
15
|
parameters = {
|
|
16
16
|
"type": "object",
|
|
17
17
|
"properties": {
|
|
18
18
|
"operation": {
|
|
19
19
|
"type": "string",
|
|
20
|
-
"description": "
|
|
20
|
+
"description": "操作类型(delete/update/add)",
|
|
21
21
|
"enum": ["delete", "update", "add"]
|
|
22
22
|
},
|
|
23
23
|
"problem_type": {
|
|
24
24
|
"type": "string",
|
|
25
|
-
"description": "
|
|
25
|
+
"description": "问题类型,例如:code_review, bug_fix 等"
|
|
26
26
|
},
|
|
27
27
|
"content": {
|
|
28
28
|
"type": "string",
|
|
29
|
-
"description": "
|
|
29
|
+
"description": "方法论内容(更新和添加时必填)",
|
|
30
30
|
"optional": True
|
|
31
31
|
}
|
|
32
32
|
},
|
|
@@ -60,7 +60,7 @@ class MethodologyTool:
|
|
|
60
60
|
except Exception as e:
|
|
61
61
|
PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
|
|
62
62
|
return {}
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
def _save_methodologies(self, methodologies: Dict):
|
|
65
65
|
"""Save all methodologies"""
|
|
66
66
|
try:
|
jarvis/jarvis_tools/rag.py
CHANGED
|
@@ -6,21 +6,21 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
|
6
6
|
|
|
7
7
|
class RAGTool:
|
|
8
8
|
name = "rag"
|
|
9
|
-
description = "
|
|
9
|
+
description = "基于文档目录进行问答,支持多种文档格式(txt、pdf、docx等)"
|
|
10
10
|
parameters = {
|
|
11
11
|
"type": "object",
|
|
12
12
|
"properties": {
|
|
13
13
|
"dir": {
|
|
14
14
|
"type": "string",
|
|
15
|
-
"description": "
|
|
15
|
+
"description": "文档目录路径,支持相对路径和绝对路径"
|
|
16
16
|
},
|
|
17
17
|
"question": {
|
|
18
18
|
"type": "string",
|
|
19
|
-
"description": "
|
|
19
|
+
"description": "要询问的问题"
|
|
20
20
|
},
|
|
21
21
|
"rebuild_index": {
|
|
22
22
|
"type": "boolean",
|
|
23
|
-
"description": "
|
|
23
|
+
"description": "是否重建索引",
|
|
24
24
|
"default": False
|
|
25
25
|
}
|
|
26
26
|
},
|
|
@@ -145,4 +145,4 @@ def main():
|
|
|
145
145
|
PrettyOutput.print(result["stderr"], OutputType.WARNING)
|
|
146
146
|
|
|
147
147
|
if __name__ == "__main__":
|
|
148
|
-
main()
|
|
148
|
+
main()
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
from typing import Dict, Any
|
|
2
2
|
import requests
|
|
3
3
|
from bs4 import BeautifulSoup
|
|
4
|
+
from yaspin import yaspin
|
|
4
5
|
|
|
5
6
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
6
7
|
|
|
7
8
|
class WebpageTool:
|
|
8
9
|
name = "read_webpage"
|
|
9
|
-
description = "
|
|
10
|
+
description = "读取网页内容,提取标题、文本和超链接"
|
|
10
11
|
parameters = {
|
|
11
12
|
"type": "object",
|
|
12
13
|
"properties": {
|
|
13
14
|
"url": {
|
|
14
15
|
"type": "string",
|
|
15
|
-
"description": "
|
|
16
|
+
"description": "要读取的网页URL"
|
|
16
17
|
}
|
|
17
18
|
},
|
|
18
19
|
"required": ["url"]
|
|
@@ -29,48 +30,67 @@ class WebpageTool:
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
# Send request
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
with yaspin(text="正在读取网页...", color="cyan") as spinner:
|
|
34
|
+
response = requests.get(url, headers=headers, timeout=10)
|
|
35
|
+
response.raise_for_status()
|
|
36
|
+
spinner.text = "网页读取完成"
|
|
37
|
+
spinner.ok("✅")
|
|
38
|
+
|
|
35
39
|
|
|
36
40
|
# Use correct encoding
|
|
41
|
+
|
|
37
42
|
response.encoding = response.apparent_encoding
|
|
38
43
|
|
|
39
44
|
# Parse HTML
|
|
40
|
-
|
|
45
|
+
with yaspin(text="正在解析网页...", color="cyan") as spinner:
|
|
46
|
+
soup = BeautifulSoup(response.text, 'html.parser')
|
|
47
|
+
spinner.text = "网页解析完成"
|
|
48
|
+
spinner.ok("✅")
|
|
41
49
|
|
|
42
50
|
# Remove script and style tags
|
|
43
|
-
|
|
44
|
-
script
|
|
51
|
+
with yaspin(text="正在移除脚本和样式...", color="cyan") as spinner:
|
|
52
|
+
for script in soup(["script", "style"]):
|
|
53
|
+
script.decompose()
|
|
54
|
+
spinner.text = "脚本和样式移除完成"
|
|
55
|
+
spinner.ok("✅")
|
|
45
56
|
|
|
46
57
|
# Extract title
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
links = []
|
|
58
|
+
with yaspin(text="正在提取标题...", color="cyan") as spinner:
|
|
59
|
+
title = soup.title.string if soup.title else ""
|
|
60
|
+
title = title.strip() if title else "No title"
|
|
61
|
+
spinner.text = "标题提取完成"
|
|
62
|
+
spinner.ok("✅")
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
with yaspin(text="正在提取文本和链接...", color="cyan") as spinner:
|
|
65
|
+
# Extract text and links
|
|
66
|
+
text_parts = []
|
|
67
|
+
links = []
|
|
68
|
+
|
|
69
|
+
# Process content and collect links
|
|
70
|
+
for element in soup.descendants:
|
|
71
|
+
if element.name == 'a' and element.get('href'): # type: ignore
|
|
72
|
+
href = element.get('href') # type: ignore
|
|
73
|
+
text = element.get_text(strip=True)
|
|
74
|
+
if text and href:
|
|
75
|
+
links.append(f"[{text}]({href})")
|
|
76
|
+
elif isinstance(element, str) and element.strip():
|
|
77
|
+
text_parts.append(element.strip())
|
|
78
|
+
spinner.text = "文本和链接提取完成"
|
|
79
|
+
spinner.ok("✅")
|
|
63
80
|
|
|
64
81
|
# Build output
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
with yaspin(text="正在构建输出...", color="cyan") as spinner:
|
|
83
|
+
output = [
|
|
84
|
+
f"Title: {title}",
|
|
85
|
+
"",
|
|
86
|
+
"Text content:",
|
|
87
|
+
"\n".join(text_parts),
|
|
88
|
+
"",
|
|
89
|
+
"Links found:",
|
|
90
|
+
"\n".join(links) if links else "No links found"
|
|
91
|
+
]
|
|
92
|
+
spinner.text = "输出构建完成"
|
|
93
|
+
spinner.ok("✅")
|
|
74
94
|
|
|
75
95
|
return {
|
|
76
96
|
"success": True,
|