jarvis-ai-assistant 0.2.0__py3-none-any.whl → 0.2.1__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.2.0"
4
+ __version__ = "0.2.1"
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import re
3
- from typing import Any, Dict, List, Optional, Tuple
3
+ from typing import Any, Dict, List, Optional, Tuple, Union
4
4
 
5
5
  import yaml
6
6
 
@@ -89,6 +89,8 @@ content: |2
89
89
  Args:
90
90
  content: The content containing send message
91
91
  """
92
+ if ot("SEND_MESSAGE") in content and ct("SEND_MESSAGE") not in content:
93
+ content += "\n" + ct("SEND_MESSAGE")
92
94
  data = re.findall(
93
95
  ot("SEND_MESSAGE") + r"\n(.*?)\n" + ct("SEND_MESSAGE"), content, re.DOTALL
94
96
  )
@@ -102,7 +104,7 @@ content: |2
102
104
  continue
103
105
  return ret
104
106
 
105
- def _get_agent(self, name: str) -> Agent | None:
107
+ def _get_agent(self, name: str) -> Union[Agent, None]:
106
108
  if name in self.agents:
107
109
  return self.agents[name]
108
110
 
@@ -113,9 +115,9 @@ content: |2
113
115
 
114
116
  if name != self.main_agent_name and self.original_question:
115
117
  system_prompt = config.get("system_prompt", "")
116
- config["system_prompt"] = (
117
- f"{system_prompt}\n\n# 原始问题\n{self.original_question}"
118
- )
118
+ config[
119
+ "system_prompt"
120
+ ] = f"{system_prompt}\n\n# 原始问题\n{self.original_question}"
119
121
 
120
122
  output_handler = config.get("output_handler", [])
121
123
  if len(output_handler) == 0:
@@ -15,6 +15,7 @@ from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
15
15
  from jarvis.jarvis_mcp.streamable_mcp_client import StreamableMcpClient
16
16
  from jarvis.jarvis_tools.base import Tool
17
17
  from jarvis.jarvis_utils.config import get_data_dir, get_tool_load_dirs
18
+ from jarvis.jarvis_utils.input import user_confirm
18
19
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
19
20
  from jarvis.jarvis_utils.tag import ct, ot
20
21
  from jarvis.jarvis_utils.utils import is_context_overflow, daily_check_git_updates
@@ -106,14 +107,20 @@ arguments:
106
107
 
107
108
 
108
109
  class OutputHandlerProtocol(Protocol):
109
- def name(self) -> str: ...
110
- def can_handle(self, response: str) -> bool: ...
111
- def prompt(self) -> str: ...
112
- def handle(self, response: str, agent: Any) -> Tuple[bool, Any]: ...
110
+ def name(self) -> str:
111
+ ...
113
112
 
113
+ def can_handle(self, response: str) -> bool:
114
+ ...
114
115
 
115
- class ToolRegistry(OutputHandlerProtocol):
116
+ def prompt(self) -> str:
117
+ ...
116
118
 
119
+ def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
120
+ ...
121
+
122
+
123
+ class ToolRegistry(OutputHandlerProtocol):
117
124
  def name(self) -> str:
118
125
  return "TOOL_CALL"
119
126
 
@@ -124,14 +131,16 @@ class ToolRegistry(OutputHandlerProtocol):
124
131
  """加载工具"""
125
132
  tools = self.get_all_tools()
126
133
  if tools:
127
- tools_prompt = f"{tool_call_help}\n<tools_section>\n"
134
+ tools_prompt = f"<tools_section>\n"
128
135
  tools_prompt += " <header>## 可用工具:</header>\n"
129
136
  tools_prompt += " <tools_list>\n"
130
137
  for tool in tools:
131
138
  try:
132
139
  tools_prompt += " <tool>\n"
133
140
  tools_prompt += f" <name>名称: {tool['name']}</name>\n"
134
- tools_prompt += f" <description>描述: {tool['description']}</description>\n"
141
+ tools_prompt += (
142
+ f" <description>描述: {tool['description']}</description>\n"
143
+ )
135
144
  tools_prompt += " <parameters>\n"
136
145
  tools_prompt += " <yaml>|\n"
137
146
 
@@ -197,9 +206,7 @@ class ToolRegistry(OutputHandlerProtocol):
197
206
  with open(stats_file, "r", encoding="utf-8") as f:
198
207
  return yaml.safe_load(f) or {}
199
208
  except Exception as e:
200
- PrettyOutput.print(
201
- f"加载工具调用统计失败: {str(e)}", OutputType.WARNING
202
- )
209
+ PrettyOutput.print(f"加载工具调用统计失败: {str(e)}", OutputType.WARNING)
203
210
  return {}
204
211
 
205
212
  def _update_tool_stats(self, name: str) -> None:
@@ -269,9 +276,7 @@ class ToolRegistry(OutputHandlerProtocol):
269
276
  config = yaml.safe_load(open(file_path, "r", encoding="utf-8"))
270
277
  self.register_mcp_tool_by_config(config)
271
278
  except Exception as e:
272
- PrettyOutput.print(
273
- f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING
274
- )
279
+ PrettyOutput.print(f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING)
275
280
 
276
281
  def _load_builtin_tools(self) -> None:
277
282
  """从内置工具目录加载工具"""
@@ -508,7 +513,6 @@ class ToolRegistry(OutputHandlerProtocol):
508
513
  and hasattr(item, "execute")
509
514
  and item.name == module_name
510
515
  ):
511
-
512
516
  if hasattr(item, "check"):
513
517
  if not item.check():
514
518
  continue
@@ -567,10 +571,46 @@ class ToolRegistry(OutputHandlerProtocol):
567
571
  ot("TOOL_CALL") + r"(.*?)" + ct("TOOL_CALL"), content, re.DOTALL
568
572
  )
569
573
  if not data:
570
- return (
571
- {},
572
- f"只有{ot('TOOL_CALL')}标签,未找到{ct('TOOL_CALL')}标签,调用格式错误,请检查工具调用格式。\n{tool_call_help}",
573
- )
574
+ # can_handle 确保 ot("TOOL_CALL") 在内容中。
575
+ # 如果数据为空,则表示 ct("TOOL_CALL") 可能丢失。
576
+ if ot("TOOL_CALL") in content and ct("TOOL_CALL") not in content:
577
+ # 尝试通过附加结束标签来修复它
578
+ fixed_content = content.strip() + f"\n{ct('TOOL_CALL')}"
579
+
580
+ # 再次提取,并检查YAML是否有效
581
+ temp_data = re.findall(
582
+ ot("TOOL_CALL") + r"(.*?)" + ct("TOOL_CALL"),
583
+ fixed_content,
584
+ re.DOTALL,
585
+ )
586
+
587
+ if temp_data:
588
+ try:
589
+ yaml.safe_load(temp_data[0]) # Check if valid YAML
590
+
591
+ # Ask user for confirmation
592
+ PrettyOutput.print(
593
+ f"检测到缺失的 {ct('TOOL_CALL')} 标签,已自动修复。修复后的内容如下:",
594
+ OutputType.INFO,
595
+ )
596
+ PrettyOutput.print(fixed_content, OutputType.TOOL)
597
+ if user_confirm("这是纠正后的,是否需要执行?", default=True):
598
+ data = temp_data
599
+ else:
600
+ return (
601
+ {},
602
+ f"只有{ot('TOOL_CALL')}标签,未找到{ct('TOOL_CALL')}标签,调用格式错误,请检查工具调用格式。\n{tool_call_help}",
603
+ )
604
+ except (yaml.YAMLError, EOFError, KeyboardInterrupt):
605
+ # Even after fixing, it's not valid YAML, or user cancelled.
606
+ # Fall through to the original error.
607
+ pass
608
+
609
+ if not data:
610
+ return (
611
+ {},
612
+ f"只有{ot('TOOL_CALL')}标签,未找到{ct('TOOL_CALL')}标签,调用格式错误,请检查工具调用格式。\n{tool_call_help}",
613
+ )
574
614
  ret = []
575
615
  for item in data:
576
616
  try:
@@ -685,9 +725,7 @@ class ToolRegistry(OutputHandlerProtocol):
685
725
  """
