jarvis-ai-assistant 0.1.151__tar.gz → 0.1.152__tar.gz

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.

Potentially problematic release.


This version of jarvis-ai-assistant might be problematic. Click here for more details.

Files changed (101) hide show
  1. {jarvis_ai_assistant-0.1.151/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.152}/PKG-INFO +1 -1
  2. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/pyproject.toml +1 -1
  3. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/setup.py +1 -1
  4. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/__init__.py +1 -1
  5. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/__init__.py +6 -2
  6. jarvis_ai_assistant-0.1.151/src/jarvis/jarvis_mcp/remote_mcp_client.py → jarvis_ai_assistant-0.1.152/src/jarvis/jarvis_mcp/sse_mcp_client.py +1 -1
  7. jarvis_ai_assistant-0.1.151/src/jarvis/jarvis_mcp/local_mcp_client.py → jarvis_ai_assistant-0.1.152/src/jarvis/jarvis_mcp/stdio_mcp_client.py +1 -1
  8. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/registry.py +175 -112
  9. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/methodology.py +1 -1
  10. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
  11. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +2 -2
  12. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/LICENSE +0 -0
  13. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/MANIFEST.in +0 -0
  14. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/README.md +0 -0
  15. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/setup.cfg +0 -0
  16. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/builtin_input_handler.py +0 -0
  17. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/file_input_handler.py +0 -0
  18. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/jarvis.py +0 -0
  19. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/main.py +0 -0
  20. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/output_handler.py +0 -0
  21. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/patch.py +0 -0
  22. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_agent/shell_input_handler.py +0 -0
  23. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
  24. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_agent/code_agent.py +0 -0
  25. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/__init__.py +0 -0
  26. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/c_cpp.py +0 -0
  27. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/csharp.py +0 -0
  28. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/data_format.py +0 -0
  29. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/devops.py +0 -0
  30. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/docs.py +0 -0
  31. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/go.py +0 -0
  32. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/infrastructure.py +0 -0
  33. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/java.py +0 -0
  34. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/javascript.py +0 -0
  35. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/kotlin.py +0 -0
  36. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/loader.py +0 -0
  37. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/php.py +0 -0
  38. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/python.py +0 -0
  39. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/ruby.py +0 -0
  40. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/rust.py +0 -0
  41. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/shell.py +0 -0
  42. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/sql.py +0 -0
  43. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/swift.py +0 -0
  44. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/checklists/web.py +0 -0
  45. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_code_analysis/code_review.py +0 -0
  46. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_dev/main.py +0 -0
  47. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_git_details/__init__.py +0 -0
  48. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_git_details/main.py +0 -0
  49. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_git_squash/__init__.py +0 -0
  50. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_git_squash/main.py +0 -0
  51. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_git_utils/git_commiter.py +0 -0
  52. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_lsp/base.py +0 -0
  53. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_lsp/cpp.py +0 -0
  54. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_lsp/go.py +0 -0
  55. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_lsp/python.py +0 -0
  56. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_lsp/registry.py +0 -0
  57. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_lsp/rust.py +0 -0
  58. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_mcp/__init__.py +0 -0
  59. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_methodology/main.py +0 -0
  60. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_multi_agent/__init__.py +0 -0
  61. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_multi_agent/main.py +0 -0
  62. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_platform/__init__.py +0 -0
  63. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_platform/base.py +0 -0
  64. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_platform/kimi.py +0 -0
  65. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_platform/registry.py +0 -0
  66. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_platform/yuanbao.py +0 -0
  67. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
  68. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_platform_manager/main.py +0 -0
  69. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  70. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_smart_shell/main.py +0 -0
  71. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/__init__.py +0 -0
  72. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/ask_codebase.py +0 -0
  73. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/ask_user.py +0 -0
  74. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/base.py +0 -0
  75. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/chdir.py +0 -0
  76. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/code_plan.py +0 -0
  77. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/create_code_agent.py +0 -0
  78. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/create_sub_agent.py +0 -0
  79. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/execute_script.py +0 -0
  80. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/file_analyzer.py +0 -0
  81. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/file_operation.py +0 -0
  82. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/find_methodology.py +0 -0
  83. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -0
  84. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/methodology.py +0 -0
  85. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/read_code.py +0 -0
  86. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
  87. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/search_web.py +0 -0
  88. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_tools/virtual_tty.py +0 -0
  89. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/__init__.py +0 -0
  90. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/config.py +0 -0
  91. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/embedding.py +0 -0
  92. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/file_processors.py +0 -0
  93. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/git_utils.py +0 -0
  94. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/globals.py +0 -0
  95. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/input.py +0 -0
  96. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/output.py +0 -0
  97. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis/jarvis_utils/utils.py +0 -0
  98. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  99. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis_ai_assistant.egg-info/entry_points.txt +0 -0
  100. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  101. {jarvis_ai_assistant-0.1.151 → jarvis_ai_assistant-0.1.152}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.151
