jarvis-ai-assistant 0.1.178__py3-none-any.whl → 0.1.180__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.

Potentially problematic release.


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

Files changed (66) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +130 -79
  3. jarvis/jarvis_agent/builtin_input_handler.py +1 -1
  4. jarvis/jarvis_agent/jarvis.py +9 -13
  5. jarvis/jarvis_agent/main.py +4 -2
  6. jarvis/jarvis_code_agent/code_agent.py +34 -23
  7. jarvis/jarvis_code_agent/lint.py +164 -0
  8. jarvis/jarvis_code_analysis/checklists/loader.py +6 -20
  9. jarvis/jarvis_code_analysis/code_review.py +8 -6
  10. jarvis/jarvis_data/config_schema.json +260 -0
  11. jarvis/jarvis_dev/main.py +1 -8
  12. jarvis/jarvis_git_details/main.py +1 -1
  13. jarvis/jarvis_git_squash/main.py +5 -3
  14. jarvis/jarvis_git_utils/git_commiter.py +25 -24
  15. jarvis/jarvis_mcp/sse_mcp_client.py +6 -4
  16. jarvis/jarvis_mcp/stdio_mcp_client.py +5 -4
  17. jarvis/jarvis_mcp/streamable_mcp_client.py +404 -0
  18. jarvis/jarvis_methodology/main.py +10 -9
  19. jarvis/jarvis_multi_agent/main.py +3 -1
  20. jarvis/jarvis_platform/base.py +14 -8
  21. jarvis/jarvis_platform/human.py +3 -1
  22. jarvis/jarvis_platform/kimi.py +8 -27
  23. jarvis/jarvis_platform/openai.py +4 -16
  24. jarvis/jarvis_platform/registry.py +6 -2
  25. jarvis/jarvis_platform/yuanbao.py +9 -29
  26. jarvis/jarvis_platform_manager/main.py +11 -9
  27. jarvis/jarvis_smart_shell/main.py +7 -3
  28. jarvis/jarvis_tools/ask_codebase.py +4 -3
  29. jarvis/jarvis_tools/ask_user.py +2 -1
  30. jarvis/jarvis_tools/base.py +3 -1
  31. jarvis/jarvis_tools/chdir.py +2 -1
  32. jarvis/jarvis_tools/cli/main.py +1 -0
  33. jarvis/jarvis_tools/code_plan.py +5 -3
  34. jarvis/jarvis_tools/create_code_agent.py +5 -2
  35. jarvis/jarvis_tools/create_sub_agent.py +1 -3
  36. jarvis/jarvis_tools/edit_file.py +4 -4
  37. jarvis/jarvis_tools/execute_script.py +1 -1
  38. jarvis/jarvis_tools/file_analyzer.py +5 -3
  39. jarvis/jarvis_tools/file_operation.py +4 -7
  40. jarvis/jarvis_tools/find_methodology.py +4 -2
  41. jarvis/jarvis_tools/generate_new_tool.py +2 -1
  42. jarvis/jarvis_tools/methodology.py +3 -4
  43. jarvis/jarvis_tools/read_code.py +2 -1
  44. jarvis/jarvis_tools/read_webpage.py +3 -1
  45. jarvis/jarvis_tools/registry.py +60 -45
  46. jarvis/jarvis_tools/rewrite_file.py +2 -1
  47. jarvis/jarvis_tools/search_web.py +1 -0
  48. jarvis/jarvis_tools/virtual_tty.py +5 -4
  49. jarvis/jarvis_utils/__init__.py +2 -0
  50. jarvis/jarvis_utils/builtin_replace_map.py +1 -1
  51. jarvis/jarvis_utils/config.py +88 -17
  52. jarvis/jarvis_utils/embedding.py +4 -3
  53. jarvis/jarvis_utils/file_processors.py +1 -0
  54. jarvis/jarvis_utils/git_utils.py +83 -40
  55. jarvis/jarvis_utils/globals.py +4 -2
  56. jarvis/jarvis_utils/input.py +14 -7
  57. jarvis/jarvis_utils/methodology.py +6 -4
  58. jarvis/jarvis_utils/output.py +10 -6
  59. jarvis/jarvis_utils/utils.py +140 -24
  60. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/METADATA +66 -59
  61. jarvis_ai_assistant-0.1.180.dist-info/RECORD +99 -0
  62. jarvis_ai_assistant-0.1.178.dist-info/RECORD +0 -96
  63. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/WHEEL +0 -0
  64. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/entry_points.txt +0 -0
  65. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/licenses/LICENSE +0 -0
  66. {jarvis_ai_assistant-0.1.178.dist-info → jarvis_ai_assistant-0.1.180.dist-info}/top_level.txt +0 -0