686
726
  if len(output.splitlines()) > 60:
687
727
  lines = output.splitlines()
688
- return "\n".join(
689
- lines[:30] + ["\n...内容太长,已截取前后30行...\n"] + lines[-30:]
690
- )
728
+ return "\n".join(lines[:30] + ["\n...内容太长,已截取前后30行...\n"] + lines[-30:])
691
729
  return output
692
730
 
693
731
  def handle_tool_calls(self, tool_call: Dict[str, Any], agent: Any) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -104,13 +104,25 @@ Dynamic: requires-python
104
104
  - Windows没有测试过,但Windows 10以上的用户可以在WSL上使用此工具
105
105
 
106
106
  ### 安装
107
+
108
+ #### 一键安装 (推荐)
109
+ 只需一行命令即可完成所有安装和配置:
110
+ ```bash
111
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/skyfireitdiy/Jarvis/main/scripts/install.sh)"
112
+ ```
113
+ > 该脚本会自动检测Python环境、克隆项目、安装依赖并设置好路径。
114
+
115
+ #### 手动安装
116
+
117
+ **1. 从源码安装**
107
118
  ```bash
108
- # 从源码安装(推荐)
109
119
  git clone https://github.com/skyfireitdiy/Jarvis
110
120
  cd Jarvis
111
121
  pip3 install -e .
122
+ ```
112
123
 