3
+ Version: 0.1.152
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
@@ -8,7 +8,7 @@ default = true
8
8
 
9
9
  [project]
10
10
  name = "jarvis-ai-assistant"
11
- version = "0.1.151"
11
+ version = "0.1.152"
12
12
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
13
13
  readme = "README.md"
14
14
  authors = [{ name = "skyfire", email = "skyfireitdiy@hotmail.com" }]
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="jarvis-ai-assistant",
5
- version="0.1.151",
5
+ version="0.1.152",
6
6
  author="skyfire",
7
7
  author_email="skyfireitdiy@hotmail.com",
8
8
  description="An AI assistant that uses various tools to interact with the system",
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.151"
3
+ __version__ = "0.1.152"
@@ -5,6 +5,7 @@ from typing import Any, Callable, List, Optional, Tuple, Union
5
5
  from yaspin import yaspin
6
6
 
7
7
  from jarvis.jarvis_agent.output_handler import OutputHandler
8
+ from jarvis.jarvis_agent.patch import PatchOutputHandler
8
9
  from jarvis.jarvis_platform.base import BasePlatform
9
10
  from jarvis.jarvis_platform.registry import PlatformRegistry
10
11
  from jarvis.jarvis_utils.output import PrettyOutput, OutputType
@@ -193,7 +194,7 @@ class Agent:
193
194
  self.model.set_suppress_output(False)
194
195
 
195
196
  from jarvis.jarvis_tools.registry import ToolRegistry
196
- self.output_handler = output_handler if output_handler else [ToolRegistry()]
197
+ self.output_handler = output_handler if output_handler else [ToolRegistry(), PatchOutputHandler()]
197
198
  self.multiline_inputer = multiline_inputer if multiline_inputer else get_multiline_input
198
199
 
199
200
  self.prompt = ""
@@ -591,7 +592,10 @@ arguments:
591
592
  self.prompt = f"{user_input}"
592
593
 
593
594
  if self.first:
594
- self.prompt = f"{user_input}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(user_input)}"
595
+ msg = user_input
596
+ for handler in self.input_handler:
597
+ msg, _ = handler(msg, self)
598
+ self.prompt = f"{user_input}\n\n以下是历史类似问题的执行经验,可参考:\n{load_methodology(msg)}"
595
599
  self.first = False
596
600
 
597
601
  while True:
@@ -9,7 +9,7 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
9
  from . import McpClient
10
10
 
11
11
 
12
- class RemoteMcpClient(McpClient):
12
+ class SSEMcpClient(McpClient):
13
13
  """远程MCP客户端实现
14
14
 
15
15
  参数:
@@ -6,7 +6,7 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
6
6
  from . import McpClient
7
7
 
8
8
 
9
- class LocalMcpClient(McpClient):
9
+ class StdioMcpClient(McpClient):
10
10
  """本地MCP客户端实现
11
11
 
12
12
  参数:
@@ -10,16 +10,19 @@ import yaml
10
10
  from jarvis.jarvis_agent.output_handler import OutputHandler
11
11
  from jarvis.jarvis_platform.registry import PlatformRegistry
12
12
  from jarvis.jarvis_tools.base import Tool
13
- from jarvis.jarvis_utils.config import INPUT_WINDOW_REVERSE_SIZE, get_max_input_token_count, get_data_dir
13
+ from jarvis.jarvis_utils.config import (
14
+ INPUT_WINDOW_REVERSE_SIZE,
15
+ get_max_input_token_count,
16
+ get_data_dir,
17
+ )
14
18
  from jarvis.jarvis_utils.embedding import get_context_token_count
15
19
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
16
20
  from jarvis.jarvis_utils.utils import ct, ot, init_env
