jarvis-ai-assistant 0.1.130__py3-none-any.whl → 0.1.132__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/jarvis_agent/__init__.py +71 -38
- jarvis/jarvis_agent/builtin_input_handler.py +73 -0
- jarvis/{jarvis_code_agent → jarvis_agent}/file_input_handler.py +1 -1
- jarvis/jarvis_agent/main.py +1 -1
- jarvis/{jarvis_code_agent → jarvis_agent}/patch.py +77 -55
- jarvis/{jarvis_code_agent → jarvis_agent}/shell_input_handler.py +1 -2
- jarvis/jarvis_code_agent/code_agent.py +93 -88
- jarvis/jarvis_dev/main.py +335 -626
- jarvis/jarvis_git_squash/main.py +11 -32
- jarvis/jarvis_lsp/base.py +2 -26
- jarvis/jarvis_lsp/cpp.py +2 -14
- jarvis/jarvis_lsp/go.py +0 -13
- jarvis/jarvis_lsp/python.py +1 -30
- jarvis/jarvis_lsp/registry.py +10 -14
- jarvis/jarvis_lsp/rust.py +0 -12
- jarvis/jarvis_multi_agent/__init__.py +20 -29
- jarvis/jarvis_platform/ai8.py +7 -32
- jarvis/jarvis_platform/base.py +2 -7
- jarvis/jarvis_platform/kimi.py +3 -144
- jarvis/jarvis_platform/ollama.py +54 -68
- jarvis/jarvis_platform/openai.py +0 -4
- jarvis/jarvis_platform/oyi.py +0 -75
- jarvis/jarvis_platform/registry.py +1 -1
- jarvis/jarvis_platform/yuanbao.py +264 -0
- jarvis/jarvis_platform_manager/main.py +3 -3
- jarvis/jarvis_rag/file_processors.py +138 -0
- jarvis/jarvis_rag/main.py +1305 -425
- jarvis/jarvis_tools/ask_codebase.py +227 -41
- jarvis/jarvis_tools/code_review.py +229 -166
- jarvis/jarvis_tools/create_code_agent.py +76 -72
- jarvis/jarvis_tools/create_sub_agent.py +32 -15
- jarvis/jarvis_tools/execute_python_script.py +58 -0
- jarvis/jarvis_tools/execute_shell.py +15 -28
- jarvis/jarvis_tools/execute_shell_script.py +2 -2
- jarvis/jarvis_tools/file_analyzer.py +271 -0
- jarvis/jarvis_tools/file_operation.py +3 -3
- jarvis/jarvis_tools/find_caller.py +213 -0
- jarvis/jarvis_tools/find_symbol.py +211 -0
- jarvis/jarvis_tools/function_analyzer.py +248 -0
- jarvis/jarvis_tools/git_commiter.py +89 -70
- jarvis/jarvis_tools/lsp_find_definition.py +83 -67
- jarvis/jarvis_tools/lsp_find_references.py +62 -46
- jarvis/jarvis_tools/lsp_get_diagnostics.py +90 -74
- jarvis/jarvis_tools/methodology.py +89 -48
- jarvis/jarvis_tools/project_analyzer.py +220 -0
- jarvis/jarvis_tools/read_code.py +24 -3
- jarvis/jarvis_tools/read_webpage.py +195 -81
- jarvis/jarvis_tools/registry.py +132 -11
- jarvis/jarvis_tools/search_web.py +73 -30
- jarvis/jarvis_tools/tool_generator.py +7 -9
- jarvis/jarvis_utils/__init__.py +1 -0
- jarvis/jarvis_utils/config.py +67 -3
- jarvis/jarvis_utils/embedding.py +344 -45
- jarvis/jarvis_utils/git_utils.py +18 -2
- jarvis/jarvis_utils/input.py +7 -4
- jarvis/jarvis_utils/methodology.py +379 -7
- jarvis/jarvis_utils/output.py +5 -3
- jarvis/jarvis_utils/utils.py +62 -10
- {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/METADATA +3 -4
- jarvis_ai_assistant-0.1.132.dist-info/RECORD +82 -0
- {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/entry_points.txt +2 -0
- jarvis/jarvis_c2rust/c2rust.yaml +0 -734
- jarvis/jarvis_code_agent/builtin_input_handler.py +0 -43
- jarvis/jarvis_codebase/__init__.py +0 -0
- jarvis/jarvis_codebase/main.py +0 -1011
- jarvis/jarvis_tools/lsp_get_document_symbols.py +0 -87
- jarvis/jarvis_tools/lsp_prepare_rename.py +0 -130
- jarvis_ai_assistant-0.1.130.dist-info/RECORD +0 -79
- {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/top_level.txt +0 -0
jarvis/jarvis_git_squash/main.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import re
|
|
1
2
|
import sys
|
|
2
3
|
import argparse
|
|
3
4
|
from typing import Dict, Any
|
|
@@ -18,7 +19,7 @@ class GitSquashTool:
|
|
|
18
19
|
"""Perform soft reset to specified commit hash"""
|
|
19
20
|
try:
|
|
20
21
|
subprocess.Popen(
|
|
21
|
-
["git", "reset", "--
|
|
22
|
+
["git", "reset", "--mixed", commit_hash],
|
|
22
23
|
stdout=subprocess.DEVNULL,
|
|
23
24
|
stderr=subprocess.DEVNULL
|
|
24
25
|
).wait()
|
|
@@ -26,39 +27,23 @@ class GitSquashTool:
|
|
|
26
27
|
except Exception:
|
|
27
28
|
return False
|
|
28
29
|
|
|
29
|
-
def execute(self, args: Dict)
|
|
30
|
+
def execute(self, args: Dict):
|
|
30
31
|
"""Execute the squash operation"""
|
|
31
32
|
try:
|
|
32
33
|
if not self._confirm_squash():
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"stdout": "Operation cancelled",
|
|
36
|
-
"stderr": ""
|
|
37
|
-
}
|
|
34
|
+
PrettyOutput.print("操作已取消", OutputType.WARNING)
|
|
35
|
+
return
|
|
38
36
|
|
|
39
37
|
if not self._reset_to_commit(args['commit_hash']):
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"stdout": "",
|
|
43
|
-
"stderr": "Failed to reset to specified commit"
|
|
44
|
-
}
|
|
38
|
+
PrettyOutput.print("重置到指定提交失败", OutputType.WARNING)
|
|
39
|
+
return
|
|
45
40
|
|
|
46
41
|
# Use existing GitCommitTool for new commit
|
|
47
42
|
commit_tool = GitCommitTool()
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
"success": result['success'],
|
|
52
|
-
"stdout": result['stdout'],
|
|
53
|
-
"stderr": result['stderr']
|
|
54
|
-
}
|
|
55
|
-
|
|
43
|
+
commit_tool.execute({"lang": args.get('lang', 'Chinese')})
|
|
56
44
|
except Exception as e:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"stdout": "",
|
|
60
|
-
"stderr": f"Squash failed: {str(e)}"
|
|
61
|
-
}
|
|
45
|
+
PrettyOutput.print(f"压缩提交失败: {str(e)}", OutputType.WARNING)
|
|
46
|
+
|
|
62
47
|
def main():
|
|
63
48
|
init_env()
|
|
64
49
|
parser = argparse.ArgumentParser(description='Git squash tool')
|
|
@@ -67,15 +52,9 @@ def main():
|
|
|
67
52
|
args = parser.parse_args()
|
|
68
53
|
|
|
69
54
|
tool = GitSquashTool()
|
|
70
|
-
|
|
55
|
+
tool.execute({
|
|
71
56
|
'commit_hash': args.commit_hash,
|
|
72
57
|
'lang': args.lang
|
|
73
58
|
})
|
|
74
|
-
|
|
75
|
-
if not result['success']:
|
|
76
|
-
PrettyOutput.print(result['stderr'], OutputType.ERROR)
|
|
77
|
-
sys.exit(1)
|
|
78
|
-
|
|
79
|
-
PrettyOutput.print(result['stdout'], OutputType.SUCCESS)
|
|
80
59
|
if __name__ == "__main__":
|
|
81
60
|
sys.exit(main())
|
jarvis/jarvis_lsp/base.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import List, Dict, Optional, Tuple, Any
|
|
2
|
+
from typing import List, Dict, Optional, Tuple, Any, Union
|
|
3
3
|
|
|
4
4
|
class BaseLSP(ABC):
|
|
5
5
|
"""Base class for Language Server Protocol integration.
|
|
@@ -11,7 +11,7 @@ class BaseLSP(ABC):
|
|
|
11
11
|
4. Symbol analysis
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
language: str = "" # Language identifier, should be overridden by subclasses
|
|
14
|
+
language: Union[str, List[str]] = "" # Language identifier, should be overridden by subclasses
|
|
15
15
|
|
|
16
16
|
@abstractmethod
|
|
17
17
|
def initialize(self, workspace_path: str) -> bool:
|
|
@@ -67,17 +67,6 @@ class BaseLSP(ABC):
|
|
|
67
67
|
"""
|
|
68
68
|
return None
|
|
69
69
|
|
|
70
|
-
@abstractmethod
|
|
71
|
-
def get_document_symbols(self, file_path: str) -> List[Dict[str, Any]]:
|
|
72
|
-
"""Get all symbols in document.
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
file_path: Path to the file
|
|
76
|
-
|
|
77
|
-
Returns:
|
|
78
|
-
List of symbols with their locations and types
|
|
79
|
-
"""
|
|
80
|
-
return []
|
|
81
70
|
|
|
82
71
|
@abstractmethod
|
|
83
72
|
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
@@ -112,19 +101,6 @@ class BaseLSP(ABC):
|
|
|
112
101
|
"""
|
|
113
102
|
return []
|
|
114
103
|
|
|
115
|
-
@abstractmethod
|
|
116
|
-
def prepare_rename(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
|
|
117
|
-
"""Check if symbol at position can be renamed.
|
|
118
|
-
|
|
119
|
-
Args:
|
|
120
|
-
file_path: Path to the file
|
|
121
|
-
position: Symbol position
|
|
122
|
-
|
|
123
|
-
Returns:
|
|
124
|
-
Range that would be renamed or None if rename not allowed
|
|
125
|
-
"""
|
|
126
|
-
return None
|
|
127
|
-
|
|
128
104
|
|
|
129
105
|
def shutdown(self):
|
|
130
106
|
"""Shutdown LSP server cleanly."""
|
jarvis/jarvis_lsp/cpp.py
CHANGED
|
@@ -9,7 +9,7 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
|
9
9
|
class CPPLSP(BaseLSP):
|
|
10
10
|
"""C++ LSP implementation using clangd."""
|
|
11
11
|
|
|
12
|
-
language = "cpp"
|
|
12
|
+
language = ["cpp", "c"]
|
|
13
13
|
|
|
14
14
|
@staticmethod
|
|
15
15
|
def check() -> bool:
|
|
@@ -80,12 +80,7 @@ class CPPLSP(BaseLSP):
|
|
|
80
80
|
"position": {"line": position[0], "character": position[1]}
|
|
81
81
|
})
|
|
82
82
|
return result[0] if result else None
|
|
83
|
-
|
|
84
|
-
def get_document_symbols(self, file_path: str) -> List[Dict[str, Any]]:
|
|
85
|
-
result = self._send_request("textDocument/documentSymbol", {
|
|
86
|
-
"textDocument": {"uri": f"file://{file_path}"}
|
|
87
|
-
})
|
|
88
|
-
return result or [] # type: ignore
|
|
83
|
+
|
|
89
84
|
|
|
90
85
|
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
91
86
|
# Send didOpen notification to trigger diagnostics
|
|
@@ -107,13 +102,6 @@ class CPPLSP(BaseLSP):
|
|
|
107
102
|
pass
|
|
108
103
|
return []
|
|
109
104
|
|
|
110
|
-
def prepare_rename(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
|
|
111
|
-
result = self._send_request("textDocument/prepareRename", {
|
|
112
|
-
"textDocument": {"uri": f"file://{file_path}"},
|
|
113
|
-
"position": {"line": position[0], "character": position[1]}
|
|
114
|
-
})
|
|
115
|
-
return result
|
|
116
|
-
|
|
117
105
|
|
|
118
106
|
def shutdown(self):
|
|
119
107
|
if self.clangd_process:
|
jarvis/jarvis_lsp/go.py
CHANGED
|
@@ -87,12 +87,6 @@ class GoLSP(BaseLSP):
|
|
|
87
87
|
})
|
|
88
88
|
return result[0] if result else None
|
|
89
89
|
|
|
90
|
-
def get_document_symbols(self, file_path: str) -> List[Dict[str, Any]]:
|
|
91
|
-
result = self._send_request("textDocument/documentSymbol", {
|
|
92
|
-
"textDocument": {"uri": f"file://{file_path}"}
|
|
93
|
-
})
|
|
94
|
-
return result or [] # type: ignore
|
|
95
|
-
|
|
96
90
|
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
97
91
|
# Send didOpen notification to trigger diagnostics
|
|
98
92
|
self._send_request("textDocument/didOpen", {
|
|
@@ -113,13 +107,6 @@ class GoLSP(BaseLSP):
|
|
|
113
107
|
pass
|
|
114
108
|
return []
|
|
115
109
|
|
|
116
|
-
def prepare_rename(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
|
|
117
|
-
result = self._send_request("textDocument/prepareRename", {
|
|
118
|
-
"textDocument": {"uri": f"file://{file_path}"},
|
|
119
|
-
"position": {"line": position[0], "character": position[1]}
|
|
120
|
-
})
|
|
121
|
-
return result
|
|
122
|
-
|
|
123
110
|
|
|
124
111
|
def shutdown(self):
|
|
125
112
|
if self.gopls_process:
|
jarvis/jarvis_lsp/python.py
CHANGED
|
@@ -18,7 +18,7 @@ class PythonLSP(BaseLSP):
|
|
|
18
18
|
def _get_script(self, file_path: str):
|
|
19
19
|
if file_path not in self.script_cache:
|
|
20
20
|
try:
|
|
21
|
-
with open(file_path, 'r') as f:
|
|
21
|
+
with open(file_path, 'r', errors="ignore") as f:
|
|
22
22
|
content = f.read()
|
|
23
23
|
self.script_cache[file_path] = jedi.Script(code=content, path=file_path)
|
|
24
24
|
except Exception:
|
|
@@ -54,16 +54,6 @@ class PythonLSP(BaseLSP):
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
def get_document_symbols(self, file_path: str) -> List[Dict[str, Any]]:
|
|
58
|
-
script = self._get_script(file_path)
|
|
59
|
-
if not script:
|
|
60
|
-
return []
|
|
61
|
-
try:
|
|
62
|
-
names = script.get_names()
|
|
63
|
-
return [self._location_to_dict(name) for name in names]
|
|
64
|
-
except Exception:
|
|
65
|
-
return []
|
|
66
|
-
|
|
67
57
|
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
68
58
|
script = self._get_script(file_path)
|
|
69
59
|
if not script:
|
|
@@ -82,24 +72,5 @@ class PythonLSP(BaseLSP):
|
|
|
82
72
|
except Exception:
|
|
83
73
|
return []
|
|
84
74
|
|
|
85
|
-
def prepare_rename(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
|
|
86
|
-
script = self._get_script(file_path)
|
|
87
|
-
if not script:
|
|
88
|
-
return None
|
|
89
|
-
try:
|
|
90
|
-
refs = script.get_references(line=position[0] + 1, column=position[1])
|
|
91
|
-
if refs:
|
|
92
|
-
ref = refs[0]
|
|
93
|
-
return {
|
|
94
|
-
"range": {
|
|
95
|
-
"start": {"line": ref.line - 1, "character": ref.column},
|
|
96
|
-
"end": {"line": ref.line - 1, "character": ref.column + len(ref.name)}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
except Exception:
|
|
100
|
-
return None
|
|
101
|
-
return None
|
|
102
|
-
|
|
103
|
-
|
|
104
75
|
def shutdown(self):
|
|
105
76
|
self.script_cache.clear()
|
jarvis/jarvis_lsp/registry.py
CHANGED
|
@@ -11,9 +11,7 @@ REQUIRED_METHODS = [
|
|
|
11
11
|
('initialize', ['workspace_path']),
|
|
12
12
|
('find_references', ['file_path', 'position']),
|
|
13
13
|
('find_definition', ['file_path', 'position']),
|
|
14
|
-
('get_document_symbols', ['file_path']),
|
|
15
14
|
('get_diagnostics', ['file_path']),
|
|
16
|
-
('prepare_rename', ['file_path', 'position']),
|
|
17
15
|
('shutdown', [])
|
|
18
16
|
]
|
|
19
17
|
|
|
@@ -29,7 +27,7 @@ class LSPRegistry:
|
|
|
29
27
|
if not os.path.exists(user_lsp_dir):
|
|
30
28
|
try:
|
|
31
29
|
os.makedirs(user_lsp_dir)
|
|
32
|
-
with open(os.path.join(user_lsp_dir, "__init__.py"), "w") as f:
|
|
30
|
+
with open(os.path.join(user_lsp_dir, "__init__.py"), "w", errors="ignore") as f:
|
|
33
31
|
pass
|
|
34
32
|
except Exception as e:
|
|
35
33
|
PrettyOutput.print(f"创建 LSP 目录失败: {str(e)}", OutputType.ERROR)
|
|
@@ -100,7 +98,11 @@ class LSPRegistry:
|
|
|
100
98
|
if hasattr(obj, 'check'):
|
|
101
99
|
if not obj.check(): # type: ignore
|
|
102
100
|
continue
|
|
103
|
-
|
|
101
|
+
if isinstance(obj.language, str):
|
|
102
|
+
lsp_servers[obj.language] = obj
|
|
103
|
+
elif isinstance(obj.language, list):
|
|
104
|
+
for lang in obj.language: # type: ignore
|
|
105
|
+
lsp_servers[lang] = obj
|
|
104
106
|
break
|
|
105
107
|
except Exception as e:
|
|
106
108
|
PrettyOutput.print(f"加载 LSP {module_name} 失败: {str(e)}", OutputType.ERROR)
|
|
@@ -154,7 +156,7 @@ class LSPRegistry:
|
|
|
154
156
|
@staticmethod
|
|
155
157
|
def get_text_at_position(file_path: str, line: int, start_character: int) -> str:
|
|
156
158
|
"""Get text at position."""
|
|
157
|
-
with open(file_path, 'r') as file:
|
|
159
|
+
with open(file_path, 'r', errors="ignore") as file:
|
|
158
160
|
lines = file.readlines()
|
|
159
161
|
symbol = re.search(r'\b\w+\b', lines[line][start_character:])
|
|
160
162
|
return symbol.group() if symbol else ""
|
|
@@ -162,7 +164,7 @@ class LSPRegistry:
|
|
|
162
164
|
@staticmethod
|
|
163
165
|
def get_line_at_position(file_path: str, line: int) -> str:
|
|
164
166
|
"""Get line at position."""
|
|
165
|
-
with open(file_path, 'r') as file:
|
|
167
|
+
with open(file_path, 'r', errors="ignore") as file:
|
|
166
168
|
lines = file.readlines()
|
|
167
169
|
return lines[line]
|
|
168
170
|
|
|
@@ -192,14 +194,8 @@ def main():
|
|
|
192
194
|
PrettyOutput.print("LSP 初始化失败", OutputType.WARNING)
|
|
193
195
|
return 1
|
|
194
196
|
|
|
195
|
-
try:
|
|
196
|
-
|
|
197
|
-
if args.action == 'symbols':
|
|
198
|
-
symbols = lsp.get_document_symbols(args.file)
|
|
199
|
-
for symbol in symbols:
|
|
200
|
-
print(f"Symbol {LSPRegistry.get_text_at_position(args.file, symbol['range']['start']['line'], symbol['range']['start']['character'])} at {symbol['range']['start']['line']}:{symbol['range']['start']['character']}: {symbol['uri']}")
|
|
201
|
-
|
|
202
|
-
elif args.action == 'diagnostics':
|
|
197
|
+
try:
|
|
198
|
+
if args.action == 'diagnostics':
|
|
203
199
|
diagnostics = lsp.get_diagnostics(args.file)
|
|
204
200
|
for diag in diagnostics:
|
|
205
201
|
severity = ['Error', 'Warning', 'Info', 'Hint'][diag['severity'] - 1]
|
jarvis/jarvis_lsp/rust.py
CHANGED
|
@@ -89,11 +89,6 @@ class RustLSP(BaseLSP):
|
|
|
89
89
|
})
|
|
90
90
|
return result[0] if result else None
|
|
91
91
|
|
|
92
|
-
def get_document_symbols(self, file_path: str) -> List[Dict[str, Any]]:
|
|
93
|
-
result = self._send_request("textDocument/documentSymbol", {
|
|
94
|
-
"textDocument": {"uri": f"file://{file_path}"}
|
|
95
|
-
})
|
|
96
|
-
return result or [] # type: ignore
|
|
97
92
|
|
|
98
93
|
def get_diagnostics(self, file_path: str) -> List[Dict[str, Any]]:
|
|
99
94
|
# Send didOpen notification to trigger diagnostics
|
|
@@ -115,13 +110,6 @@ class RustLSP(BaseLSP):
|
|
|
115
110
|
pass
|
|
116
111
|
return []
|
|
117
112
|
|
|
118
|
-
def prepare_rename(self, file_path: str, position: Tuple[int, int]) -> Optional[Dict[str, Any]]:
|
|
119
|
-
result = self._send_request("textDocument/prepareRename", {
|
|
120
|
-
"textDocument": {"uri": f"file://{file_path}"},
|
|
121
|
-
"position": {"line": position[0], "character": position[1]}
|
|
122
|
-
})
|
|
123
|
-
return result
|
|
124
|
-
|
|
125
113
|
|
|
126
114
|
def shutdown(self):
|
|
127
115
|
if self.analyzer_process:
|
|
@@ -8,7 +8,7 @@ from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
|
8
8
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
9
9
|
from jarvis.jarvis_utils.input import get_multiline_input
|
|
10
10
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
11
|
-
from jarvis.jarvis_utils.utils import init_env
|
|
11
|
+
from jarvis.jarvis_utils.utils import ct, ot, init_env
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class MultiAgent(OutputHandler):
|
|
@@ -20,12 +20,7 @@ class MultiAgent(OutputHandler):
|
|
|
20
20
|
|
|
21
21
|
def prompt(self) -> str:
|
|
22
22
|
return f"""
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
## 身份与角色定位
|
|
26
|
-
- **核心职责**:作为多智能体系统的协调者,通过结构化消息实现高效协作
|
|
27
|
-
- **关键能力**:消息路由、任务分发、结果整合、流程协调
|
|
28
|
-
- **工作范围**:在多个专业智能体之间建立有效沟通渠道
|
|
23
|
+
# 多智能体消息发送
|
|
29
24
|
|
|
30
25
|
## 交互原则与策略
|
|
31
26
|
### 消息处理规范
|
|
@@ -36,7 +31,7 @@ class MultiAgent(OutputHandler):
|
|
|
36
31
|
|
|
37
32
|
### 消息格式标准
|
|
38
33
|
```
|
|
39
|
-
|
|
34
|
+
{ot("SEND_MESSAGE")}
|
|
40
35
|
to: 智能体名称 # 目标智能体名称
|
|
41
36
|
content: |
|
|
42
37
|
# 消息主题
|
|
@@ -52,31 +47,27 @@ content: |
|
|
|
52
47
|
|
|
53
48
|
## 期望结果
|
|
54
49
|
[描述期望的输出格式和内容]
|
|
55
|
-
|
|
50
|
+
|
|
51
|
+
## 下一步计划
|
|
52
|
+
[描述下一步的计划和行动]
|
|
53
|
+
{ct("SEND_MESSAGE")}
|
|
56
54
|
```
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
### 任务分发流程
|
|
60
|
-
1. **需求分析**:理解用户需求并确定最适合的智能体
|
|
61
|
-
2. **任务分解**:将复杂任务分解为可管理的子任务
|
|
62
|
-
3. **精准分发**:根据专长将任务分配给合适的智能体
|
|
63
|
-
4. **结果整合**:收集各智能体的输出并整合为连贯结果
|
|
56
|
+
或者:
|
|
64
57
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
```
|
|
59
|
+
{ot("SEND_MESSAGE")}
|
|
60
|
+
to: 智能体名称 # 目标智能体名称
|
|
61
|
+
content: |
|
|
62
|
+
# 消息主题
|
|
63
|
+
|
|
64
|
+
## 任务结果
|
|
65
|
+
[任务完成结果,用于反馈]
|
|
66
|
+
{ct("SEND_MESSAGE")}
|
|
67
|
+
```
|
|
70
68
|
|
|
71
69
|
## 可用智能体资源
|
|
72
70
|
{chr(10).join([f"- **{c['name']}**: {c.get('description', '')}" for c in self.agents_config])}
|
|
73
|
-
|
|
74
|
-
## 最佳实践指南
|
|
75
|
-
1. **任务明确化**:每个消息专注于单一、明确的任务
|
|
76
|
-
2. **信息充分性**:提供足够信息让接收者能独立完成任务
|
|
77
|
-
3. **反馈循环**:建立清晰的反馈机制,及时调整方向
|
|
78
|
-
4. **知识共享**:确保关键信息在相关智能体间共享
|
|
79
|
-
5. **协作效率**:避免不必要的消息传递,减少协调开销
|
|
80
71
|
"""
|
|
81
72
|
|
|
82
73
|
def can_handle(self, response: str) -> bool:
|
|
@@ -102,7 +93,7 @@ content: |
|
|
|
102
93
|
Args:
|
|
103
94
|
content: The content containing send message
|
|
104
95
|
"""
|
|
105
|
-
data = re.findall(r'
|
|
96
|
+
data = re.findall(ot("SEND_MESSAGE")+r'\n(.*?)\n'+ct("SEND_MESSAGE"), content, re.DOTALL)
|
|
106
97
|
ret = []
|
|
107
98
|
for item in data:
|
|
108
99
|
try:
|
|
@@ -163,7 +154,7 @@ def main():
|
|
|
163
154
|
args = parser.parse_args()
|
|
164
155
|
|
|
165
156
|
try:
|
|
166
|
-
with open(args.config, 'r') as f:
|
|
157
|
+
with open(args.config, 'r', errors="ignore") as f:
|
|
167
158
|
config_data = yaml.safe_load(f)
|
|
168
159
|
|
|
169
160
|
# 获取agents配置
|
jarvis/jarvis_platform/ai8.py
CHANGED
|
@@ -23,7 +23,6 @@ class AI8Model(BasePlatform):
|
|
|
23
23
|
super().__init__()
|
|
24
24
|
self.system_message = ""
|
|
25
25
|
self.conversation = {}
|
|
26
|
-
self.files = []
|
|
27
26
|
self.models = {} # 存储模型信息
|
|
28
27
|
|
|
29
28
|
self.token = os.getenv("AI8_API_KEY")
|
|
@@ -103,18 +102,6 @@ class AI8Model(BasePlatform):
|
|
|
103
102
|
except Exception as e:
|
|
104
103
|
PrettyOutput.print(f"创建会话失败: {str(e)}", OutputType.ERROR)
|
|
105
104
|
return False
|
|
106
|
-
|
|
107
|
-
def upload_files(self, file_list: List[str]) -> List[Dict]:
|
|
108
|
-
for file_path in file_list:
|
|
109
|
-
name = os.path.basename(file_path)
|
|
110
|
-
with open(file_path, 'rb') as f:
|
|
111
|
-
file_data = f.read()
|
|
112
|
-
base64_data = base64.b64encode(file_data).decode('utf-8')
|
|
113
|
-
self.files.append({
|
|
114
|
-
"name": name,
|
|
115
|
-
"data": f"data:image/png;base64,{base64_data}"
|
|
116
|
-
})
|
|
117
|
-
return self.files
|
|
118
105
|
|
|
119
106
|
def set_system_message(self, message: str):
|
|
120
107
|
"""Set system message"""
|
|
@@ -145,14 +132,6 @@ class AI8Model(BasePlatform):
|
|
|
145
132
|
"files": []
|
|
146
133
|
}
|
|
147
134
|
|
|
148
|
-
# 如果有文件需要发送
|
|
149
|
-
if self.files:
|
|
150
|
-
for file_data in self.files:
|
|
151
|
-
payload["files"].append({
|
|
152
|
-
"name": file_data["name"],
|
|
153
|
-
"data": file_data["data"]
|
|
154
|
-
})
|
|
155
|
-
self.files = [] # 清空已使用的文件
|
|
156
135
|
|
|
157
136
|
response = requests.post(
|
|
158
137
|
f"{self.BASE_URL}/api/chat/completions",
|
|
@@ -200,7 +179,6 @@ class AI8Model(BasePlatform):
|
|
|
200
179
|
def reset(self):
|
|
201
180
|
"""Reset model state"""
|
|
202
181
|
self.conversation = None
|
|
203
|
-
self.files = [] # 清空文件列表
|
|
204
182
|
|
|
205
183
|
def delete_chat(self) -> bool:
|
|
206
184
|
"""Delete current chat session"""
|
|
@@ -284,13 +262,6 @@ class AI8Model(BasePlatform):
|
|
|
284
262
|
# 添加标签
|
|
285
263
|
model_str = f"{model['label']}"
|
|
286
264
|
|
|
287
|
-
# 添加标签和积分信息
|
|
288
|
-
attrs = []
|
|
289
|
-
if model['attr'].get('tag'):
|
|
290
|
-
attrs.append(model['attr']['tag'])
|
|
291
|
-
if model['attr'].get('integral'):
|
|
292
|
-
attrs.append(model['attr']['integral'])
|
|
293
|
-
|
|
294
265
|
# 添加特性标记
|
|
295
266
|
features = []
|
|
296
267
|
if model['attr'].get('multimodal'):
|
|
@@ -299,12 +270,16 @@ class AI8Model(BasePlatform):
|
|
|
299
270
|
features.append("Plugin support")
|
|
300
271
|
if model['attr'].get('onlyImg'):
|
|
301
272
|
features.append("Image support")
|
|
302
|
-
if
|
|
303
|
-
|
|
304
|
-
|
|
273
|
+
if model['attr'].get('tag'):
|
|
274
|
+
features.append(model['attr']['tag'])
|
|
275
|
+
if model['attr'].get('integral'):
|
|
276
|
+
features.append(model['attr']['integral'])
|
|
305
277
|
# 添加备注
|
|
306
278
|
if model['attr'].get('note'):
|
|
307
279
|
model_str += f" - {model['attr']['note']}"
|
|
280
|
+
if features:
|
|
281
|
+
model_str += f" [{'|'.join(features)}]"
|
|
282
|
+
|
|
308
283
|
model['desc'] = model_str
|
|
309
284
|
|
|
310
285
|
return list(self.models.keys())
|
jarvis/jarvis_platform/base.py
CHANGED
|
@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
|
|
|
2
2
|
import re
|
|
3
3
|
from typing import Dict, List, Tuple
|
|
4
4
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
5
|
-
from jarvis.jarvis_utils.utils import get_context_token_count, while_success, while_true
|
|
5
|
+
from jarvis.jarvis_utils.utils import ct, ot, get_context_token_count, while_success, while_true
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class BasePlatform(ABC):
|
|
@@ -53,16 +53,11 @@ class BasePlatform(ABC):
|
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
# Keep original think tag handling
|
|
56
|
-
response = re.sub(r'
|
|
56
|
+
response = re.sub(ot("think")+r'.*?'+ct("think"), '', response, flags=re.DOTALL)
|
|
57
57
|
return response
|
|
58
58
|
|
|
59
59
|
return while_true(lambda: while_success(lambda: _chat(), 5), 5)
|
|
60
60
|
|
|
61
|
-
@abstractmethod
|
|
62
|
-
def upload_files(self, file_list: List[str]) -> List[Dict]:
|
|
63
|
-
"""Upload files"""
|
|
64
|
-
raise NotImplementedError("upload_files is not implemented")
|
|
65
|
-
|
|
66
61
|
@abstractmethod
|
|
67
62
|
def reset(self):
|
|
68
63
|
"""Reset model"""
|