jarvis-ai-assistant 0.1.114__py3-none-any.whl → 0.1.116__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.
- jarvis/__init__.py +1 -1
- jarvis/{agent.py → jarvis_agent/__init__.py} +35 -159
- jarvis/jarvis_agent/output_handler.py +23 -0
- jarvis/jarvis_code_agent/code_agent.py +11 -11
- jarvis/jarvis_code_agent/file_select.py +28 -7
- jarvis/jarvis_code_agent/patch.py +25 -2
- jarvis/jarvis_code_agent/relevant_files.py +1 -1
- jarvis/jarvis_codebase/main.py +2 -2
- jarvis/jarvis_lsp/cpp.py +1 -1
- jarvis/jarvis_lsp/go.py +1 -1
- jarvis/jarvis_lsp/registry.py +1 -1
- jarvis/jarvis_lsp/rust.py +1 -1
- jarvis/jarvis_multi_agent/__init__.py +147 -0
- jarvis/jarvis_platform/ai8.py +2 -2
- jarvis/jarvis_platform/base.py +14 -4
- jarvis/jarvis_platform/kimi.py +2 -2
- jarvis/jarvis_platform/ollama.py +1 -1
- jarvis/jarvis_platform/openai.py +1 -1
- jarvis/jarvis_platform/oyi.py +1 -1
- jarvis/jarvis_platform/registry.py +1 -1
- jarvis/jarvis_platform_manager/main.py +422 -6
- jarvis/jarvis_platform_manager/openai_test.py +139 -0
- jarvis/jarvis_rag/main.py +2 -2
- jarvis/jarvis_smart_shell/main.py +17 -16
- jarvis/jarvis_tools/ask_codebase.py +1 -1
- jarvis/jarvis_tools/ask_user.py +1 -1
- jarvis/jarvis_tools/chdir.py +1 -1
- jarvis/jarvis_tools/code_review.py +3 -3
- jarvis/jarvis_tools/create_code_agent.py +1 -1
- jarvis/jarvis_tools/create_sub_agent.py +2 -2
- jarvis/jarvis_tools/execute_shell.py +1 -1
- jarvis/jarvis_tools/file_operation.py +16 -14
- jarvis/jarvis_tools/git_commiter.py +2 -2
- jarvis/jarvis_tools/methodology.py +1 -1
- jarvis/jarvis_tools/rag.py +1 -1
- jarvis/jarvis_tools/read_code.py +19 -8
- jarvis/jarvis_tools/read_webpage.py +1 -1
- jarvis/jarvis_tools/registry.py +53 -6
- jarvis/jarvis_tools/search.py +1 -1
- jarvis/jarvis_tools/select_code_files.py +1 -1
- jarvis/{utils.py → jarvis_utils/__init__.py} +69 -53
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.116.dist-info/RECORD +64 -0
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/WHEEL +1 -1
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/entry_points.txt +1 -2
- jarvis/jarvis_dev/main.py +0 -664
- jarvis/multi_agent.py +0 -76
- jarvis/utils/date_utils.py +0 -19
- jarvis_ai_assistant-0.1.114.dist-info/RECORD +0 -64
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import re
|
|
5
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
from jarvis.jarvis_agent import Agent
|
|
10
|
+
from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
11
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AgentConfig:
|
|
15
|
+
def __init__(self, **config):
|
|
16
|
+
self.system_prompt = config.get('system_prompt', '')
|
|
17
|
+
self.name = config.get('name', 'Jarvis')
|
|
18
|
+
self.description = config.get('description', '')
|
|
19
|
+
self.is_sub_agent = config.get('is_sub_agent', False)
|
|
20
|
+
self.output_handler = config.get('output_handler', [])
|
|
21
|
+
self.platform = config.get('platform')
|
|
22
|
+
self.model_name = config.get('model_name')
|
|
23
|
+
self.summary_prompt = config.get('summary_prompt')
|
|
24
|
+
self.auto_complete = config.get('auto_complete', False)
|
|
25
|
+
self.input_handler = config.get('input_handler')
|
|
26
|
+
self.max_context_length = config.get('max_context_length')
|
|
27
|
+
self.execute_tool_confirm = config.get('execute_tool_confirm')
|
|
28
|
+
|
|
29
|
+
class MultiAgent(OutputHandler):
|
|
30
|
+
def __init__(self, configs: List[AgentConfig], main_agent_name: str):
|
|
31
|
+
self.agents_config = configs
|
|
32
|
+
self.agents = {}
|
|
33
|
+
self.init_agents()
|
|
34
|
+
self.main_agent_name = main_agent_name
|
|
35
|
+
|
|
36
|
+
def prompt(self) -> str:
|
|
37
|
+
return """
|
|
38
|
+
- Send Message Rules
|
|
39
|
+
!!! CRITICAL ACTION RULES !!!
|
|
40
|
+
You can ONLY perform ONE action per turn:
|
|
41
|
+
- ENSURE USE ONLY ONE TOOL EVERY TURN (file_operation, ask_user, etc.)
|
|
42
|
+
- OR SEND ONE MESSAGE TO ANOTHER AGENT
|
|
43
|
+
- NEVER DO BOTH IN THE SAME TURN
|
|
44
|
+
|
|
45
|
+
2. Message Format:
|
|
46
|
+
<SEND_MESSAGE>
|
|
47
|
+
to: agent_name # Target agent name
|
|
48
|
+
content: |
|
|
49
|
+
message_content # Message content, multi-line must be separated by newlines
|
|
50
|
+
</SEND_MESSAGE>
|
|
51
|
+
|
|
52
|
+
3. Message Handling:
|
|
53
|
+
- After sending a message, WAIT for response
|
|
54
|
+
- Process response before next action
|
|
55
|
+
- Never send multiple messages at once
|
|
56
|
+
- Never combine message with tool calls
|
|
57
|
+
|
|
58
|
+
4. If Multiple Actions Needed:
|
|
59
|
+
a. Choose most important action first
|
|
60
|
+
b. Wait for response/result
|
|
61
|
+
c. Plan next action based on response
|
|
62
|
+
d. Execute next action in new turn
|
|
63
|
+
|
|
64
|
+
- Remember:
|
|
65
|
+
- First action will be executed
|
|
66
|
+
- Additional actions will be IGNORED
|
|
67
|
+
- Always process responses before new actions
|
|
68
|
+
- You should send message to other to continue the task if you are nothing to do
|
|
69
|
+
- If you receive a message from other agent, you should handle it and reply to sender
|
|
70
|
+
|
|
71
|
+
You can send message to following agents: """ + "\n".join([f"{c.name}: {c.description}" for c in self.agents_config])
|
|
72
|
+
|
|
73
|
+
def can_handle(self, response: str) -> bool:
|
|
74
|
+
return len(self._extract_send_msg(response)) > 0
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def handle(self, response: str) -> Tuple[bool, Any]:
|
|
78
|
+
send_messages = self._extract_send_msg(response)
|
|
79
|
+
if len(send_messages) > 1:
|
|
80
|
+
return False, f"Send multiple messages, please only send one message at a time."
|
|
81
|
+
if len(send_messages) == 0:
|
|
82
|
+
return False, ""
|
|
83
|
+
return True, send_messages[0]
|
|
84
|
+
|
|
85
|
+
def name(self) -> str:
|
|
86
|
+
return "SEND_MESSAGE"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@staticmethod
|
|
90
|
+
def _extract_send_msg(content: str) -> List[Dict]:
|
|
91
|
+
"""Extract send message from content.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
content: The content containing send message
|
|
95
|
+
"""
|
|
96
|
+
data = re.findall(r'<SEND_MESSAGE>(.*?)</SEND_MESSAGE>', content, re.DOTALL)
|
|
97
|
+
ret = []
|
|
98
|
+
for item in data:
|
|
99
|
+
try:
|
|
100
|
+
msg = yaml.safe_load(item)
|
|
101
|
+
if 'to' in msg and 'content' in msg:
|
|
102
|
+
ret.append(msg)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
continue
|
|
105
|
+
return ret
|
|
106
|
+
|
|
107
|
+
def init_agents(self):
|
|
108
|
+
for agent_config in self.agents_config:
|
|
109
|
+
agent = Agent(system_prompt=agent_config.system_prompt,
|
|
110
|
+
name=agent_config.name,
|
|
111
|
+
description=agent_config.description,
|
|
112
|
+
model_name=agent_config.model_name,
|
|
113
|
+
platform=agent_config.platform,
|
|
114
|
+
max_context_length=agent_config.max_context_length,
|
|
115
|
+
execute_tool_confirm=agent_config.execute_tool_confirm,
|
|
116
|
+
input_handler=agent_config.input_handler,
|
|
117
|
+
use_methodology=False,
|
|
118
|
+
record_methodology=False,
|
|
119
|
+
need_summary=False,
|
|
120
|
+
auto_complete=agent_config.auto_complete,
|
|
121
|
+
summary_prompt=agent_config.summary_prompt,
|
|
122
|
+
is_sub_agent=agent_config.is_sub_agent,
|
|
123
|
+
output_handler=[*agent_config.output_handler, self],
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
self.agents[agent_config.name] = agent
|
|
127
|
+
|
|
128
|
+
def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str:
|
|
129
|
+
last_agent = self.main_agent_name
|
|
130
|
+
msg = self.agents[self.main_agent_name].run(user_input, file_list)
|
|
131
|
+
while msg:
|
|
132
|
+
if isinstance(msg, str):
|
|
133
|
+
return msg
|
|
134
|
+
elif isinstance(msg, Dict):
|
|
135
|
+
prompt = f"""
|
|
136
|
+
Please handle this message:
|
|
137
|
+
from: {last_agent}
|
|
138
|
+
content: {msg['content']}
|
|
139
|
+
"""
|
|
140
|
+
if msg['to'] not in self.agents:
|
|
141
|
+
PrettyOutput.print(f"没有找到{msg['to']},重试...", OutputType.WARNING)
|
|
142
|
+
msg = self.agents[last_agent].run(f"The agent {msg['to']} is not found, agent list: {self.agents.keys()}")
|
|
143
|
+
continue
|
|
144
|
+
PrettyOutput.print(f"{last_agent} 发送消息给 {msg['to']}...", OutputType.INFO)
|
|
145
|
+
last_agent = self.agents[msg['to']].name
|
|
146
|
+
msg = self.agents[msg['to']].run(prompt)
|
|
147
|
+
return ""
|
jarvis/jarvis_platform/ai8.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from typing import Dict, List, Tuple
|
|
3
3
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
4
|
-
from jarvis.
|
|
4
|
+
from jarvis.jarvis_utils import PrettyOutput, OutputType
|
|
5
5
|
import requests
|
|
6
6
|
import json
|
|
7
7
|
import base64
|
|
@@ -260,7 +260,7 @@ class AI8Model(BasePlatform):
|
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
response = requests.get(
|
|
263
|
-
f"{self.BASE_URL}/api/chat/
|
|
263
|
+
f"{self.BASE_URL}/api/chat/tmpl",
|
|
264
264
|
headers=headers
|
|
265
265
|
)
|
|
266
266
|
|
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -2,7 +2,9 @@ from abc import ABC, abstractmethod
|
|
|
2
2
|
import re
|
|
3
3
|
from typing import Dict, List, Tuple
|
|
4
4
|
|
|
5
|
-
from jarvis.
|
|
5
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput, while_success, while_true
|
|
6
|
+
from yaspin import yaspin
|
|
7
|
+
from yaspin.spinners import Spinners
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
class BasePlatform(ABC):
|
|
@@ -28,9 +30,17 @@ class BasePlatform(ABC):
|
|
|
28
30
|
|
|
29
31
|
def chat_until_success(self, message: str) -> str:
|
|
30
32
|
def _chat():
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
if self.suppress_output:
|
|
34
|
+
with yaspin(Spinners.dots, text="Thinking", color="yellow") as spinner:
|
|
35
|
+
response = self.chat(message)
|
|
36
|
+
response = re.sub(r'<think>(.*?)</think>', '', response, flags=re.DOTALL)
|
|
37
|
+
spinner.ok("✓")
|
|
38
|
+
return response
|
|
39
|
+
else:
|
|
40
|
+
response = self.chat(message)
|
|
41
|
+
response = re.sub(r'<think>(.*?)</think>', '', response, flags=re.DOTALL)
|
|
42
|
+
return response
|
|
43
|
+
|
|
34
44
|
return while_true(lambda: while_success(lambda: _chat(), 5), 5)
|
|
35
45
|
|
|
36
46
|
@abstractmethod
|
jarvis/jarvis_platform/kimi.py
CHANGED
|
@@ -5,8 +5,8 @@ import os
|
|
|
5
5
|
import mimetypes
|
|
6
6
|
import time
|
|
7
7
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
8
|
-
from jarvis.
|
|
9
|
-
from jarvis.
|
|
8
|
+
from jarvis.jarvis_utils import PrettyOutput, OutputType
|
|
9
|
+
from jarvis.jarvis_utils import while_success
|
|
10
10
|
|
|
11
11
|
class KimiModel(BasePlatform):
|
|
12
12
|
"""Kimi model implementation"""
|
jarvis/jarvis_platform/ollama.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
from typing import List, Dict, Tuple
|
|
3
3
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
4
|
-
from jarvis.
|
|
4
|
+
from jarvis.jarvis_utils import OutputType, PrettyOutput, get_single_line_input
|
|
5
5
|
import os
|
|
6
6
|
import json
|
|
7
7
|
|
jarvis/jarvis_platform/openai.py
CHANGED
|
@@ -2,7 +2,7 @@ from typing import Dict, List, Tuple
|
|
|
2
2
|
import os
|
|
3
3
|
from openai import OpenAI
|
|
4
4
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
5
|
-
from jarvis.
|
|
5
|
+
from jarvis.jarvis_utils import PrettyOutput, OutputType
|
|
6
6
|
|
|
7
7
|
class OpenAIModel(BasePlatform):
|
|
8
8
|
platform_name = "openai"
|
jarvis/jarvis_platform/oyi.py
CHANGED
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
import sys
|
|
5
5
|
from typing import Dict, Type, Optional, List
|
|
6
6
|
from jarvis.jarvis_platform.base import BasePlatform
|
|
7
|
-
from jarvis.
|
|
7
|
+
from jarvis.jarvis_utils import PrettyOutput, OutputType, get_cheap_model_name, get_cheap_platform_name, get_codegen_model_name, get_codegen_platform_name, get_normal_model_name, get_normal_platform_name, get_thinking_model_name, get_thinking_platform_name
|
|
8
8
|
|
|
9
9
|
REQUIRED_METHODS = [
|
|
10
10
|
('chat', ['message']), # 方法名和参数列表
|