17
- from jarvis.jarvis_mcp.local_mcp_client import LocalMcpClient
18
- from jarvis.jarvis_mcp.remote_mcp_client import RemoteMcpClient
21
+ from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
22
+ from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
19
23
  from jarvis.jarvis_mcp import McpClient
20
24
 
21
25
 
22
-
23
26
  tool_call_help = f"""
24
27
  # 🛠️ 工具使用系统
25
28
  您正在使用一个需要精确格式和严格规则的工具执行系统。
@@ -82,6 +85,7 @@ arguments:
82
85
  - 在没有所需信息的情况下继续
83
86
  """
84
87
 
88
+
85
89
  class ToolRegistry(OutputHandler):
86
90
 
87
91
  def name(self) -> str:
@@ -103,19 +107,22 @@ class ToolRegistry(OutputHandler):
103
107
 
104
108
  # 生成格式化的YAML参数
105
109
  yaml_params = yaml.dump(
106
- tool['parameters'],
110
+ tool["parameters"],
107
111
  allow_unicode=True,
108
112
  indent=4,
109
113
  sort_keys=False,
110
- width=120 # 增加行宽限制
114
+ width=120, # 增加行宽限制
111
115
  )
112
116
 
113
117
  # 添加缩进并移除尾部空格
114
- for line in yaml_params.split('\n'):
118
+ for line in yaml_params.split("\n"):
115
119
  tools_prompt += f" {line.rstrip()}\n"
116
120
 
117
121
  except yaml.YAMLError as e:
118
- PrettyOutput.print(f"工具 {tool['name']} 参数序列化失败: {str(e)}", OutputType.ERROR)
122
+ PrettyOutput.print(
123
+ f"工具 {tool['name']} 参数序列化失败: {str(e)}",
124
+ OutputType.ERROR,
125
+ )
119
126
  continue
120
127
 
121
128
  tools_prompt += tool_call_help.rstrip() # 移除帮助文本尾部空格
@@ -135,7 +142,9 @@ class ToolRegistry(OutputHandler):
135
142
  self._load_builtin_tools()
136
143
  self._load_external_tools()
137
144
  self._load_mcp_tools()
138
- self.max_input_token_count = get_max_input_token_count() - INPUT_WINDOW_REVERSE_SIZE
145
+ self.max_input_token_count = (
146
+ get_max_input_token_count() - INPUT_WINDOW_REVERSE_SIZE
147
+ )
139
148
 
140
149
  def use_tools(self, name: List[str]) -> None:
141
150
  """使用指定工具
@@ -145,7 +154,10 @@ class ToolRegistry(OutputHandler):
145
154
  """
146
155
  missing_tools = [tool_name for tool_name in name if tool_name not in self.tools]
147
156
  if missing_tools:
148
- PrettyOutput.print(f"工具 {missing_tools} 不存在,可用的工具有: {', '.join(self.tools.keys())}", OutputType.WARNING)
157
+ PrettyOutput.print(
158
+ f"工具 {missing_tools} 不存在,可用的工具有: {', '.join(self.tools.keys())}",
159
+ OutputType.WARNING,
160
+ )
149
161
  self.tools = {tool_name: self.tools[tool_name] for tool_name in name}
150
162
 
151
163
  def dont_use_tools(self, names: List[str]) -> None:
@@ -154,11 +166,13 @@ class ToolRegistry(OutputHandler):
154
166
  参数:
155
167
  names: 要移除的工具名称列表
156
168
  """
157
- self.tools = {name: tool for name, tool in self.tools.items() if name not in names}
169
+ self.tools = {
170
+ name: tool for name, tool in self.tools.items() if name not in names
171
+ }
158
172
 
159
173
  def _load_mcp_tools(self) -> None:
160
174
  """从jarvis_data/tools/mcp加载工具"""
161
- mcp_tools_dir = Path(get_data_dir()) / 'mcp'
175
+ mcp_tools_dir = Path(get_data_dir()) / "mcp"
162
176
  if not mcp_tools_dir.exists():
163
177
  return
164
178
 
@@ -180,7 +194,7 @@ class ToolRegistry(OutputHandler):
180
194
 
181
195
  def _load_external_tools(self) -> None:
182
196
  """从jarvis_data/tools加载外部工具"""
183
- external_tools_dir = Path(get_data_dir()) / 'tools'
197
+ external_tools_dir = Path(get_data_dir()) / "tools"
184
198
  if not external_tools_dir.exists():
185
199
  return
186
200
 
@@ -202,79 +216,102 @@ class ToolRegistry(OutputHandler):
202
216
  bool: 工具是否加载成功
203
217
  """