@@ -1,24 +1,23 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Generator, List, Tuple
3
- import requests
2
+ import hashlib
3
+ import hmac
4
4
  import json
5
5
  import os
6
- import hmac
7
- import hashlib
8
6
  import time
9
7
  import urllib.parse
8
+ from typing import Dict, Generator, List, Tuple
9
+
10
+ import requests
10
11
  from PIL import Image
11
12
  from yaspin import yaspin
12
- from yaspin.spinners import Spinners
13
13
  from yaspin.api import Yaspin
14
- from rich.live import Live
15
- from rich.text import Text
16
- from rich.panel import Panel
17
- from rich import box
14
+ from yaspin.spinners import Spinners
15
+
18
16
  from jarvis.jarvis_platform.base import BasePlatform
17
+ from jarvis.jarvis_utils.config import get_data_dir
19
18
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
20
19
  from jarvis.jarvis_utils.utils import while_success
21
- from jarvis.jarvis_utils.config import get_data_dir
20
+
22
21
 
23
22
  class YuanbaoPlatform(BasePlatform):
24
23
  """Hunyuan模型实现"""
@@ -40,25 +39,6 @@ class YuanbaoPlatform(BasePlatform):
40
39
  self.agent_id = os.getenv("YUANBAO_AGENT_ID") # 代理ID
41
40
 
42
41
  if not self.cookies:
43
- message = (
44
- "需要设置 YUANBAO_COOKIES 和 YUANBAO_AGENT_ID 才能使用 Jarvis 的元宝功能。请按照以下步骤操作:\n"
45
- "1. 获取元宝 API 参数:\n"
46
- " • 访问元宝平台: https://yuanbao.tencent.com\n"
47
- " • 登录您的账户\n"
48
- " • 打开浏览器开发者工具 (F12 或右键 -> 检查)\n"
49
- " • 切换到网络标签\n"
50
- " • 发送任意消息\n"
51
- " • 查看请求中的 Cookie 和 AgentID 值(具体位置见README.md中截图)\n"
52
- "2. 设置环境变量:\n"
53
- " • 方法 1: 创建或编辑配置文件:\n"
54
- f" echo 'YUANBAO_COOKIES=your_cookies_here' >> {get_data_dir()}/env\n"
55
- f" echo 'YUANBAO_AGENT_ID=your_agent_id_here' >> {get_data_dir()}/env\n"
56
- " • 方法 2: 直接设置环境变量:\n"
57
- " export YUANBAO_COOKIES=your_cookies_here\n"
58
- " export YUANBAO_AGENT_ID=your_agent_id_here\n"
59
- "设置后,重新运行 Jarvis。"
60
- )
61
- PrettyOutput.print(message, OutputType.INFO)
62
42
  PrettyOutput.print("YUANBAO_COOKIES 未设置", OutputType.WARNING)
63
43
 
64
44
  self.system_message = "" # 系统消息,用于初始化对话
@@ -1,18 +1,20 @@
1
1
  # -*- coding: utf-8 -*-
2
- import os
3
- from jarvis.jarvis_platform.registry import PlatformRegistry
4
2
  import asyncio
3
+ import os
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ import uvicorn
5
7
  from fastapi import FastAPI, HTTPException
8
+ from fastapi.middleware.cors import CORSMiddleware
6
9
  from fastapi.responses import StreamingResponse
7
10
  from pydantic import BaseModel, Field
8
- from typing import List, Dict, Any, Optional
9
- import uvicorn
10
- from fastapi.middleware.cors import CORSMiddleware
11
11
 
12
+ from jarvis.jarvis_platform.registry import PlatformRegistry
12
13
  from jarvis.jarvis_utils.input import get_multiline_input
13
14
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
14
15
  from jarvis.jarvis_utils.utils import init_env
15
16
 
17
+
16
18
  def list_platforms():
17
19
  """List all supported platforms and models"""