113
- # 或者从PyPI安装(可能更新不及时)
124
+ **2. PyPI安装 (可能不是最新版)**
125
+ ```bash
114
126
  pip3 install jarvis-ai-assistant
115
127
  ```
116
128
 
@@ -1,4 +1,4 @@
1
- jarvis/__init__.py,sha256=EmFCOffXrFq1m3oGpL5fp5ciwQF4OV_6X1esvw2Ukdg,73
1
+ jarvis/__init__.py,sha256=7YS_CmhWeXPE4rP8NAcZnRuHXCr7rFpRpDd4pK4v2GQ,73
2
2
  jarvis/jarvis_agent/__init__.py,sha256=BmBbMUsCwe_0znrwxSipaKj-MuOgJTZvLbyKzBFfpic,22559
3
3
  jarvis/jarvis_agent/builtin_input_handler.py,sha256=Qs4LAr4xdKLBJpQE81YP4CkucAop86ms0iVoKa1nnso,2468
4
4
  jarvis/jarvis_agent/edit_file_handler.py,sha256=ml1o-BE2Ca1-ybPlKuhstLQYwdJag39o0_-PXTUvFaE,11646
@@ -47,7 +47,7 @@ jarvis/jarvis_mcp/sse_mcp_client.py,sha256=AhYLPQb0mE9-6ZQw1JesRNyEy0esJumNEFb5L
47
47
  jarvis/jarvis_mcp/stdio_mcp_client.py,sha256=APYUksYKlMx7AVNODKOLrTkKZPnp4kqTQIYIuNDDKko,11286
48
48
  jarvis/jarvis_mcp/streamable_mcp_client.py,sha256=1OZpsG82U2MLbGuojllJAblFUAMmp1N0i5fsKM4n5Ts,14453
49
49
  jarvis/jarvis_methodology/main.py,sha256=-PqsWvtpUJkkhiGgV-1JegEnEZBmv8SHnNMNNm_-QQc,11720
50
- jarvis/jarvis_multi_agent/__init__.py,sha256=efB04nWPRl4EOD64RThqQ6w78GZc2t0GGisX2wwTP8I,5949
50
+ jarvis/jarvis_multi_agent/__init__.py,sha256=kCgtAX7VvliyEOQxIj2DvNjRAuh6bpNaOtDn60nzph4,6089
51
51
  jarvis/jarvis_multi_agent/main.py,sha256=h7VUSwoPrES0XTK8z5kt3XLX1mmcm8UEuFEHQOUWPH4,1696