204
218
  try:
205
- config = yaml.safe_load(open(file_path, 'r', encoding='utf-8'))
206
- if 'type' not in config:
219
+ config = yaml.safe_load(open(file_path, "r", encoding="utf-8"))
220
+ if "type" not in config:
207
221
  PrettyOutput.print(f"文件 {file_path} 缺少type字段", OutputType.WARNING)
208
222
  return False
209
223
 
210
224
  # 检查enable标志
211
- if not config.get('enable', True):
212
- PrettyOutput.print(f"文件 {file_path} 已禁用(enable=false),跳过注册", OutputType.INFO)
225
+ if not config.get("enable", True):
226
+ PrettyOutput.print(
227
+ f"文件 {file_path} 已禁用(enable=false),跳过注册", OutputType.INFO
228
+ )
213
229
  return False
214
230
 
215
- name = config.get('name', Path(file_path).stem)
216
-
231
+ name = config.get("name", Path(file_path).stem)
217
232
 
218
233
  # 注册资源工具
219
234
  def create_resource_list_func(client: McpClient):
220
235
  def execute(arguments: Dict[str, Any]) -> Dict[str, Any]:
221
236
  args = arguments.copy()
222
- args.pop('agent', None)
223
- args.pop('want', None)
237
+ args.pop("agent", None)
238
+ args.pop("want", None)
224
239
  ret = client.get_resource_list()
225
- PrettyOutput.print(f"MCP {name} 资源列表:\n{yaml.safe_dump(ret)}", OutputType.TOOL)
240
+ PrettyOutput.print(
241
+ f"MCP {name} 资源列表:\n{yaml.safe_dump(ret)}", OutputType.TOOL
242
+ )
226
243
  return {
227
- 'success': True,
228
- 'stdout': yaml.safe_dump(ret),
229
- 'stderr': ''
244
+ "success": True,
245
+ "stdout": yaml.safe_dump(ret),
246
+ "stderr": "",
230
247
  }
248
+
231
249
  return execute
232
250
 
233
251
  def create_resource_get_func(client: McpClient):
234
252
  def execute(arguments: Dict[str, Any]) -> Dict[str, Any]:
235
253
  args = arguments.copy()
236
- args.pop('agent', None)
237
- args.pop('want', None)
238
- if 'uri' not in args:
254
+ args.pop("agent", None)
255
+ args.pop("want", None)
256
+ if "uri" not in args:
239
257
  return {
240
- 'success': False,
241
- 'stdout': '',
242
- 'stderr': '缺少必需的uri参数'
258
+ "success": False,
259
+ "stdout": "",
260
+ "stderr": "缺少必需的uri参数",
243
261
  }
244
- ret = client.get_resource(args['uri'])
245
- PrettyOutput.print(f"MCP {name} 获取资源:\n{yaml.safe_dump(ret)}", OutputType.TOOL)
262
+ ret = client.get_resource(args["uri"])
263
+ PrettyOutput.print(
264
+ f"MCP {name} 获取资源:\n{yaml.safe_dump(ret)}", OutputType.TOOL
265
+ )
246
266
  return ret
267
+
247
268
  return execute
248
269
 
249
270
  def create_mcp_execute_func(tool_name: str, client: McpClient):
250
271
  def execute(arguments: Dict[str, Any]) -> Dict[str, Any]:
251
272
  args = arguments.copy()
252
- args.pop('agent', None)
253
- args.pop('want', None)
273
+ args.pop("agent", None)
274
+ args.pop("want", None)
254
275
  ret = client.execute(tool_name, args)
255
- PrettyOutput.print(f"MCP {name} {tool_name} 执行结果:\n{yaml.safe_dump(ret)}", OutputType.TOOL)
276
+ PrettyOutput.print(
277
+ f"MCP {name} {tool_name} 执行结果:\n{yaml.safe_dump(ret)}",
278
+ OutputType.TOOL,
279
+ )
256
280
  return ret
281
+
257
282
  return execute
258
283
 
259
- if config['type'] == 'local':
260
- if 'command' not in config:
261
- PrettyOutput.print(f"文件 {file_path} 缺少command字段", OutputType.WARNING)
284
+ if config["type"] == "stdio":
285
+ if "command" not in config:
286
+ PrettyOutput.print(
287
+ f"文件 {file_path} 缺少command字段", OutputType.WARNING
288
+ )
262
289
  return False