18
20
  registry = PlatformRegistry.get_global_platform_registry()
@@ -248,10 +250,10 @@ class ChatCompletionResponse(BaseModel):
248
250
 
249
251
  def service_command(args):
250
252
  """Process service subcommand - start OpenAI-compatible API server"""
251
- import time
252
- import uuid
253
253
  import json
254
254
  import os
255
+ import time
256
+ import uuid
255
257
  from datetime import datetime
256
258
 
257
259
  host = args.host
@@ -451,11 +453,11 @@ def service_command(args):
451
453
 
452
454
  async def stream_chat_response(platform, message, model_name):
453
455
  """Stream chat response in OpenAI-compatible format"""
454
- import time
455
456
  import json
457
+ import os
458
+ import time
456
459
  import uuid
457
460
  from datetime import datetime
458
- import os
459
461
 
460
462
  completion_id = f"chatcmpl-{str(uuid.uuid4())}"
461
463
  created_time = int(time.time())
@@ -8,10 +8,11 @@ from typing import Optional
8
8
  from sympy import false
9
9
 
10
10
  from jarvis.jarvis_platform.registry import PlatformRegistry
11
- from jarvis.jarvis_utils.config import get_shell_name
11
+ from jarvis.jarvis_utils.config import get_shell_name, set_config
12
12
  from jarvis.jarvis_utils.input import get_multiline_input
13
13
  from jarvis.jarvis_utils.utils import init_env
14
14
 
15
+
15
16
  def execute_command(command: str, should_run: bool) -> None:
16
17
  """Print command without execution"""
17
18
  print(command)
@@ -89,7 +90,7 @@ def process_request(request: str) -> Optional[str]:
89
90
 
90
91
  # 规则
91
92
  1. 只输出命令
92
- 2. 不要解释或标记
93
+ 2. 不要输出任何命令之外的内容
93
94
  3. 单行输出
94
95
  4. 多个命令用&&连接
95
96
 
@@ -115,8 +116,11 @@ def process_request(request: str) -> Optional[str]:
115
116
  return None
116
117
 
117
118
  def main() -> int:
118
- # 创建参数解析器s
119
+ # 创建参数解析器
119
120
  init_env("")