52
52
  jarvis/jarvis_platform/__init__.py,sha256=WLQHSiE87PPket2M50_hHzjdMIgPIBx2VF8JfB_NNRk,105
53
53
  jarvis/jarvis_platform/ai8.py,sha256=yi7xG8ld4Yrf7drz-uu_JT_XCGYRB0obhygt-jKik8o,10871
@@ -83,7 +83,7 @@ jarvis/jarvis_tools/generate_new_tool.py,sha256=ppMRuTYUZ0c02rHo7xi8DCGiDVPZTANV
83
83
  jarvis/jarvis_tools/methodology.py,sha256=_K4GIDUodGEma3SvNRo7Qs5rliijgNespVLyAPN35JU,5233
84
84
  jarvis/jarvis_tools/read_code.py,sha256=EnI-R-5HyIQYhMD391nZWXHIuHHBF-OJIRE0QpLcPX4,6417
85
85
  jarvis/jarvis_tools/read_webpage.py,sha256=NmDUboVZd4CGHBPRFK6dp3uqVhuGopW1bOi3TcaLDF4,2092
86
- jarvis/jarvis_tools/registry.py,sha256=3SMzVM9rhI9Gl8EdI13_NOHBxwygueqw-nUcCi6AgRM,26754
86
+ jarvis/jarvis_tools/registry.py,sha256=FO72qNhDXeBRMnLc9IR87X0SNqAkGkzbHYtbw-7OMgI,28604
87
87
  jarvis/jarvis_tools/rewrite_file.py,sha256=eG_WKg6cVAXmuGwUqlWkcuyay5S8DOzEi8vZCmX3O8w,7255
88
88
  jarvis/jarvis_tools/search_web.py,sha256=DDAPjYWTFaF85zsnhJ6VNDSc1BcY8EHus5ymKP9nnPs,5703
89
89
  jarvis/jarvis_tools/virtual_tty.py,sha256=KKr3jpvQWWMPr2o40hlmN6fuXJCN8H4_ma5QU40Citc,16089
@@ -102,9 +102,9 @@ jarvis/jarvis_utils/methodology.py,sha256=V2Y0mbamrWBhhCK-3foAM1hKewOEcIDcXO-Sv_
102
102
  jarvis/jarvis_utils/output.py,sha256=2QMpzb8ZOysQ6HHsRjRzjgUnNXaFGkIiZ_qElPKLbsA,10858
103
103
  jarvis/jarvis_utils/tag.py,sha256=f211opbbbTcSyzCDwuIK_oCnKhXPNK-RknYyGzY1yD0,431
104
104
  jarvis/jarvis_utils/utils.py,sha256=G6UuiBrPlWLpau1LbSGStrlAHCHG8JufINLD_bwtjTE,20006
105
- jarvis_ai_assistant-0.2.0.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
106
- jarvis_ai_assistant-0.2.0.dist-info/METADATA,sha256=ddh41XdsU955MHnmlVF1YhXW5D2oYZK-M7ZsTUqVMAs,25713
107
- jarvis_ai_assistant-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
108
- jarvis_ai_assistant-0.2.0.dist-info/entry_points.txt,sha256=JXK_n-d9HZ_RLz959CvpK5-UPOCwssn5oAH8dAHuebA,1277
109
- jarvis_ai_assistant-0.2.0.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
110
- jarvis_ai_assistant-0.2.0.dist-info/RECORD,,
105
+ jarvis_ai_assistant-0.2.1.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
106
+ jarvis_ai_assistant-0.2.1.dist-info/METADATA,sha256=2CaCKJhb4POadlWKBvaXRe1Lf1YVPNI1jCGXbbkQuDo,26021
107
+ jarvis_ai_assistant-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
108
+ jarvis_ai_assistant-0.2.1.dist-info/entry_points.txt,sha256=JXK_n-d9HZ_RLz959CvpK5-UPOCwssn5oAH8dAHuebA,1277
109
+ jarvis_ai_assistant-0.2.1.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
110
+ jarvis_ai_assistant-0.2.1.dist-info/RECORD,,