263
- elif config['type'] == 'remote':
264
- if 'base_url' not in config:
265
- PrettyOutput.print(f"文件 {file_path} 缺少base_url字段", OutputType.WARNING)
290
+ elif config["type"] == "sse":
291
+ if "base_url" not in config:
292
+ PrettyOutput.print(
293
+ f"文件 {file_path} 缺少base_url字段", OutputType.WARNING
294
+ )
266
295
  return False
267
296
  else:
268
- PrettyOutput.print(f"文件 {file_path} 类型错误: {config['type']}", OutputType.WARNING)
297
+ PrettyOutput.print(
298
+ f"文件 {file_path} 类型错误: {config['type']}", OutputType.WARNING
299
+ )
269
300
  return False
270
301
 
271
302
  # 创建MCP客户端
272
- mcp_client: McpClient = LocalMcpClient(config) if config['type'] == 'local' else RemoteMcpClient(config)
303
+ mcp_client: McpClient = (
304
+ StdioMcpClient(config)
305
+ if config["type"] == "stdio"
306
+ else SSEMcpClient(config)
307
+ )
273
308
 
274
309
  # 获取工具信息
275
310
  tools = mcp_client.get_tool_list()
276
311
  if not tools:
277
- PrettyOutput.print(f"从 {file_path} 获取工具列表失败", OutputType.WARNING)
312
+ PrettyOutput.print(
313
+ f"从 {file_path} 获取工具列表失败", OutputType.WARNING
314
+ )
278
315
  return False
279
316
 
280
317
  # 注册每个工具
@@ -283,22 +320,17 @@ class ToolRegistry(OutputHandler):
283
320
  # 注册工具
284
321
  self.register_tool(
285
322
  name=f"{name}.tool_call.{tool['name']}",
286
- description=tool['description'],
287
- parameters=tool['parameters'],
288
- func=create_mcp_execute_func(tool['name'], mcp_client)
323
+ description=tool["description"],
324
+ parameters=tool["parameters"],
325
+ func=create_mcp_execute_func(tool["name"], mcp_client),
289
326
  )
290
327
 
291
-
292
328
  # 注册资源列表工具
293
329
  self.register_tool(
294
330
  name=f"{name}.resource.get_resource_list",
295
331
  description=f"获取{name}MCP服务器上的资源列表",
296
- parameters={
297
- 'type': 'object',
298
- 'properties': {},
299
- 'required': []
300
- },
301
- func=create_resource_list_func(mcp_client)
332
+ parameters={"type": "object", "properties": {}, "required": []},
333
+ func=create_resource_list_func(mcp_client),
302
334
  )
303
335
 
304
336
  # 注册获取资源工具
@@ -306,23 +338,21 @@ class ToolRegistry(OutputHandler):
306
338
  name=f"{name}.resource.get_resource",
307
339
  description=f"获取{name}MCP服务器上的指定资源",
308
340
  parameters={
309
- 'type': 'object',
310
- 'properties': {
311
- 'uri': {
312
- 'type': 'string',
313
- 'description': '资源的URI标识符'
314
- }
341
+ "type": "object",
342
+ "properties": {
343
+ "uri": {"type": "string", "description": "资源的URI标识符"}
315
344
  },
316
- 'required': ['uri']
345
+ "required": ["uri"],
317
346
  },
318
- func=create_resource_get_func(mcp_client)
347
+ func=create_resource_get_func(mcp_client),
319
348
  )
320
349
 
321
350
  return True
322
351
 
323
-
324
352
  except Exception as e:
325
- PrettyOutput.print(f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING)
353
+ PrettyOutput.print(
354
+ f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING
355
+ )
326
356
  return False
327
357
 
328
358
  def register_tool_by_file(self, file_path: str) -> bool:
@@ -354,12 +384,14 @@ class ToolRegistry(OutputHandler):
354
384
  for item_name in dir(module):
355
385
  item = getattr(module, item_name)
356
386
  # 检查是否是类并具有必要属性
