jarvis-ai-assistant 0.1.193__py3-none-any.whl → 0.1.195__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 +45 -41
- jarvis/jarvis_agent/builtin_input_handler.py +26 -4
- jarvis/jarvis_agent/jarvis.py +30 -19
- jarvis/jarvis_agent/main.py +20 -12
- jarvis/jarvis_agent/output_handler.py +7 -7
- jarvis/jarvis_agent/shell_input_handler.py +14 -11
- jarvis/jarvis_code_agent/code_agent.py +81 -79
- jarvis/jarvis_code_agent/lint.py +92 -105
- jarvis/jarvis_code_analysis/checklists/__init__.py +1 -1
- jarvis/jarvis_code_analysis/checklists/c_cpp.py +1 -1
- jarvis/jarvis_code_analysis/checklists/csharp.py +1 -1
- jarvis/jarvis_code_analysis/checklists/data_format.py +1 -1
- jarvis/jarvis_code_analysis/checklists/devops.py +1 -1
- jarvis/jarvis_code_analysis/checklists/docs.py +1 -1
- jarvis/jarvis_code_analysis/checklists/go.py +1 -1
- jarvis/jarvis_code_analysis/checklists/infrastructure.py +1 -1
- jarvis/jarvis_code_analysis/checklists/java.py +1 -1
- jarvis/jarvis_code_analysis/checklists/javascript.py +1 -1
- jarvis/jarvis_code_analysis/checklists/kotlin.py +1 -1
- jarvis/jarvis_code_analysis/checklists/loader.py +31 -29
- jarvis/jarvis_code_analysis/checklists/php.py +1 -1
- jarvis/jarvis_code_analysis/checklists/python.py +1 -1
- jarvis/jarvis_code_analysis/checklists/ruby.py +1 -1
- jarvis/jarvis_code_analysis/checklists/rust.py +1 -1
- jarvis/jarvis_code_analysis/checklists/shell.py +1 -1
- jarvis/jarvis_code_analysis/checklists/sql.py +1 -1
- jarvis/jarvis_code_analysis/checklists/swift.py +1 -1
- jarvis/jarvis_code_analysis/checklists/web.py +1 -1
- jarvis/jarvis_code_analysis/code_review.py +292 -190
- jarvis/jarvis_dev/main.py +73 -56
- jarvis/jarvis_git_details/main.py +29 -33
- jarvis/jarvis_git_squash/main.py +13 -11
- jarvis/jarvis_git_utils/git_commiter.py +15 -5
- jarvis/jarvis_mcp/__init__.py +8 -10
- jarvis/jarvis_mcp/sse_mcp_client.py +182 -205
- jarvis/jarvis_mcp/stdio_mcp_client.py +93 -120
- jarvis/jarvis_mcp/streamable_mcp_client.py +117 -142
- jarvis/jarvis_methodology/main.py +71 -39
- jarvis/jarvis_multi_agent/__init__.py +24 -16
- jarvis/jarvis_multi_agent/main.py +10 -4
- jarvis/jarvis_platform/__init__.py +1 -1
- jarvis/jarvis_platform/base.py +44 -18
- jarvis/jarvis_platform/human.py +15 -3
- jarvis/jarvis_platform/kimi.py +117 -81
- jarvis/jarvis_platform/openai.py +23 -28
- jarvis/jarvis_platform/registry.py +43 -29
- jarvis/jarvis_platform/tongyi.py +16 -10
- jarvis/jarvis_platform/yuanbao.py +197 -144
- jarvis/jarvis_platform_manager/main.py +4 -2
- jarvis/jarvis_smart_shell/main.py +35 -30
- jarvis/jarvis_tools/ask_user.py +8 -16
- jarvis/jarvis_tools/base.py +3 -2
- jarvis/jarvis_tools/chdir.py +7 -19
- jarvis/jarvis_tools/cli/main.py +14 -10
- jarvis/jarvis_tools/code_plan.py +10 -31
- jarvis/jarvis_tools/create_code_agent.py +6 -11
- jarvis/jarvis_tools/create_sub_agent.py +10 -22
- jarvis/jarvis_tools/edit_file.py +98 -76
- jarvis/jarvis_tools/execute_script.py +46 -46
- jarvis/jarvis_tools/file_analyzer.py +22 -34
- jarvis/jarvis_tools/file_operation.py +69 -62
- jarvis/jarvis_tools/generate_new_tool.py +0 -2
- jarvis/jarvis_tools/methodology.py +19 -23
- jarvis/jarvis_tools/read_code.py +35 -35
- jarvis/jarvis_tools/read_webpage.py +7 -16
- jarvis/jarvis_tools/registry.py +63 -30
- jarvis/jarvis_tools/rewrite_file.py +26 -29
- jarvis/jarvis_tools/search_web.py +5 -8
- jarvis/jarvis_tools/virtual_tty.py +133 -122
- jarvis/jarvis_utils/__init__.py +0 -1
- jarvis/jarvis_utils/builtin_replace_map.py +9 -9
- jarvis/jarvis_utils/config.py +60 -37
- jarvis/jarvis_utils/embedding.py +24 -19
- jarvis/jarvis_utils/file_processors.py +16 -9
- jarvis/jarvis_utils/git_utils.py +157 -107
- jarvis/jarvis_utils/globals.py +1 -1
- jarvis/jarvis_utils/input.py +85 -52
- jarvis/jarvis_utils/jarvis_history.py +43 -0
- jarvis/jarvis_utils/methodology.py +31 -24
- jarvis/jarvis_utils/output.py +164 -80
- jarvis/jarvis_utils/tag.py +2 -1
- jarvis/jarvis_utils/utils.py +84 -52
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/METADATA +362 -230
- jarvis_ai_assistant-0.1.195.dist-info/RECORD +98 -0
- jarvis/jarvis_agent/file_input_handler.py +0 -112
- jarvis/jarvis_event/__init__.py +0 -0
- jarvis_ai_assistant-0.1.193.dist-info/RECORD +0 -99
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.193.dist-info → jarvis_ai_assistant-0.1.195.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_agent/__init__.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# 标准库导入
|
3
3
|
import datetime
|
4
|
+
from pathlib import Path
|
4
5
|
import platform
|
5
6
|
from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
|
6
7
|
|
@@ -13,15 +14,17 @@ from yaspin import yaspin # type: ignore
|
|
13
14
|
from jarvis.jarvis_platform.base import BasePlatform
|
14
15
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
15
16
|
# jarvis_utils 相关
|
16
|
-
from jarvis.jarvis_utils.config import (get_max_token_count,
|
17
|
+
from jarvis.jarvis_utils.config import (get_data_dir, get_max_token_count,
|
17
18
|
get_max_tool_call_count,
|
18
19
|
is_auto_complete,
|
19
20
|
is_execute_tool_confirm,
|
20
21
|
is_use_analysis, is_use_methodology)
|
21
22
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
22
|
-
from jarvis.jarvis_utils.globals import (delete_agent, get_interrupt,
|
23
|
-
set_agent,
|
23
|
+
from jarvis.jarvis_utils.globals import (delete_agent, get_interrupt,
|
24
|
+
make_agent_name, set_agent,
|
25
|
+
set_interrupt)
|
24
26
|
from jarvis.jarvis_utils.input import get_multiline_input
|
27
|
+
from jarvis.jarvis_utils.jarvis_history import JarvisHistory
|
25
28
|
from jarvis.jarvis_utils.methodology import (load_methodology,
|
26
29
|
upload_methodology)
|
27
30
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
@@ -112,28 +115,16 @@ origin_agent_system_prompt = f"""
|
|
112
115
|
|
113
116
|
|
114
117
|
class OutputHandlerProtocol(Protocol):
|
115
|
-
def name(self) -> str:
|
116
|
-
...
|
118
|
+
def name(self) -> str: ...
|
117
119
|
|
118
|
-
def can_handle(self, response: str) -> bool:
|
119
|
-
...
|
120
|
+
def can_handle(self, response: str) -> bool: ...
|
120
121
|
|
121
|
-
def prompt(self) -> str:
|
122
|
-
...
|
122
|
+
def prompt(self) -> str: ...
|
123
123
|
|
124
|
-
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
|
125
|
-
...
|
124
|
+
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]: ...
|
126
125
|
|
127
126
|
|
128
127
|
class Agent:
|
129
|
-
def set_summary_prompt(self, summary_prompt: str):
|
130
|
-
"""设置任务完成时的总结提示模板。
|
131
|
-
|
132
|
-
参数:
|
133
|
-
summary_prompt: 用于生成任务总结的提示模板
|
134
|
-
"""
|
135
|
-
self.summary_prompt = summary_prompt
|
136
|
-
|
137
128
|
def clear(self):
|
138
129
|
"""清除当前对话历史,保留系统消息。
|
139
130
|
|
@@ -147,6 +138,7 @@ class Agent:
|
|
147
138
|
self.prompt = ""
|
148
139
|
|
149
140
|
def __del__(self):
|
141
|
+
self.history.stop_record()
|
150
142
|
delete_agent(self.name)
|
151
143
|
|
152
144
|
def __init__(
|
@@ -195,7 +187,9 @@ class Agent:
|
|
195
187
|
if isinstance(platform, str):
|
196
188
|
self.model = PlatformRegistry().create_platform(platform)
|
197
189
|
if self.model is None:
|
198
|
-
PrettyOutput.print(
|
190
|
+
PrettyOutput.print(
|
191
|
+
f"平台 {platform} 不存在,将使用普通模型", OutputType.WARNING
|
192
|
+
)
|
199
193
|
self.model = PlatformRegistry().get_normal_platform()
|
200
194
|
else:
|
201
195
|
self.model = platform
|
@@ -243,6 +237,9 @@ class Agent:
|
|
243
237
|
self.max_tool_call_count = get_max_tool_call_count()
|
244
238
|
self.after_tool_call_cb: Optional[Callable[[Agent], None]] = None
|
245
239
|
|
240
|
+
self.history = JarvisHistory()
|
241
|
+
self.history.start_record(str(Path(get_data_dir())/"history"))
|
242
|
+
|
246
243
|
self.execute_tool_confirm = (
|
247
244
|
execute_tool_confirm
|
248
245
|
if execute_tool_confirm is not None
|
@@ -404,8 +401,10 @@ class Agent:
|
|
404
401
|
if self.conversation_length > self.max_token_count:
|
405
402
|
message = self._summarize_and_clear_history() + "\n\n" + message
|
406
403
|
self.conversation_length += get_context_token_count(message)
|
404
|
+
self.history.append_msg("user", message)
|
407
405
|
response = self.model.chat_until_success(message) # type: ignore
|
408
406
|
self.conversation_length += get_context_token_count(response)
|
407
|
+
self.history.append_msg("assistant", response)
|
409
408
|
return response
|
410
409
|
|
411
410
|
def generate_summary(self) -> str:
|
@@ -528,7 +527,9 @@ class Agent:
|
|
528
527
|
if not self.execute_tool_confirm or user_confirm(
|
529
528
|
f"需要执行{tool_list[0].name()}确认执行?", True
|
530
529
|
):
|
531
|
-
with yaspin(
|
530
|
+
with yaspin(
|
531
|
+
text=f"正在执行{tool_list[0].name()}...", color="cyan"
|
532
|
+
) as spinner:
|
532
533
|
with spinner.hidden():
|
533
534
|
result = tool_list[0].handle(response, self)
|
534
535
|
spinner.text = f"{tool_list[0].name()}执行完成"
|
@@ -726,7 +727,6 @@ arguments:
|
|
726
727
|
spinner.text = "分析失败"
|
727
728
|
spinner.fail("❌")
|
728
729
|
|
729
|
-
|
730
730
|
def make_default_addon_prompt(self, need_complete: bool) -> str:
|
731
731
|
"""生成附加提示。
|
732
732
|
|
@@ -734,7 +734,6 @@ arguments:
|
|
734
734
|
need_complete: 是否需要完成任务
|
735
735
|
|
736
736
|
"""
|
737
|
-
return ""
|
738
737
|
# 结构化系统指令
|
739
738
|
action_handlers = ", ".join([handler.name() for handler in self.output_handler])
|
740
739
|
|
@@ -762,7 +761,6 @@ arguments:
|
|
762
761
|
|
763
762
|
return addon_prompt
|
764
763
|
|
765
|
-
|
766
764
|
def run(self, user_input: str) -> Any:
|
767
765
|
"""处理用户输入并执行任务
|
768
766
|
|
@@ -786,17 +784,23 @@ arguments:
|
|
786
784
|
while True:
|
787
785
|
if self.first:
|
788
786
|
# 如果有上传文件,先上传文件
|
789
|
-
if (
|
790
|
-
self.
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
787
|
+
if self.model and self.model.support_upload_files():
|
788
|
+
if self.use_methodology:
|
789
|
+
if not upload_methodology(self.model, other_files=self.files):
|
790
|
+
if self.files:
|
791
|
+
PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
|
792
|
+
# 上传失败则回退到本地加载
|
793
|
+
msg = self.prompt
|
794
|
+
for handler in self.input_handler:
|
795
|
+
msg, _ = handler(msg, self)
|
796
|
+
self.prompt = f"{self.prompt}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg, self.get_tool_registry())}"
|
797
|
+
elif self.files:
|
798
|
+
if not self.model.upload_files(self.files):
|
799
|
+
PrettyOutput.print("文件上传失败,将忽略文件列表", OutputType.WARNING)
|
800
|
+
else:
|
801
|
+
if self.files:
|
802
|
+
PrettyOutput.print("不支持上传文件,将忽略文件列表", OutputType.WARNING)
|
803
|
+
if self.use_methodology:
|
800
804
|
msg = self.prompt
|
801
805
|
for handler in self.input_handler:
|
802
806
|
msg, _ = handler(msg, self)
|
@@ -807,20 +811,20 @@ arguments:
|
|
807
811
|
current_response = self._call_model(self.prompt, True)
|
808
812
|
self.prompt = ""
|
809
813
|
|
810
|
-
need_return, self.prompt = self._call_tools(current_response)
|
811
|
-
|
812
|
-
if need_return:
|
813
|
-
return self.prompt
|
814
|
-
|
815
814
|
if get_interrupt():
|
816
815
|
set_interrupt(False)
|
817
816
|
user_input = self.multiline_inputer(
|
818
817
|
f"模型交互期间被中断,请输入用户干预信息:"
|
819
818
|
)
|
820
819
|
if user_input:
|
821
|
-
self.prompt += f"
|
820
|
+
self.prompt += f"{user_input}"
|
822
821
|
continue
|
823
822
|
|
823
|
+
need_return, self.prompt = self._call_tools(current_response)
|
824
|
+
|
825
|
+
if need_return:
|
826
|
+
return self.prompt
|
827
|
+
|
824
828
|
if self.after_tool_call_cb:
|
825
829
|
self.after_tool_call_cb(self)
|
826
830
|
|
@@ -5,7 +5,7 @@ from typing import Any, Tuple
|
|
5
5
|
from jarvis.jarvis_utils.config import get_replace_map
|
6
6
|
|
7
7
|
|
8
|
-
def builtin_input_handler(user_input: str,
|
8
|
+
def builtin_input_handler(user_input: str, agent_: Any) -> Tuple[str, bool]:
|
9
9
|
"""
|
10
10
|
处理内置的特殊输入标记,并追加相应的提示词
|
11
11
|
|
@@ -16,6 +16,9 @@ def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
16
16
|
返回:
|
17
17
|
Tuple[str, bool]: 处理后的输入和是否需要进一步处理
|
18
18
|
"""
|
19
|
+
from jarvis.jarvis_agent import Agent
|
20
|
+
|
21
|
+
agent: Agent = agent_
|
19
22
|
# 查找特殊标记
|
20
23
|
special_tags = re.findall(r"'<([^>]+)>'", user_input)
|
21
24
|
|
@@ -34,18 +37,37 @@ def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
34
37
|
elif tag == "Clear":
|
35
38
|
agent.clear()
|
36
39
|
return "", True
|
37
|
-
|
40
|
+
elif tag == "ToolUsage":
|
41
|
+
from jarvis.jarvis_tools.registry import ToolRegistry
|
42
|
+
|
43
|
+
tool_registry_ = agent.get_tool_registry()
|
44
|
+
tool_registry: ToolRegistry = (
|
45
|
+
tool_registry_ if tool_registry_ else ToolRegistry()
|
46
|
+
)
|
47
|
+
agent.set_addon_prompt(tool_registry.prompt())
|
48
|
+
elif tag == "ReloadConfig":
|
49
|
+
from jarvis.jarvis_utils.utils import load_config
|
50
|
+
|
51
|
+
load_config()
|
52
|
+
return "", True
|
53
|
+
|
38
54
|
processed_tag = set()
|
39
55
|
add_on_prompt = ""
|
40
56
|
|
41
57
|
# 处理普通替换标记
|
42
58
|
if tag in replace_map:
|
43
59
|
processed_tag.add(tag)
|
44
|
-
if
|
60
|
+
if (
|
61
|
+
"append" in replace_map[tag]
|
62
|
+
and replace_map[tag]["append"]
|
63
|
+
and tag not in processed_tag
|
64
|
+
):
|
45
65
|
user_input = user_input.replace(f"'<{tag}>'", "")
|
46
66
|
add_on_prompt += replace_map[tag]["template"] + "\n"
|
47
67
|
else:
|
48
|
-
user_input = user_input.replace(
|
68
|
+
user_input = user_input.replace(
|
69
|
+
f"'<{tag}>'", replace_map[tag]["template"]
|
70
|
+
)
|
49
71
|
|
50
72
|
agent.set_addon_prompt(add_on_prompt)
|
51
73
|
|
jarvis/jarvis_agent/jarvis.py
CHANGED
@@ -29,7 +29,9 @@ def _load_tasks() -> Dict[str, str]:
|
|
29
29
|
spinner_text = f"从{pre_command_path}加载预定义任务..."
|
30
30
|
with yaspin(text=spinner_text, color="cyan") as spinner:
|
31
31
|
try:
|
32
|
-
with open(
|
32
|
+
with open(
|
33
|
+
pre_command_path, "r", encoding="utf-8", errors="ignore"
|
34
|
+
) as f:
|
33
35
|
user_tasks = yaml.safe_load(f)
|
34
36
|
if isinstance(user_tasks, dict):
|
35
37
|
for name, desc in user_tasks.items():
|
@@ -48,7 +50,9 @@ def _load_tasks() -> Dict[str, str]:
|
|
48
50
|
spinner_text = f"从{abs_path}加载预定义任务..."
|
49
51
|
with yaspin(text=spinner_text, color="cyan") as spinner:
|
50
52
|
try:
|
51
|
-
with open(
|
53
|
+
with open(
|
54
|
+
pre_command_path, "r", encoding="utf-8", errors="ignore"
|
55
|
+
) as f:
|
52
56
|
local_tasks = yaml.safe_load(f)
|
53
57
|
if isinstance(local_tasks, dict):
|
54
58
|
for name, desc in local_tasks.items():
|
@@ -62,11 +66,12 @@ def _load_tasks() -> Dict[str, str]:
|
|
62
66
|
|
63
67
|
return tasks
|
64
68
|
|
69
|
+
|
65
70
|
def _select_task(tasks: Dict[str, str]) -> str:
|
66
71
|
"""Let user select a task from the list or skip. Returns task description if selected."""
|
67
72
|
if not tasks:
|
68
73
|
return ""
|
69
|
-
|
74
|
+
|
70
75
|
task_names = list(tasks.keys())
|
71
76
|
task_list = ["可用任务:"]
|
72
77
|
for i, name in enumerate(task_names, 1):
|
@@ -74,7 +79,6 @@ def _select_task(tasks: Dict[str, str]) -> str:
|
|
74
79
|
task_list.append("[0] 跳过预定义任务")
|
75
80
|
PrettyOutput.print("\n".join(task_list), OutputType.INFO)
|
76
81
|
|
77
|
-
|
78
82
|
while True:
|
79
83
|
try:
|
80
84
|
choice_str = prompt("\n请选择一个任务编号(0 跳过预定义任务):").strip()
|
@@ -88,13 +92,19 @@ def _select_task(tasks: Dict[str, str]) -> str:
|
|
88
92
|
selected_task = tasks[task_names[choice - 1]]
|
89
93
|
PrettyOutput.print(f"将要执行任务:\n {selected_task}", OutputType.INFO)
|
90
94
|
# 询问是否需要补充信息
|
91
|
-
need_additional = user_confirm(
|
95
|
+
need_additional = user_confirm(
|
96
|
+
"需要为此任务添加补充信息吗?", default=False
|
97
|
+
)
|
92
98
|
if need_additional:
|
93
99
|
additional_input = get_multiline_input("请输入补充信息:")
|
94
100
|
if additional_input:
|
95
|
-
selected_task =
|
101
|
+
selected_task = (
|
102
|
+
f"{selected_task}\n\n补充信息:\n{additional_input}"
|
103
|
+
)
|
96
104
|
return selected_task
|
97
|
-
PrettyOutput.print(
|
105
|
+
PrettyOutput.print(
|
106
|
+
"无效的选择。请选择列表中的一个号码。", OutputType.WARNING
|
107
|
+
)
|
98
108
|
|
99
109
|
except (KeyboardInterrupt, EOFError):
|
100
110
|
return ""
|
@@ -104,26 +114,26 @@ def _select_task(tasks: Dict[str, str]) -> str:
|
|
104
114
|
|
105
115
|
def main() -> None:
|
106
116
|
|
107
|
-
|
108
|
-
parser =
|
109
|
-
parser.add_argument(
|
110
|
-
parser.add_argument(
|
111
|
-
|
112
|
-
|
117
|
+
parser = argparse.ArgumentParser(description="Jarvis AI assistant")
|
118
|
+
parser.add_argument("-p", "--platform", type=str, help="Platform to use")
|
119
|
+
parser.add_argument("-m", "--model", type=str, help="Model to use")
|
120
|
+
parser.add_argument(
|
121
|
+
"-t", "--task", type=str, help="Directly input task content from command line"
|
122
|
+
)
|
123
|
+
parser.add_argument("-f", "--config", type=str, help="Path to custom config file")
|
113
124
|
args = parser.parse_args()
|
114
|
-
init_env(
|
125
|
+
init_env(
|
126
|
+
"欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=args.config
|
127
|
+
)
|
115
128
|
|
116
129
|
try:
|
117
130
|
agent = Agent(
|
118
131
|
system_prompt=origin_agent_system_prompt,
|
119
132
|
platform=args.platform,
|
120
133
|
model_name=args.model,
|
121
|
-
input_handler=[
|
122
|
-
shell_input_handler,
|
123
|
-
builtin_input_handler
|
124
|
-
],
|
134
|
+
input_handler=[shell_input_handler, builtin_input_handler],
|
125
135
|
output_handler=[ToolRegistry()],
|
126
|
-
need_summary=False
|
136
|
+
need_summary=False,
|
127
137
|
)
|
128
138
|
|
129
139
|
# 优先处理命令行直接传入的任务
|
@@ -146,5 +156,6 @@ def main() -> None:
|
|
146
156
|
PrettyOutput.print(f"初始化错误: {str(err)}", OutputType.ERROR)
|
147
157
|
sys.exit(1)
|
148
158
|
|
159
|
+
|
149
160
|
if __name__ == "__main__":
|
150
161
|
main()
|
jarvis/jarvis_agent/main.py
CHANGED
@@ -20,10 +20,12 @@ def load_config(config_path: str) -> dict:
|
|
20
20
|
dict: 配置字典
|
21
21
|
"""
|
22
22
|
if not os.path.exists(config_path):
|
23
|
-
PrettyOutput.print(
|
23
|
+
PrettyOutput.print(
|
24
|
+
f"配置文件 {config_path} 不存在,使用默认配置", OutputType.WARNING
|
25
|
+
)
|
24
26
|
return {}
|
25
27
|
|
26
|
-
with open(config_path,
|
28
|
+
with open(config_path, "r", encoding="utf-8", errors="ignore") as f:
|
27
29
|
try:
|
28
30
|
config = yaml.safe_load(f)
|
29
31
|
return config if config else {}
|
@@ -31,20 +33,24 @@ def load_config(config_path: str) -> dict:
|
|
31
33
|
PrettyOutput.print(f"配置文件解析失败: {str(e)}", OutputType.ERROR)
|
32
34
|
return {}
|
33
35
|
|
36
|
+
|
34
37
|
def main():
|
35
38
|
"""Main entry point for Jarvis agent"""
|
36
39
|
# Set up argument parser
|
37
|
-
parser = argparse.ArgumentParser(description=
|
38
|
-
parser.add_argument(
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
parser = argparse.ArgumentParser(description="Jarvis AI assistant")
|
41
|
+
parser.add_argument(
|
42
|
+
"-f", "--config", type=str, required=False, help="Path to agent config file"
|
43
|
+
)
|
44
|
+
parser.add_argument(
|
45
|
+
"-c", "--agent_definition", type=str, help="Path to agent definition file"
|
46
|
+
)
|
47
|
+
parser.add_argument("-t", "--task", type=str, help="Initial task to execute")
|
44
48
|
args = parser.parse_args()
|
45
49
|
|
46
50
|
# Initialize environment
|
47
|
-
init_env(
|
51
|
+
init_env(
|
52
|
+
"欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=args.config
|
53
|
+
)
|
48
54
|
|
49
55
|
# Load configuration
|
50
56
|
config = load_config(args.agent_definition) if args.agent_definition else {}
|
@@ -59,12 +65,13 @@ def main():
|
|
59
65
|
agent.run(args.task)
|
60
66
|
return 0
|
61
67
|
|
62
|
-
|
63
68
|
try:
|
64
69
|
user_input = get_multiline_input("请输入你的任务(输入空行退出):")
|
65
70
|
if not user_input:
|
66
71
|
return 0
|
67
|
-
agent.set_addon_prompt(
|
72
|
+
agent.set_addon_prompt(
|
73
|
+
"如果有必要,请先指定出行动计划,然后根据计划一步步执行,如果任务过于复杂,可以拆分子Agent进行执行,拆的子Agent需要掌握所有必要的任务信息,否则无法执行"
|
74
|
+
)
|
68
75
|
agent.run(user_input)
|
69
76
|
except Exception as e:
|
70
77
|
PrettyOutput.print(f"错误: {str(e)}", OutputType.ERROR)
|
@@ -75,5 +82,6 @@ def main():
|
|
75
82
|
|
76
83
|
return 0
|
77
84
|
|
85
|
+
|
78
86
|
if __name__ == "__main__":
|
79
87
|
exit(main())
|
@@ -7,11 +7,11 @@ class OutputHandler(ABC):
|
|
7
7
|
@abstractmethod
|
8
8
|
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
|
9
9
|
"""处理响应数据
|
10
|
-
|
10
|
+
|
11
11
|
Args:
|
12
12
|
response: 需要处理的响应字符串
|
13
13
|
agent: 执行处理的agent实例
|
14
|
-
|
14
|
+
|
15
15
|
Returns:
|
16
16
|
Tuple[bool, Any]: 返回处理结果元组,第一个元素表示是否处理成功,第二个元素为处理后的数据
|
17
17
|
"""
|
@@ -20,10 +20,10 @@ class OutputHandler(ABC):
|
|
20
20
|
@abstractmethod
|
21
21
|
def can_handle(self, response: str) -> bool:
|
22
22
|
"""判断是否能处理给定的响应
|
23
|
-
|
23
|
+
|
24
24
|
Args:
|
25
25
|
response: 需要判断的响应字符串
|
26
|
-
|
26
|
+
|
27
27
|
Returns:
|
28
28
|
bool: 返回是否能处理该响应
|
29
29
|
"""
|
@@ -32,7 +32,7 @@ class OutputHandler(ABC):
|
|
32
32
|
@abstractmethod
|
33
33
|
def prompt(self) -> str:
|
34
34
|
"""获取处理器的提示信息
|
35
|
-
|
35
|
+
|
36
36
|
Returns:
|
37
37
|
str: 返回处理器的提示字符串
|
38
38
|
"""
|
@@ -41,8 +41,8 @@ class OutputHandler(ABC):
|
|
41
41
|
@abstractmethod
|
42
42
|
def name(self) -> str:
|
43
43
|
"""获取处理器的名称
|
44
|
-
|
44
|
+
|
45
45
|
Returns:
|
46
46
|
str: 返回处理器的名称字符串
|
47
47
|
"""
|
48
|
-
pass
|
48
|
+
pass
|
@@ -11,20 +11,23 @@ def shell_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
11
11
|
if len(cmdline) == 0:
|
12
12
|
return user_input, False
|
13
13
|
else:
|
14
|
-
script =
|
14
|
+
script = "\n".join([c[1:] for c in cmdline])
|
15
15
|
PrettyOutput.print(script, OutputType.CODE, lang="bash")
|
16
16
|
if user_confirm(f"是否要执行以上shell脚本?", default=True):
|
17
17
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
"
|
23
|
-
"script_content": script
|
24
|
-
}
|
25
|
-
|
18
|
+
|
19
|
+
output = ToolRegistry().handle_tool_calls(
|
20
|
+
{
|
21
|
+
"name": "execute_script",
|
22
|
+
"want": "提取命令执行结果关键信息",
|
23
|
+
"arguments": {"interpreter": "bash", "script_content": script},
|
24
|
+
},
|
25
|
+
agent,
|
26
|
+
)
|
26
27
|
if user_confirm("是否将执行结果反馈给Agent?", default=True):
|
27
|
-
return
|
28
|
+
return (
|
29
|
+
f"{user_input}\n\n用户执行以下脚本:\n{script}\n\n执行结果:\n{output}",
|
30
|
+
False,
|
31
|
+
)
|
28
32
|
return "", True
|
29
33
|
return user_input, False
|
30
|
-
|