121
+
122
+ set_config("JARVIS_PRINT_PROMPT", "false")
123
+
120
124
  parser = argparse.ArgumentParser(
121
125
  description="将自然语言要求转换为shell命令",
122
126
  formatter_class=argparse.RawDescriptionHelpFormatter,
@@ -1,14 +1,14 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
4
-
3
+ from typing import Any, Dict
5
4
 
6
5
  from jarvis.jarvis_agent import Agent
7
6
  from jarvis.jarvis_platform.registry import PlatformRegistry
8
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
7
  from jarvis.jarvis_utils.git_utils import find_git_root
8
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
10
9
  from jarvis.jarvis_utils.utils import init_env
11
10
 
11
+
12
12
  class AskCodebaseTool:
13
13
  """用于智能代码库查询和分析的工具
14
14
 
@@ -258,6 +258,7 @@ def main():
258
258
  """
259
259
  import argparse
260
260
  import sys
261
+
261
262
  from jarvis.jarvis_utils.input import get_multiline_input
262
263
 
263
264
  init_env("欢迎使用 Jarvis-AskCodebase,您的智能代码库查询工具已准备就绪!")
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # 导入所需的类型注解模块
3
- from typing import Dict, Any
3
+ from typing import Any, Dict
4
4
 
5
5
  # 导入多行输入工具和输出工具
6
6
  from jarvis.jarvis_utils.input import get_multiline_input
7
7
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
8
 
9
+
9
10
  # 定义AskUserTool类,用于向用户提问
10
11
  class AskUserTool:
11
12
  name="ask_user"
@@ -1,6 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any, Callable
3
2
  import json
3
+ from typing import Any, Callable, Dict
4
+
5
+
4
6
  class Tool:
5
7
  """工具类,用于封装工具的基本信息和执行方法"""
6
8
 
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
3
+ from typing import Any, Dict
4
+
4
5
 
5
6
  class ChdirTool:
6
7
  name = "chdir"
@@ -1,5 +1,6 @@
1
1
 
2
2
  import sys
3
+
3
4
  from jarvis.jarvis_tools.registry import ToolRegistry
4
5
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
5
6
  from jarvis.jarvis_utils.utils import init_env
@@ -9,13 +9,15 @@
9
9
  4. 修改计划输出
10
10
  """
11
11
 
12
- from typing import Dict, Any
13
12
  import os
14
- from jarvis.jarvis_tools.registry import ToolRegistry
13
+ from typing import Any, Dict
14
+
15
15
  from jarvis.jarvis_agent import Agent
16
16
  from jarvis.jarvis_platform.registry import PlatformRegistry
17
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
17
+ from jarvis.jarvis_tools.registry import ToolRegistry
18
18
  from jarvis.jarvis_utils.git_utils import find_git_root
19
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
20
+
19
21
 
20
22
  class CodePlanTool:
21
23
  """用于代码修改规划和需求分析的工具
@@ -1,11 +1,14 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
3
+ from typing import Any, Dict
4
+
4
5
  from jarvis.jarvis_code_agent.code_agent import CodeAgent
5
6
  from jarvis.jarvis_git_utils.git_commiter import GitCommitTool
6
- from jarvis.jarvis_utils.git_utils import get_latest_commit_hash, has_uncommitted_changes
7
+ from jarvis.jarvis_utils.git_utils import (get_latest_commit_hash,
8
+ has_uncommitted_changes)
7
9
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
10
 
11
+
9
12
  class CreateCodeAgentTool:
10
13
  """用于管理代码开发工作流的工具"""
11
14
 
@@ -1,13 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
4
-
3
+ from typing import Any, Dict
5
4
 
6
5
  from jarvis.jarvis_agent import Agent, origin_agent_system_prompt
7
6
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
7
 
9
8
 
10
-
11
9
  class SubAgentTool:
12
10
  name = "create_sub_agent"
13
11
  description = "创建子代理以处理特定任务,子代理将生成任务总结报告"
@@ -17,9 +17,8 @@
17
17
  - 支持大文件处理(自动上传到模型平台)
18
18
  - 提供3次重试机制确保操作可靠性
19
19
  """
20
- from typing import List
21
20
  import re
22
- from typing import Any, Dict, Tuple
21
+ from typing import Any, Dict, List, Tuple
23
22
 
24
23
  import yaml
25
24
  from yaspin import yaspin
@@ -130,7 +129,8 @@ class FileSearchReplaceTool:
130
129
  4. 保持原始代码的格式风格
131
130
  """
132
131
  import os
133
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
132
+
133
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
134
134
 
135
135
  stdout_messages = []
136
136
  stderr_messages = []
@@ -156,7 +156,7 @@ class FileSearchReplaceTool:
156
156
  with yaspin(text=f"正在处理文件 {file_path}...", color="cyan") as spinner:
157
157
  success, temp_content = fast_edit(file_path, changes, spinner)
158
158
  if not success:
159
- success, temp_content = slow_edit(file_path, yaml.safe_dump(changes), spinner)
159
+ success, temp_content = slow_edit(file_path, yaml.safe_dump(changes, allow_unicode=True), spinner)
160
160
 
161
161
  # 只有当所有替换操作都成功时,才写回文件
162
162
  if success and (temp_content != original_content or not file_exists):
@@ -1,8 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
4
3
  import tempfile
5
4
  from pathlib import Path
5
+ from typing import Any, Dict
6
6
 
7
7
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
8
 
@@ -1,11 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
3
+ from typing import Any, Dict
4
+
5
+ from yaspin import yaspin # type: ignore
6
+ from yaspin.spinners import Spinners # type: ignore
4
7
 
5
8
  from jarvis.jarvis_platform.registry import PlatformRegistry
6
9
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
7
- from yaspin import yaspin # type: ignore
8
- from yaspin.spinners import Spinners # type: ignore
10
+
9
11
 
10
12
  class FileAnalyzerTool:
11
13
  name = "file_analyzer"
@@ -1,16 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
4
3
  from pathlib import Path
4
+ from typing import Any, Dict
5
5
 
6
- from yaspin import yaspin # type: ignore
6
+ from yaspin import yaspin # type: ignore
7
7
 
8
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
8
  # 导入文件处理器
10
- from jarvis.jarvis_utils.file_processors import (
11
- TextFileProcessor
12
- )
13
-
9
+ from jarvis.jarvis_utils.file_processors import TextFileProcessor
10
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
14
11
 
15
12
 
16
13
  class FileOperationTool:
@@ -1,9 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
2
+ from typing import Any, Dict
3
+
3
4
  from yaspin import yaspin
4
5
 
5
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
6
6
  from jarvis.jarvis_utils.methodology import load_methodology
7
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
+
7
9
 
8
10
  class FindMethodologyTool:
9
11
  name = "find_methodology"
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import re
3
3
  from pathlib import Path
4
- from typing import Dict, Any, Tuple
4
+ from typing import Any, Dict, Tuple
5
5
 
6
6
  from jarvis.jarvis_utils.config import get_data_dir
7
7
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
8
 
9
+
9
10
  class generate_new_tool:
10
11
  name = "generate_new_tool"
11
12
  description = """
@@ -1,14 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
- import os
3
- import json
4
2
  import hashlib
5
- from typing import Dict, Any
3
+ import json
4
+ import os
5
+ from typing import Any, Dict
6
6
 
7
7
  from jarvis.jarvis_utils.config import get_data_dir
8
8
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
9
 
10
10
 
11
-
12
11
  class MethodologyTool:
13
12
  """经验管理工具"""
14
13
 
@@ -1,11 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
3
+ from typing import Any, Dict
4
4
 
5
5
  from yaspin import yaspin
6
6
 
7
7
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
8
 
9
+
9
10
  class ReadCodeTool:
10
11
  name = "read_code"
11
12
  description = "代码阅读与分析工具,用于读取源代码文件并添加行号,针对代码文件优化,提供更好的格式化输出和行号显示,适用于代码分析、审查和理解代码实现的场景"
@@ -1,9 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
- from typing import Dict, Any
3
2
  import os
3
+ from typing import Any, Dict
4
+
4
5
  from jarvis.jarvis_platform.registry import PlatformRegistry
5
6
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
6
7
 
8
+
7
9
  class WebpageTool:
8
10
  name = "read_webpage"
9
11
  description = "读取网页内容,提取标题、文本和超链接"
@@ -1,24 +1,24 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import json
3
- from pathlib import Path
3
+ import os
4
4
  import re
5
5
  import sys
6
6
  import tempfile
7
- import os
8
- from typing import Any, Callable, Dict, List, Optional, Tuple, Protocol
7
+ from pathlib import Path
8
+ from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple
9
9
 
10
10
  import yaml
11
11
 
12
+ from jarvis.jarvis_mcp import McpClient
13
+ from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
14
+ from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
15
+ from jarvis.jarvis_mcp.streamable_mcp_client import StreamableMcpClient
12
16
  from jarvis.jarvis_platform.registry import PlatformRegistry
13
17
  from jarvis.jarvis_tools.base import Tool
14
18
  from jarvis.jarvis_utils.config import get_data_dir
15
19
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
20
+ from jarvis.jarvis_utils.tag import ct, ot
16
21
  from jarvis.jarvis_utils.utils import init_env, is_context_overflow
17
- from jarvis.jarvis_utils.tag import ot, ct
18
- from jarvis.jarvis_mcp.stdio_mcp_client import StdioMcpClient
19
- from jarvis.jarvis_mcp.sse_mcp_client import SSEMcpClient
20
- from jarvis.jarvis_mcp import McpClient
21
-
22
22
 
23
23
  tool_call_help = f"""
24
24
  <tool_system_guide>
@@ -198,7 +198,7 @@ class ToolRegistry(OutputHandlerProtocol):
198
198
  stats_file = Path(get_data_dir()) / "tool_stat.yaml"
199
199
  try:
200
200
  with open(stats_file, "w", encoding="utf-8") as f:
201
- yaml.safe_dump(stats, f)
201
+ yaml.safe_dump(stats, f, allow_unicode=True)
202
202
  except Exception as e:
203
203
  PrettyOutput.print(
204
204
  f"保存工具调用统计失败: {str(e)}", OutputType.WARNING
@@ -229,14 +229,36 @@ class ToolRegistry(OutputHandlerProtocol):
229
229
  }
230
230
 
231
231
  def _load_mcp_tools(self) -> None:
232
- """从jarvis_data/tools/mcp加载工具"""
232
+ """加载MCP工具,优先从配置获取,其次从目录扫描"""
233
+ from jarvis.jarvis_utils.config import get_mcp_config
234
+
235
+ # 优先从配置获取MCP工具配置
236
+ mcp_configs = get_mcp_config()
237
+ if mcp_configs:
238
+ for config in mcp_configs:
239
+ self.register_mcp_tool_by_config(config)
240
+ return
241
+
242
+ # 如果配置中没有,则扫描目录
233
243
  mcp_tools_dir = Path(get_data_dir()) / "mcp"
234
244
  if not mcp_tools_dir.exists():
235
245
  return
236
246
 
247
+ # 添加警告信息
248
+ PrettyOutput.print(
249
+ "警告: 从文件目录加载MCP工具的方式将在未来版本中废弃,请尽快迁移到JARVIS_MCP配置方式",
250
+ OutputType.WARNING
251
+ )
252
+
237
253
  # 遍历目录中的所有.yaml文件
238
254
  for file_path in mcp_tools_dir.glob("*.yaml"):
239
- self.register_mcp_tool_by_file(str(file_path))
255
+ try:
256
+ config = yaml.safe_load(open(file_path, "r", encoding="utf-8"))
257
+ self.register_mcp_tool_by_config(config)
258
+ except Exception as e:
259
+ PrettyOutput.print(
260
+ f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING
261
+ )
240
262
 
241
263
  def _load_builtin_tools(self) -> None:
242
264
  """从内置工具目录加载工具"""
@@ -264,29 +286,26 @@ class ToolRegistry(OutputHandlerProtocol):
264
286
 
265
287
  self.register_tool_by_file(str(file_path))
266
288
 
267
- def register_mcp_tool_by_file(self, file_path: str) -> bool:
268
- """从指定文件加载并注册工具
289
+ def register_mcp_tool_by_config(self, config: Dict[str, Any]) -> bool:
290
+ """从配置字典加载并注册工具
269
291
 
270
292
  参数:
271
- file_path: 工具文件的路径
293
+ config: MCP工具配置字典
272
294
 
273
295
  返回:
274
296
  bool: 工具是否加载成功
275
297
  """
276
298
  try:
277
- config = yaml.safe_load(open(file_path, "r", encoding="utf-8"))
278
299
  if "type" not in config:
279
- PrettyOutput.print(f"文件 {file_path} 缺少type字段", OutputType.WARNING)
300
+ PrettyOutput.print(f"配置{config.get('name', '')}缺少type字段", OutputType.WARNING)
280
301
  return False
281
302
 
282
303
  # 检查enable标志
283
304
  if not config.get("enable", True):
284
- PrettyOutput.print(
285
- f"文件 {file_path} 已禁用(enable=false),跳过注册", OutputType.INFO
286
- )
305
+ PrettyOutput.print(f"MCP配置{config.get('name', '')}已禁用(enable=false),跳过注册", OutputType.INFO)
287
306
  return False
288
307
 
289
- name = config.get("name", Path(file_path).stem)
308
+ name = config.get("name", "mcp")
290
309
 
291
310
  # 注册资源工具
292
311
  def create_resource_list_func(client: McpClient):
@@ -296,11 +315,11 @@ class ToolRegistry(OutputHandlerProtocol):
296
315
  args.pop("want", None)
297
316
  ret = client.get_resource_list()
298
317
  PrettyOutput.print(
299
- f"MCP {name} 资源列表:\n{yaml.safe_dump(ret)}", OutputType.TOOL
318
+ f"MCP {name} 资源列表:\n{yaml.safe_dump(ret, allow_unicode=True)}", OutputType.TOOL
300
319
  )
301
320
  return {
302
321
  "success": True,
303
- "stdout": yaml.safe_dump(ret),
322
+ "stdout": yaml.safe_dump(ret, allow_unicode=True),
304
323
  "stderr": "",
305
324
  }
306
325
 
@@ -319,7 +338,7 @@ class ToolRegistry(OutputHandlerProtocol):
319
338
  }
320
339
  ret = client.get_resource(args["uri"])
321
340
  PrettyOutput.print(
322
- f"MCP {name} 获取资源:\n{yaml.safe_dump(ret)}", OutputType.TOOL
341
+ f"MCP {name} 获取资源:\n{yaml.safe_dump(ret, allow_unicode=True)}", OutputType.TOOL
323
342
  )
324
343
  return ret
325
344
 
@@ -332,7 +351,7 @@ class ToolRegistry(OutputHandlerProtocol):
332
351
  args.pop("want", None)
333
352
  ret = client.execute(tool_name, args)
334
353
  PrettyOutput.print(
335
- f"MCP {name} {tool_name} 执行结果:\n{yaml.safe_dump(ret)}",
354
+ f"MCP {name} {tool_name} 执行结果:\n{yaml.safe_dump(ret, allow_unicode=True)}",
336
355
  OutputType.TOOL,
337
356
  )
338
357
  return ret
@@ -341,40 +360,38 @@ class ToolRegistry(OutputHandlerProtocol):
341
360
 
342
361
  if config["type"] == "stdio":
343
362
  if "command" not in config:
344
- PrettyOutput.print(
345
- f"文件 {file_path} 缺少command字段", OutputType.WARNING
346
- )
363
+ PrettyOutput.print(f"配置{config.get('name', '')}缺少command字段", OutputType.WARNING)
347
364
  return False
348
365
  elif config["type"] == "sse":
349
366
  if "base_url" not in config:
350
- PrettyOutput.print(
351
- f"文件 {file_path} 缺少base_url字段", OutputType.WARNING
352
- )
367
+ PrettyOutput.print(f"配置{config.get('name', '')}缺少base_url字段", OutputType.WARNING)
368
+ return False
369
+ elif config["type"] == "streamable":
370
+ if "base_url" not in config:
371
+ PrettyOutput.print(f"配置{config.get('name', '')}缺少base_url字段", OutputType.WARNING)
353
372
  return False
354
373
  else:
355
- PrettyOutput.print(
356
- f"文件 {file_path} 类型错误: {config['type']}", OutputType.WARNING
357
- )
374
+ PrettyOutput.print(f"不支持的MCP客户端类型: {config['type']}", OutputType.WARNING)
358
375
  return False
359
376
 
360
377
  # 创建MCP客户端
361
- mcp_client: McpClient = (
362
- StdioMcpClient(config)
363
- if config["type"] == "stdio"
364
- else SSEMcpClient(config)
365
- )
378
+ if config["type"] == "stdio":
379
+ mcp_client: McpClient = StdioMcpClient(config)
380
+ elif config["type"] == "sse":
381
+ mcp_client: McpClient = SSEMcpClient(config)
382
+ elif config["type"] == "streamable":
383
+ mcp_client: McpClient = StreamableMcpClient(config)
384
+ else:
385
+ raise ValueError(f"不支持的MCP客户端类型: {config['type']}")
366
386
 
367
387
  # 获取工具信息
368
388
  tools = mcp_client.get_tool_list()
369
389
  if not tools:
370
- PrettyOutput.print(
371
- f"从 {file_path} 获取工具列表失败", OutputType.WARNING
372
- )
390
+ PrettyOutput.print(f"从配置{config.get('name', '')}获取工具列表失败", OutputType.WARNING)
373
391
  return False
374
392
 
375
393
  # 注册每个工具
376
394
  for tool in tools:
377
-
378
395
  # 注册工具
379
396
  self.register_tool(
380
397
  name=f"{name}.tool_call.{tool['name']}",
@@ -408,9 +425,7 @@ class ToolRegistry(OutputHandlerProtocol):
408
425
  return True
409
426
 
410
427
  except Exception as e:
411
- PrettyOutput.print(
412
- f"文件 {file_path} 加载失败: {str(e)}", OutputType.WARNING
413
- )
428
+ PrettyOutput.print(f"MCP配置{config.get('name', '')}加载失败: {str(e)}", OutputType.WARNING)
414
429
  return False
415
430
 
416
431
  def register_tool_by_file(self, file_path: str) -> bool:
@@ -80,7 +80,8 @@ class FileRewriteTool:
80
80
  }
81
81
  """
82
82
  import os
83
- from jarvis.jarvis_utils.output import PrettyOutput, OutputType
83
+
84
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
84
85
 
85
86
  stdout_messages = []
86
87
  stderr_messages = []
@@ -1,6 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  import os
3
3
  from typing import Any, Dict
4
+
4
5
  from jarvis.jarvis_platform.registry import PlatformRegistry
5
6
 
6
7