357
- if (isinstance(item, type) and
358
- hasattr(item, 'name') and
359
- hasattr(item, 'description') and
360
- hasattr(item, 'parameters') and
361
- hasattr(item, 'execute') and
362
- item.name == module_name):
387
+ if (
388
+ isinstance(item, type)
389
+ and hasattr(item, "name")
390
+ and hasattr(item, "description")
391
+ and hasattr(item, "parameters")
392
+ and hasattr(item, "execute")
393
+ and item.name == module_name
394
+ ):
363
395
 
364
396
  if hasattr(item, "check"):
365
397
  if not item.check():
@@ -373,7 +405,7 @@ class ToolRegistry(OutputHandler):
373
405
  name=tool_instance.name,
374
406
  description=tool_instance.description,
375
407
  parameters=tool_instance.parameters,
376
- func=tool_instance.execute
408
+ func=tool_instance.execute,
377
409
  )
378
410
  tool_found = True
379
411
  break
@@ -388,13 +420,18 @@ class ToolRegistry(OutputHandler):
388
420
  sys.path.remove(parent_dir)
389
421
 
390
422
  except Exception as e:
391
- PrettyOutput.print(f"从 {Path(file_path).name} 加载工具失败: {str(e)}", OutputType.ERROR)
423
+ PrettyOutput.print(
424
+ f"从 {Path(file_path).name} 加载工具失败: {str(e)}", OutputType.ERROR
425
+ )
392
426
  return False
393
427
 
394
428
  @staticmethod
395
429
  def _has_tool_calls_block(content: str) -> bool:
396
430
  """从内容中提取工具调用块"""
397
- return re.search(ot("TOOL_CALL")+r'(.*?)'+ct("TOOL_CALL"), content, re.DOTALL) is not None
431
+ return (
432
+ re.search(ot("TOOL_CALL") + r"(.*?)" + ct("TOOL_CALL"), content, re.DOTALL)
433
+ is not None
434
+ )
398
435
 
399
436
  @staticmethod
400
437
  def _extract_tool_calls(content: str) -> Tuple[Dict[str, Dict[str, Any]], str]:
@@ -410,26 +447,40 @@ class ToolRegistry(OutputHandler):
410
447
  Exception: 如果工具调用缺少必要字段
