jarvis-ai-assistant 0.1.192__py3-none-any.whl → 0.1.194__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 +69 -37
- jarvis/jarvis_agent/builtin_input_handler.py +26 -4
- jarvis/jarvis_agent/jarvis.py +38 -22
- 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 +93 -90
- 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 +51 -35
- 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 +293 -192
- 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 +12 -3
- 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 +81 -47
- 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 +49 -21
- jarvis/jarvis_platform/human.py +5 -3
- jarvis/jarvis_platform/kimi.py +96 -72
- jarvis/jarvis_platform/openai.py +23 -28
- jarvis/jarvis_platform/registry.py +50 -33
- jarvis/jarvis_platform/tongyi.py +16 -10
- jarvis/jarvis_platform/yuanbao.py +205 -147
- jarvis/jarvis_platform_manager/main.py +4 -2
- jarvis/jarvis_smart_shell/main.py +35 -29
- 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 +10 -13
- 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 +42 -33
- jarvis/jarvis_tools/read_webpage.py +7 -16
- jarvis/jarvis_tools/registry.py +65 -32
- 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 +96 -8
- jarvis/jarvis_utils/config.py +59 -32
- jarvis/jarvis_utils/embedding.py +17 -14
- jarvis/jarvis_utils/file_processors.py +16 -9
- jarvis/jarvis_utils/git_utils.py +140 -99
- jarvis/jarvis_utils/globals.py +1 -1
- jarvis/jarvis_utils/input.py +84 -52
- jarvis/jarvis_utils/methodology.py +28 -21
- jarvis/jarvis_utils/output.py +159 -78
- jarvis/jarvis_utils/tag.py +2 -1
- jarvis/jarvis_utils/utils.py +85 -51
- {jarvis_ai_assistant-0.1.192.dist-info → jarvis_ai_assistant-0.1.194.dist-info}/METADATA +337 -204
- jarvis_ai_assistant-0.1.194.dist-info/RECORD +97 -0
- jarvis/jarvis_agent/file_input_handler.py +0 -112
- jarvis/jarvis_event/__init__.py +0 -0
- jarvis_ai_assistant-0.1.192.dist-info/RECORD +0 -99
- {jarvis_ai_assistant-0.1.192.dist-info → jarvis_ai_assistant-0.1.194.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.192.dist-info → jarvis_ai_assistant-0.1.194.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.192.dist-info → jarvis_ai_assistant-0.1.194.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.192.dist-info → jarvis_ai_assistant-0.1.194.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
jarvis/jarvis_agent/__init__.py
CHANGED
@@ -12,18 +12,26 @@ from yaspin import yaspin # type: ignore
|
|
12
12
|
# jarvis_platform 相关
|
13
13
|
from jarvis.jarvis_platform.base import BasePlatform
|
14
14
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
15
|
+
|
15
16
|
# jarvis_utils 相关
|
16
|
-
from jarvis.jarvis_utils.config import (
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
from jarvis.jarvis_utils.config import (
|
18
|
+
get_max_token_count,
|
19
|
+
get_max_tool_call_count,
|
20
|
+
is_auto_complete,
|
21
|
+
is_execute_tool_confirm,
|
22
|
+
is_use_analysis,
|
23
|
+
is_use_methodology,
|
24
|
+
)
|
21
25
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
22
|
-
from jarvis.jarvis_utils.globals import (
|
23
|
-
|
26
|
+
from jarvis.jarvis_utils.globals import (
|
27
|
+
delete_agent,
|
28
|
+
get_interrupt,
|
29
|
+
make_agent_name,
|
30
|
+
set_agent,
|
31
|
+
set_interrupt,
|
32
|
+
)
|
24
33
|
from jarvis.jarvis_utils.input import get_multiline_input
|
25
|
-
from jarvis.jarvis_utils.methodology import
|
26
|
-
upload_methodology)
|
34
|
+
from jarvis.jarvis_utils.methodology import load_methodology, upload_methodology
|
27
35
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
28
36
|
from jarvis.jarvis_utils.tag import ct, ot
|
29
37
|
from jarvis.jarvis_utils.utils import user_confirm
|
@@ -112,28 +120,16 @@ origin_agent_system_prompt = f"""
|
|
112
120
|
|
113
121
|
|
114
122
|
class OutputHandlerProtocol(Protocol):
|
115
|
-
def name(self) -> str:
|
116
|
-
...
|
123
|
+
def name(self) -> str: ...
|
117
124
|
|
118
|
-
def can_handle(self, response: str) -> bool:
|
119
|
-
...
|
125
|
+
def can_handle(self, response: str) -> bool: ...
|
120
126
|
|
121
|
-
def prompt(self) -> str:
|
122
|
-
...
|
127
|
+
def prompt(self) -> str: ...
|
123
128
|
|
124
|
-
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
|
125
|
-
...
|
129
|
+
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]: ...
|
126
130
|
|
127
131
|
|
128
132
|
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
133
|
def clear(self):
|
138
134
|
"""清除当前对话历史,保留系统消息。
|
139
135
|
|
@@ -195,7 +191,9 @@ class Agent:
|
|
195
191
|
if isinstance(platform, str):
|
196
192
|
self.model = PlatformRegistry().create_platform(platform)
|
197
193
|
if self.model is None:
|
198
|
-
PrettyOutput.print(
|
194
|
+
PrettyOutput.print(
|
195
|
+
f"平台 {platform} 不存在,将使用普通模型", OutputType.WARNING
|
196
|
+
)
|
199
197
|
self.model = PlatformRegistry().get_normal_platform()
|
200
198
|
else:
|
201
199
|
self.model = platform
|
@@ -395,6 +393,8 @@ class Agent:
|
|
395
393
|
if self.addon_prompt:
|
396
394
|
message += f"\n\n{self.addon_prompt}"
|
397
395
|
self.addon_prompt = ""
|
396
|
+
else:
|
397
|
+
message += f"\n\n{self.make_default_addon_prompt(need_complete)}"
|
398
398
|
|
399
399
|
# 累加对话长度
|
400
400
|
self.conversation_length += get_context_token_count(message)
|
@@ -526,7 +526,9 @@ class Agent:
|
|
526
526
|
if not self.execute_tool_confirm or user_confirm(
|
527
527
|
f"需要执行{tool_list[0].name()}确认执行?", True
|
528
528
|
):
|
529
|
-
with yaspin(
|
529
|
+
with yaspin(
|
530
|
+
text=f"正在执行{tool_list[0].name()}...", color="cyan"
|
531
|
+
) as spinner:
|
530
532
|
with spinner.hidden():
|
531
533
|
result = tool_list[0].handle(response, self)
|
532
534
|
spinner.text = f"{tool_list[0].name()}执行完成"
|
@@ -724,6 +726,40 @@ arguments:
|
|
724
726
|
spinner.text = "分析失败"
|
725
727
|
spinner.fail("❌")
|
726
728
|
|
729
|
+
def make_default_addon_prompt(self, need_complete: bool) -> str:
|
730
|
+
"""生成附加提示。
|
731
|
+
|
732
|
+
参数:
|
733
|
+
need_complete: 是否需要完成任务
|
734
|
+
|
735
|
+
"""
|
736
|
+
# 结构化系统指令
|
737
|
+
action_handlers = ", ".join([handler.name() for handler in self.output_handler])
|
738
|
+
|
739
|
+
# 任务完成提示
|
740
|
+
complete_prompt = (
|
741
|
+
f"- 输出{ot('!!!COMPLETE!!!')}"
|
742
|
+
if need_complete and self.auto_complete
|
743
|
+
else ""
|
744
|
+
)
|
745
|
+
|
746
|
+
addon_prompt = f"""
|
747
|
+
<system_prompt>
|
748
|
+
请判断是否已经完成任务,如果已经完成:
|
749
|
+
- 直接输出完成原因,不需要再有新的操作,不要输出{ot("TOOL_CALL")}标签
|
750
|
+
{complete_prompt}
|
751
|
+
如果没有完成,请进行下一步操作:
|
752
|
+
- 仅包含一个操作
|
753
|
+
- 如果信息不明确,请请求用户补充
|
754
|
+
- 如果执行过程中连续失败5次,请使用ask_user询问用户操作
|
755
|
+
- 操作列表:{action_handlers}
|
756
|
+
</system_prompt>
|
757
|
+
|
758
|
+
请继续。
|
759
|
+
"""
|
760
|
+
|
761
|
+
return addon_prompt
|
762
|
+
|
727
763
|
def run(self, user_input: str) -> Any:
|
728
764
|
"""处理用户输入并执行任务
|
729
765
|
|
@@ -747,11 +783,7 @@ arguments:
|
|
747
783
|
while True:
|
748
784
|
if self.first:
|
749
785
|
# 如果有上传文件,先上传文件
|
750
|
-
if (
|
751
|
-
self.files
|
752
|
-
and self.model
|
753
|
-
and self.model.support_upload_files()
|
754
|
-
):
|
786
|
+
if self.files and self.model and self.model.support_upload_files():
|
755
787
|
self.model.upload_files(self.files)
|
756
788
|
|
757
789
|
# 如果启用方法论且没有上传文件,上传方法论
|
@@ -768,11 +800,6 @@ arguments:
|
|
768
800
|
current_response = self._call_model(self.prompt, True)
|
769
801
|
self.prompt = ""
|
770
802
|
|
771
|
-
need_return, self.prompt = self._call_tools(current_response)
|
772
|
-
|
773
|
-
if need_return:
|
774
|
-
return self.prompt
|
775
|
-
|
776
803
|
if get_interrupt():
|
777
804
|
set_interrupt(False)
|
778
805
|
user_input = self.multiline_inputer(
|
@@ -782,6 +809,11 @@ arguments:
|
|
782
809
|
self.prompt += f"{user_input}"
|
783
810
|
continue
|
784
811
|
|
812
|
+
need_return, self.prompt = self._call_tools(current_response)
|
813
|
+
|
814
|
+
if need_return:
|
815
|
+
return self.prompt
|
816
|
+
|
785
817
|
if self.after_tool_call_cb:
|
786
818
|
self.after_tool_call_cb(self)
|
787
819
|
|
@@ -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
@@ -8,9 +8,14 @@ import yaml
|
|
8
8
|
from prompt_toolkit import prompt
|
9
9
|
from yaspin import yaspin
|
10
10
|
|
11
|
-
from jarvis.jarvis_agent import (
|
12
|
-
|
13
|
-
|
11
|
+
from jarvis.jarvis_agent import (
|
12
|
+
Agent,
|
13
|
+
OutputType,
|
14
|
+
PrettyOutput,
|
15
|
+
get_multiline_input,
|
16
|
+
origin_agent_system_prompt,
|
17
|
+
user_confirm,
|
18
|
+
)
|
14
19
|
from jarvis.jarvis_agent.builtin_input_handler import builtin_input_handler
|
15
20
|
from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
|
16
21
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
@@ -29,7 +34,9 @@ def _load_tasks() -> Dict[str, str]:
|
|
29
34
|
spinner_text = f"从{pre_command_path}加载预定义任务..."
|
30
35
|
with yaspin(text=spinner_text, color="cyan") as spinner:
|
31
36
|
try:
|
32
|
-
with open(
|
37
|
+
with open(
|
38
|
+
pre_command_path, "r", encoding="utf-8", errors="ignore"
|
39
|
+
) as f:
|
33
40
|
user_tasks = yaml.safe_load(f)
|
34
41
|
if isinstance(user_tasks, dict):
|
35
42
|
for name, desc in user_tasks.items():
|
@@ -48,7 +55,9 @@ def _load_tasks() -> Dict[str, str]:
|
|
48
55
|
spinner_text = f"从{abs_path}加载预定义任务..."
|
49
56
|
with yaspin(text=spinner_text, color="cyan") as spinner:
|
50
57
|
try:
|
51
|
-
with open(
|
58
|
+
with open(
|
59
|
+
pre_command_path, "r", encoding="utf-8", errors="ignore"
|
60
|
+
) as f:
|
52
61
|
local_tasks = yaml.safe_load(f)
|
53
62
|
if isinstance(local_tasks, dict):
|
54
63
|
for name, desc in local_tasks.items():
|
@@ -62,11 +71,12 @@ def _load_tasks() -> Dict[str, str]:
|
|
62
71
|
|
63
72
|
return tasks
|
64
73
|
|
74
|
+
|
65
75
|
def _select_task(tasks: Dict[str, str]) -> str:
|
66
76
|
"""Let user select a task from the list or skip. Returns task description if selected."""
|
67
77
|
if not tasks:
|
68
78
|
return ""
|
69
|
-
|
79
|
+
|
70
80
|
task_names = list(tasks.keys())
|
71
81
|
task_list = ["可用任务:"]
|
72
82
|
for i, name in enumerate(task_names, 1):
|
@@ -74,7 +84,6 @@ def _select_task(tasks: Dict[str, str]) -> str:
|
|
74
84
|
task_list.append("[0] 跳过预定义任务")
|
75
85
|
PrettyOutput.print("\n".join(task_list), OutputType.INFO)
|
76
86
|
|
77
|
-
|
78
87
|
while True:
|
79
88
|
try:
|
80
89
|
choice_str = prompt("\n请选择一个任务编号(0 跳过预定义任务):").strip()
|
@@ -88,13 +97,19 @@ def _select_task(tasks: Dict[str, str]) -> str:
|
|
88
97
|
selected_task = tasks[task_names[choice - 1]]
|
89
98
|
PrettyOutput.print(f"将要执行任务:\n {selected_task}", OutputType.INFO)
|
90
99
|
# 询问是否需要补充信息
|
91
|
-
need_additional = user_confirm(
|
100
|
+
need_additional = user_confirm(
|
101
|
+
"需要为此任务添加补充信息吗?", default=False
|
102
|
+
)
|
92
103
|
if need_additional:
|
93
104
|
additional_input = get_multiline_input("请输入补充信息:")
|
94
105
|
if additional_input:
|
95
|
-
selected_task =
|
106
|
+
selected_task = (
|
107
|
+
f"{selected_task}\n\n补充信息:\n{additional_input}"
|
108
|
+
)
|
96
109
|
return selected_task
|
97
|
-
PrettyOutput.print(
|
110
|
+
PrettyOutput.print(
|
111
|
+
"无效的选择。请选择列表中的一个号码。", OutputType.WARNING
|
112
|
+
)
|
98
113
|
|
99
114
|
except (KeyboardInterrupt, EOFError):
|
100
115
|
return ""
|
@@ -104,26 +119,26 @@ def _select_task(tasks: Dict[str, str]) -> str:
|
|
104
119
|
|
105
120
|
def main() -> None:
|
106
121
|
|
107
|
-
|
108
|
-
parser =
|
109
|
-
parser.add_argument(
|
110
|
-
parser.add_argument(
|
111
|
-
|
112
|
-
|
122
|
+
parser = argparse.ArgumentParser(description="Jarvis AI assistant")
|
123
|
+
parser.add_argument("-p", "--platform", type=str, help="Platform to use")
|
124
|
+
parser.add_argument("-m", "--model", type=str, help="Model to use")
|
125
|
+
parser.add_argument(
|
126
|
+
"-t", "--task", type=str, help="Directly input task content from command line"
|
127
|
+
)
|
128
|
+
parser.add_argument("-f", "--config", type=str, help="Path to custom config file")
|
113
129
|
args = parser.parse_args()
|
114
|
-
init_env(
|
130
|
+
init_env(
|
131
|
+
"欢迎使用 Jarvis AI 助手,您的智能助理已准备就绪!", config_file=args.config
|
132
|
+
)
|
115
133
|
|
116
134
|
try:
|
117
135
|
agent = Agent(
|
118
136
|
system_prompt=origin_agent_system_prompt,
|
119
137
|
platform=args.platform,
|
120
138
|
model_name=args.model,
|
121
|
-
input_handler=[
|
122
|
-
shell_input_handler,
|
123
|
-
builtin_input_handler
|
124
|
-
],
|
139
|
+
input_handler=[shell_input_handler, builtin_input_handler],
|
125
140
|
output_handler=[ToolRegistry()],
|
126
|
-
need_summary=False
|
141
|
+
need_summary=False,
|
127
142
|
)
|
128
143
|
|
129
144
|
# 优先处理命令行直接传入的任务
|
@@ -146,5 +161,6 @@ def main() -> None:
|
|
146
161
|
PrettyOutput.print(f"初始化错误: {str(err)}", OutputType.ERROR)
|
147
162
|
sys.exit(1)
|
148
163
|
|
164
|
+
|
149
165
|
if __name__ == "__main__":
|
150
166
|
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
|
-
|