jarvis-ai-assistant 0.1.96__py3-none-any.whl → 0.1.98__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/agent.py +138 -144
- jarvis/jarvis_codebase/main.py +87 -54
- jarvis/jarvis_coder/git_utils.py +22 -25
- jarvis/jarvis_coder/main.py +166 -171
- jarvis/jarvis_coder/patch_handler.py +153 -453
- jarvis/jarvis_coder/plan_generator.py +76 -48
- jarvis/jarvis_platform/main.py +39 -39
- jarvis/jarvis_rag/main.py +182 -182
- jarvis/jarvis_smart_shell/main.py +34 -34
- jarvis/main.py +24 -24
- jarvis/models/ai8.py +22 -22
- jarvis/models/base.py +17 -13
- jarvis/models/kimi.py +31 -31
- jarvis/models/ollama.py +28 -28
- jarvis/models/openai.py +22 -24
- jarvis/models/oyi.py +25 -25
- jarvis/models/registry.py +33 -34
- jarvis/tools/ask_user.py +5 -5
- jarvis/tools/base.py +2 -2
- jarvis/tools/chdir.py +9 -9
- jarvis/tools/codebase_qa.py +4 -4
- jarvis/tools/coder.py +4 -4
- jarvis/tools/file_ops.py +1 -1
- jarvis/tools/generator.py +23 -23
- jarvis/tools/methodology.py +4 -4
- jarvis/tools/rag.py +4 -4
- jarvis/tools/registry.py +38 -38
- jarvis/tools/search.py +42 -42
- jarvis/tools/shell.py +13 -13
- jarvis/tools/sub_agent.py +16 -16
- jarvis/tools/thinker.py +41 -41
- jarvis/tools/webpage.py +17 -17
- jarvis/utils.py +59 -60
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.98.dist-info/RECORD +47 -0
- jarvis_ai_assistant-0.1.96.dist-info/RECORD +0 -47
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.96.dist-info → jarvis_ai_assistant-0.1.98.dist-info}/top_level.txt +0 -0
|
@@ -1,75 +1,103 @@
|
|
|
1
|
-
|
|
1
|
+
import re
|
|
2
|
+
from typing import Dict, List, Tuple
|
|
2
3
|
from jarvis.models.registry import PlatformRegistry
|
|
3
|
-
from jarvis.utils import PrettyOutput, OutputType, get_multiline_input
|
|
4
|
-
from jarvis.models.base import BasePlatform
|
|
4
|
+
from jarvis.utils import PrettyOutput, OutputType, get_multiline_input
|
|
5
5
|
|
|
6
6
|
class PlanGenerator:
|
|
7
|
-
"""
|
|
7
|
+
"""Modification plan generator"""
|
|
8
8
|
|
|
9
|
-
def
|
|
10
|
-
"""
|
|
9
|
+
def _build_prompt(self, feature: str, related_files: List[Dict], additional_info: str) -> str:
|
|
10
|
+
"""Build prompt
|
|
11
11
|
|
|
12
12
|
Args:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def _build_prompt(self, feature: str, related_files: List[Dict]) -> str:
|
|
18
|
-
"""构建提示词
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
feature: 功能描述
|
|
22
|
-
related_files: 相关文件列表
|
|
23
|
-
user_feedback: 用户反馈信息
|
|
13
|
+
feature: Feature description
|
|
14
|
+
related_files: Related files list
|
|
15
|
+
additional_info: User supplement information
|
|
24
16
|
|
|
25
17
|
Returns:
|
|
26
|
-
str:
|
|
18
|
+
str: Complete prompt
|
|
27
19
|
"""
|
|
28
|
-
prompt = "
|
|
20
|
+
prompt = "You are a code modification expert who can generate modification plans based on requirements and relevant code snippets. I need your help to analyze how to implement the following feature:\n\n"
|
|
29
21
|
prompt += f"{feature}\n\n"
|
|
30
22
|
|
|
31
|
-
prompt += "
|
|
23
|
+
prompt += "Here are the relevant code file snippets:\n\n"
|
|
32
24
|
|
|
33
25
|
for file in related_files:
|
|
34
|
-
prompt += f"
|
|
26
|
+
prompt += f"File: {file['file_path']}\n"
|
|
35
27
|
for part in file["parts"]:
|
|
36
28
|
prompt += f"<PART>\n{part}\n</PART>\n"
|
|
37
29
|
|
|
38
|
-
prompt += "\n
|
|
39
|
-
prompt += "1.
|
|
40
|
-
prompt += "2.
|
|
41
|
-
prompt += "3.
|
|
42
|
-
prompt += "4.
|
|
30
|
+
prompt += "\nPlease provide detailed modifications needed to implement this feature. Include:\n"
|
|
31
|
+
prompt += "1. Which files need to be modified\n"
|
|
32
|
+
prompt += "2. How to modify each file, no explanation needed\n"
|
|
33
|
+
prompt += "3. Don't assume other files or code exist, only generate modification plans based on provided file contents and description\n"
|
|
34
|
+
prompt += "4. Don't implement features outside the requirement\n"
|
|
35
|
+
prompt += "5. Output only one modification plan per file (can be multiple lines)\n"
|
|
36
|
+
prompt += "6. Output format as follows:\n"
|
|
37
|
+
prompt += "<PLAN>\n"
|
|
38
|
+
prompt += "> path/to/file1\n"
|
|
39
|
+
prompt += "modification plan\n"
|
|
40
|
+
prompt += "</PLAN>\n"
|
|
41
|
+
prompt += "<PLAN>\n"
|
|
42
|
+
prompt += "> path/to/file2\n"
|
|
43
|
+
prompt += "modification plan\n"
|
|
44
|
+
prompt += "</PLAN>\n"
|
|
45
|
+
if additional_info:
|
|
46
|
+
prompt += f"# Additional information:\n{additional_info}\n"
|
|
43
47
|
|
|
44
48
|
return prompt
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
|
|
51
|
+
def generate_plan(self, feature: str, related_files: List[Dict]) -> Tuple[str, Dict[str,str]]:
|
|
52
|
+
"""Generate modification plan
|
|
48
53
|
|
|
49
54
|
Args:
|
|
50
|
-
feature:
|
|
51
|
-
related_files:
|
|
55
|
+
feature: Feature description
|
|
56
|
+
related_files: Related files list
|
|
52
57
|
|
|
53
58
|
Returns:
|
|
54
|
-
str:
|
|
59
|
+
Tuple[str, Dict[str,str]]: Modification plan, return None if user cancels
|
|
55
60
|
"""
|
|
56
|
-
|
|
61
|
+
additional_info = ""
|
|
57
62
|
while True:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
# 获取修改方案
|
|
62
|
-
plan = while_success(lambda: self.thinking_model.chat(prompt), 5)
|
|
63
|
+
prompt = self._build_prompt(feature, related_files, additional_info)
|
|
64
|
+
# Build prompt
|
|
65
|
+
PrettyOutput.print("Start generating modification plan...", OutputType.PROGRESS)
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
# Get modification plan
|
|
68
|
+
raw_plan = PlatformRegistry.get_global_platform_registry().get_thinking_platform().chat_until_success(prompt)
|
|
69
|
+
structed_plan = self._extract_code(raw_plan)
|
|
70
|
+
if not structed_plan:
|
|
71
|
+
PrettyOutput.print("Modification plan generation failed, please try again", OutputType.ERROR)
|
|
72
|
+
tmp = get_multiline_input("Please enter your additional information or suggestions (press Enter to cancel):")
|
|
73
|
+
if tmp == "__interrupt__" or prompt == "":
|
|
74
|
+
return "", {}
|
|
75
|
+
additional_info += tmp + "\n"
|
|
76
|
+
continue
|
|
77
|
+
user_input = input("\nDo you agree with this modification plan? (y/n) [y]: ").strip().lower() or 'y'
|
|
78
|
+
if user_input == 'y' or user_input == '':
|
|
79
|
+
return raw_plan, structed_plan
|
|
67
80
|
elif user_input == 'n':
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
# Get user feedback
|
|
82
|
+
tmp = get_multiline_input("Please enter your additional information or suggestions (press Enter to cancel):")
|
|
83
|
+
if prompt == "__interrupt__" or prompt == "":
|
|
84
|
+
return "", {}
|
|
85
|
+
additional_info += tmp + "\n"
|
|
86
|
+
continue
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _extract_code(self, response: str) -> Dict[str, str]:
|
|
90
|
+
"""Extract code from response
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
response: Model response content
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Dict[str, List[str]]: Code dictionary, key is file path, value is code snippet list
|
|
97
|
+
"""
|
|
98
|
+
code_dict = {}
|
|
99
|
+
for match in re.finditer(r'<PLAN>\n> (.+?)\n(.*?)\n</PLAN>', response, re.DOTALL):
|
|
100
|
+
file_path = match.group(1)
|
|
101
|
+
code_part = match.group(2)
|
|
102
|
+
code_dict[file_path] = code_part
|
|
103
|
+
return code_dict
|
jarvis/jarvis_platform/main.py
CHANGED
|
@@ -2,26 +2,26 @@ from jarvis.models.registry import PlatformRegistry
|
|
|
2
2
|
from jarvis.utils import PrettyOutput, OutputType, load_env_from_file, get_multiline_input
|
|
3
3
|
|
|
4
4
|
def list_platforms():
|
|
5
|
-
"""
|
|
5
|
+
"""List all supported platforms and models"""
|
|
6
6
|
registry = PlatformRegistry.get_global_platform_registry()
|
|
7
7
|
platforms = registry.get_available_platforms()
|
|
8
8
|
|
|
9
|
-
PrettyOutput.section("
|
|
9
|
+
PrettyOutput.section("Supported platforms and models", OutputType.SUCCESS)
|
|
10
10
|
|
|
11
11
|
for platform_name in platforms:
|
|
12
|
-
#
|
|
12
|
+
# Create platform instance
|
|
13
13
|
platform = registry.create_platform(platform_name)
|
|
14
14
|
if not platform:
|
|
15
15
|
continue
|
|
16
16
|
|
|
17
|
-
#
|
|
17
|
+
# Get the list of models supported by the platform
|
|
18
18
|
try:
|
|
19
19
|
models = platform.get_model_list()
|
|
20
20
|
|
|
21
|
-
#
|
|
21
|
+
# Print platform name
|
|
22
22
|
PrettyOutput.section(f"{platform_name}", OutputType.SUCCESS)
|
|
23
23
|
|
|
24
|
-
#
|
|
24
|
+
# Print model list
|
|
25
25
|
if models:
|
|
26
26
|
for model_name, description in models:
|
|
27
27
|
if description:
|
|
@@ -29,95 +29,95 @@ def list_platforms():
|
|
|
29
29
|
else:
|
|
30
30
|
PrettyOutput.print(f" • {model_name}", OutputType.SUCCESS)
|
|
31
31
|
else:
|
|
32
|
-
PrettyOutput.print("
|
|
32
|
+
PrettyOutput.print(" • No available model information", OutputType.WARNING)
|
|
33
33
|
|
|
34
34
|
except Exception as e:
|
|
35
|
-
PrettyOutput.print(f"
|
|
35
|
+
PrettyOutput.print(f"Failed to get model list for {platform_name}: {str(e)}", OutputType.WARNING)
|
|
36
36
|
|
|
37
37
|
def chat_with_model(platform_name: str, model_name: str):
|
|
38
|
-
"""
|
|
38
|
+
"""Chat with specified platform and model"""
|
|
39
39
|
registry = PlatformRegistry.get_global_platform_registry()
|
|
40
40
|
|
|
41
|
-
#
|
|
41
|
+
# Create platform instance
|
|
42
42
|
platform = registry.create_platform(platform_name)
|
|
43
43
|
if not platform:
|
|
44
|
-
PrettyOutput.print(f"
|
|
44
|
+
PrettyOutput.print(f"Failed to create platform {platform_name}", OutputType.ERROR)
|
|
45
45
|
return
|
|
46
46
|
|
|
47
47
|
try:
|
|
48
|
-
#
|
|
48
|
+
# Set model
|
|
49
49
|
platform.set_model_name(model_name)
|
|
50
|
-
PrettyOutput.print(f"
|
|
50
|
+
PrettyOutput.print(f"Connected to {platform_name} platform {model_name} model", OutputType.SUCCESS)
|
|
51
51
|
|
|
52
|
-
#
|
|
52
|
+
# Start conversation loop
|
|
53
53
|
while True:
|
|
54
|
-
#
|
|
54
|
+
# Get user input
|
|
55
55
|
user_input = get_multiline_input("")
|
|
56
56
|
|
|
57
|
-
#
|
|
57
|
+
# Check if input is cancelled
|
|
58
58
|
if user_input == "__interrupt__" or user_input.strip() == "/bye":
|
|
59
|
-
PrettyOutput.print("
|
|
59
|
+
PrettyOutput.print("Bye!", OutputType.SUCCESS)
|
|
60
60
|
break
|
|
61
61
|
|
|
62
|
-
#
|
|
62
|
+
# Check if input is empty
|
|
63
63
|
if not user_input.strip():
|
|
64
64
|
continue
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# Check if it is a clear session command
|
|
67
67
|
if user_input.strip() == "/clear":
|
|
68
68
|
try:
|
|
69
69
|
platform.delete_chat()
|
|
70
|
-
platform.set_model_name(model_name) #
|
|
71
|
-
PrettyOutput.print("
|
|
70
|
+
platform.set_model_name(model_name) # Reinitialize session
|
|
71
|
+
PrettyOutput.print("Session cleared", OutputType.SUCCESS)
|
|
72
72
|
except Exception as e:
|
|
73
|
-
PrettyOutput.print(f"
|
|
73
|
+
PrettyOutput.print(f"Failed to clear session: {str(e)}", OutputType.ERROR)
|
|
74
74
|
continue
|
|
75
75
|
|
|
76
76
|
try:
|
|
77
|
-
#
|
|
78
|
-
response = platform.
|
|
77
|
+
# Send to model and get reply
|
|
78
|
+
response = platform.chat_until_success(user_input)
|
|
79
79
|
if not response:
|
|
80
|
-
PrettyOutput.print("
|
|
80
|
+
PrettyOutput.print("No valid reply", OutputType.WARNING)
|
|
81
81
|
|
|
82
82
|
except Exception as e:
|
|
83
|
-
PrettyOutput.print(f"
|
|
83
|
+
PrettyOutput.print(f"Failed to chat: {str(e)}", OutputType.ERROR)
|
|
84
84
|
|
|
85
85
|
except Exception as e:
|
|
86
|
-
PrettyOutput.print(f"
|
|
86
|
+
PrettyOutput.print(f"Failed to initialize conversation: {str(e)}", OutputType.ERROR)
|
|
87
87
|
finally:
|
|
88
|
-
#
|
|
88
|
+
# Clean up resources
|
|
89
89
|
try:
|
|
90
90
|
platform.delete_chat()
|
|
91
91
|
except:
|
|
92
92
|
pass
|
|
93
93
|
|
|
94
94
|
def info_command(args):
|
|
95
|
-
"""
|
|
95
|
+
"""Process info subcommand"""
|
|
96
96
|
list_platforms()
|
|
97
97
|
|
|
98
98
|
def chat_command(args):
|
|
99
|
-
"""
|
|
99
|
+
"""Process chat subcommand"""
|
|
100
100
|
if not args.platform or not args.model:
|
|
101
|
-
PrettyOutput.print("
|
|
101
|
+
PrettyOutput.print("Please specify platform and model. Use 'jarvis info' to view available platforms and models.", OutputType.ERROR)
|
|
102
102
|
return
|
|
103
103
|
chat_with_model(args.platform, args.model)
|
|
104
104
|
|
|
105
105
|
def main():
|
|
106
|
-
"""
|
|
106
|
+
"""Main function"""
|
|
107
107
|
import argparse
|
|
108
108
|
|
|
109
109
|
load_env_from_file()
|
|
110
110
|
|
|
111
111
|
parser = argparse.ArgumentParser(description='Jarvis AI Platform')
|
|
112
|
-
subparsers = parser.add_subparsers(dest='command', help='
|
|
112
|
+
subparsers = parser.add_subparsers(dest='command', help='Available subcommands')
|
|
113
113
|
|
|
114
|
-
# info
|
|
115
|
-
info_parser = subparsers.add_parser('info', help='
|
|
114
|
+
# info subcommand
|
|
115
|
+
info_parser = subparsers.add_parser('info', help='Display supported platforms and models information')
|
|
116
116
|
|
|
117
|
-
# chat
|
|
118
|
-
chat_parser = subparsers.add_parser('chat', help='
|
|
119
|
-
chat_parser.add_argument('--platform', '-p', help='
|
|
120
|
-
chat_parser.add_argument('--model', '-m', help='
|
|
117
|
+
# chat subcommand
|
|
118
|
+
chat_parser = subparsers.add_parser('chat', help='Chat with specified platform and model')
|
|
119
|
+
chat_parser.add_argument('--platform', '-p', help='Specify the platform to use')
|
|
120
|
+
chat_parser.add_argument('--model', '-m', help='Specify the model to use')
|
|
121
121
|
|
|
122
122
|
args = parser.parse_args()
|
|
123
123
|
|