411
448
  """
412
449
  # 将内容拆分为行
413
- data = re.findall(ot("TOOL_CALL")+r'(.*?)'+ct("TOOL_CALL"), content, re.DOTALL)
450
+ data = re.findall(
451
+ ot("TOOL_CALL") + r"(.*?)" + ct("TOOL_CALL"), content, re.DOTALL
452
+ )
414
453
  ret = []
415
454
  for item in data:
416
455
  try:
417
456
  msg = yaml.safe_load(item)
418
- if 'name' in msg and 'arguments' in msg and 'want' in msg:
457
+ if "name" in msg and "arguments" in msg and "want" in msg:
419
458
  ret.append(msg)
420
459
  else:
421
- return {}, f"""工具调用格式错误,请检查工具调用格式。
460
+ return (
461
+ {},
462
+ f"""工具调用格式错误,请检查工具调用格式。
422
463
 
423
- {tool_call_help}"""
464
+ {tool_call_help}""",
465
+ )
424
466
  except Exception as e:
425
- return {}, f"""工具调用格式错误,请检查工具调用格式。
467
+ return (
468
+ {},
469
+ f"""工具调用格式错误,请检查工具调用格式。
426
470
 
427
- {tool_call_help}"""
471
+ {tool_call_help}""",
472
+ )
428
473
  if len(ret) > 1:
429
474
  return {}, "检测到多个工具调用,请一次只处理一个工具调用。"
430
475
  return ret[0] if ret else {}, ""
431
476
 
432
- def register_tool(self, name: str, description: str, parameters: Any, func: Callable[..., Dict[str, Any]]) -> None:
477
+ def register_tool(
478
+ self,
479
+ name: str,
480
+ description: str,
481
+ parameters: Any,
482
+ func: Callable[..., Dict[str, Any]],
483
+ ) -> None:
433
484
  """注册新工具
434
485
 
435
486
  参数:
@@ -471,7 +522,11 @@ class ToolRegistry(OutputHandler):
471
522
  """
472
523
  tool = self.get_tool(name)
473
524
  if tool is None:
474
- return {"success": False, "stderr": f"工具 {name} 不存在,可用的工具有: {', '.join(self.tools.keys())}", "stdout": ""}
525
+ return {
526
+ "success": False,
527
+ "stderr": f"工具 {name} 不存在,可用的工具有: {', '.join(self.tools.keys())}",
528
+ "stdout": "",
529
+ }
475
530
  return tool.execute(arguments)
476
531
 
477
532
  def _format_tool_output(self, stdout: str, stderr: str) -> str:
@@ -492,7 +547,6 @@ class ToolRegistry(OutputHandler):
492
547
  output = "\n\n".join(output_parts)
493
548
  return "无输出和错误" if not output else output
494
549
 
495
-
496
550
  def handle_tool_calls(self, tool_call: Dict[str, Any], agent: Any) -> str:
497
551
  try:
498
552
  name = tool_call["name"] # 确保name是str类型
@@ -504,25 +558,31 @@ class ToolRegistry(OutputHandler):
504
558
  try:
505
559
  args = json.loads(args)
506
560
  except json.JSONDecodeError:
507
- PrettyOutput.print(f"工具参数格式无效: {name} {tool_call_help}", OutputType.ERROR)
561
+ PrettyOutput.print(
562
+ f"工具参数格式无效: {name} {tool_call_help}", OutputType.ERROR
563
+ )
508
564
  return ""
509
565
 
510
566
  # 执行工具调用
511
567
  result = self.execute_tool(name, args) # 修正参数传递
512
568
 
513
569
  # 格式化输出
514
- output = self._format_tool_output(result["stdout"], result.get("stderr", ""))
570
+ output = self._format_tool_output(
571
+ result["stdout"], result.get("stderr", "")
572
+ )
515
573
 
516
574
  # 处理结果
517
575
  if get_context_token_count(output) > self.max_input_token_count:
518
- with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as tmp_file:
576
+ with tempfile.NamedTemporaryFile(
577
+ mode="w", suffix=".txt", delete=False
578
+ ) as tmp_file:
519
579
  output_file = tmp_file.name
520
580
  tmp_file.write(output)
521
581
  tmp_file.flush()
522
582
  platform: Any = PlatformRegistry().get_normal_platform()
523
583
  if platform:
524
584
  platform.set_suppress_output(False)
525
- platform.upload_files([output_file]) # TODO 处理错误
585
+ platform.upload_files([output_file]) # TODO 处理错误
526
586
  prompt = f"该文件为工具执行结果,请阅读文件内容,并根据文件提取出以下信息:{want}"
527
587
  return f"""工具调用原始输出过长,以下是根据输出提出的信息:
528
588
 
@@ -542,33 +602,37 @@ def main() -> int:
542
602
 
543
603
  init_env()
544
604
 
545
- parser = argparse.ArgumentParser(description='Jarvis 工具系统命令行界面')
546
- subparsers = parser.add_subparsers(dest='command', help='命令')
605
+ parser = argparse.ArgumentParser(description="Jarvis 工具系统命令行界面")
606
+ subparsers = parser.add_subparsers(dest="command", help="命令")
547
607
 
548
608
  # 列出工具子命令
549
- list_parser = subparsers.add_parser('list', help='列出所有可用工具')
550
- list_parser.add_argument('--json', action='store_true', help='以JSON格式输出')
551
- list_parser.add_argument('--detailed', action='store_true', help='显示详细信息')
609
+ list_parser = subparsers.add_parser("list", help="列出所有可用工具")
610
+ list_parser.add_argument("--json", action="store_true", help="以JSON格式输出")
611
+ list_parser.add_argument("--detailed", action="store_true", help="显示详细信息")
552
612
 
553
613
  # 调用工具子命令
554
- call_parser = subparsers.add_parser('call', help='调用指定工具')
555
- call_parser.add_argument('tool_name', help='要调用的工具名称')
556
- call_parser.add_argument('--args', type=str, help='工具参数 (JSON格式)')
557
- call_parser.add_argument('--args-file', type=str, help='从文件加载工具参数 (JSON格式)')
614
+ call_parser = subparsers.add_parser("call", help="调用指定工具")
615
+ call_parser.add_argument("tool_name", help="要调用的工具名称")
616
+ call_parser.add_argument("--args", type=str, help="工具参数 (JSON格式)")
617
+ call_parser.add_argument(
618
+ "--args-file", type=str, help="从文件加载工具参数 (JSON格式)"
619
+ )
558
620
 
559
621
  args = parser.parse_args()
560
622
 
561
623
  # 初始化工具注册表
562
624
  registry = ToolRegistry()
563
625
 
564
- if args.command == 'list':
626
+ if args.command == "list":
565
627
  tools = registry.get_all_tools()
566
628
 
567
629
  if args.json:
568
630
  if args.detailed:
569
631
  print(json.dumps(tools, indent=2, ensure_ascii=False))
570
632
  else:
571
- simple_tools = [{"name": t["name"], "description": t["description"]} for t in tools]
633
+ simple_tools = [
634
+ {"name": t["name"], "description": t["description"]} for t in tools
635
+ ]
572
636
  print(json.dumps(simple_tools, indent=2, ensure_ascii=False))
573
637
  else:
574
638
  PrettyOutput.section("可用工具列表", OutputType.SYSTEM)
@@ -577,14 +641,9 @@ def main() -> int:
577
641
  print(f" 描述: {tool['description']}")
578
642
  if args.detailed:
579
643
  print(f" 参数:")
580
- params = tool['parameters'].get('properties', {})
581
- required = tool['parameters'].get('required', [])
582
- for param_name, param_info in params.items():
583
- req_mark = "*" if param_name in required else ""
584
- desc = param_info.get('description', '无描述')
585
- print(f" - {param_name}{req_mark}: {desc}")
586
-
587
- elif args.command == 'call':
644
+ print(tool["parameters"])
645
+
646
+ elif args.command == "call":
588
647
  tool_name = args.tool_name
589
648
  tool_obj = registry.get_tool(tool_name)
590
649
 
@@ -605,23 +664,27 @@ def main() -> int:
605
664
 
606
665
  elif args.args_file:
607
666
  try:
608
- with open(args.args_file, 'r', encoding='utf-8') as f:
667
+ with open(args.args_file, "r", encoding="utf-8") as f:
609
668
  tool_args = json.load(f)
610
669
  except (json.JSONDecodeError, FileNotFoundError) as e:
611
- PrettyOutput.print(f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR)
670
+ PrettyOutput.print(
671
+ f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR
672
+ )
612
673
  return 1
613
674
 
614
675
  # 检查必需参数
615
- required_params = tool_obj.parameters.get('required', [])
676
+ required_params = tool_obj.parameters.get("required", [])
616
677
  missing_params = [p for p in required_params if p not in tool_args]
617
678
 
618
679
  if missing_params:
619
- PrettyOutput.print(f"错误: 缺少必需参数: {', '.join(missing_params)}", OutputType.ERROR)
680
+ PrettyOutput.print(
681
+ f"错误: 缺少必需参数: {', '.join(missing_params)}", OutputType.ERROR
682
+ )
620
683
  print("\n参数说明:")
621
- params = tool_obj.parameters.get('properties', {})
684
+ params = tool_obj.parameters.get("properties", {})
622
685
  for param_name in required_params:
623
686
  param_info = params.get(param_name, {})
624
- desc = param_info.get('description', '无描述')
687
+ desc = param_info.get("description", "无描述")
625
688
  print(f" - {param_name}: {desc}")
626
689
  return 1
627
690
 
@@ -141,7 +141,7 @@ def load_methodology(user_input: str) -> str:
141
141
 
142
142
  platform.set_suppress_output(False)
143
143
  # 构建提示信息
144
- prompt = f"""根据用户需求: {user_input}
144
+ prompt = f"""根据用户需求和已有的方法论内容,总结出与该任务/需求相关的方法论: {user_input}
145
145
 
146
146
  请按以下格式回复:
147
147
  ### 与该任务/需求相关的方法论
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.151
3
+ Version: 0.1.152
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
@@ -48,8 +48,8 @@ src/jarvis/jarvis_lsp/python.py
48
48
  src/jarvis/jarvis_lsp/registry.py
49
49
  src/jarvis/jarvis_lsp/rust.py
50
50
  src/jarvis/jarvis_mcp/__init__.py
51
- src/jarvis/jarvis_mcp/local_mcp_client.py
52
- src/jarvis/jarvis_mcp/remote_mcp_client.py
51
+ src/jarvis/jarvis_mcp/sse_mcp_client.py
52
+ src/jarvis/jarvis_mcp/stdio_mcp_client.py
53
53
  src/jarvis/jarvis_methodology/main.py
54
54
  src/jarvis/jarvis_multi_agent/__init__.py
55
55
  src/jarvis/jarvis_multi_agent/main.py