XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/gpt4free

Add replace_string_in_file tool

de03716d
hlohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

2 个文件 +75 -0
Modified g4f/mcp/server.py +2 -0
@@ -38,6 +38,7 @@ from .tools import (
38 38 ApplyPatchTool,
39 39 CreateFileTool,
40 40 FileWriteTool,
41 ReplaceStringInFileTool,
41 42 FetchWebpageTool,
42 43 FileSearchGlobTool,
43 44 GrepSearchTool,
@@ -96,6 +97,7 @@ class MCPServer:
96 97 "file_delete": FileDeleteTool(),
97 98 "create_file": CreateFileTool(),
98 99 "file_write": FileWriteTool(),
100 "replace_string_in_file": ReplaceStringInFileTool(),
99 101 "fetch_webpage": FetchWebpageTool(),
100 102 "file_search_glob": FileSearchGlobTool(),
101 103 "grep_search": GrepSearchTool(),
Modified g4f/mcp/tools.py +73 -0
@@ -881,6 +881,79 @@ class FileWriteTool(MCPTool):
881 881 return {"error": f"Write failed: {exc}"}
882 882
883 883
884 class ReplaceStringInFileTool(MCPTool):
885 """Replace an exact string in a file inside the ``~/.g4f/workspace`` directory."""
886
887 @property
888 def description(self) -> str:
889 return (
890 "Replace an exact string in a file inside the ~/.g4f/workspace directory. "
891 "Provide the relative file path, the exact old string, and the new string. "
892 "Only the first occurrence is replaced. Returns whether a replacement was made."
893 )
894
895 @property
896 def input_schema(self) -> Dict[str, Any]:
897 return {
898 "type": "object",
899 "properties": {
900 "filePath": {
901 "type": "string",
902 "description": "Relative path to the file inside the workspace",
903 },
904 "oldString": {
905 "type": "string",
906 "description": "The exact text to replace. Must uniquely identify one location.",
907 },
908 "newString": {
909 "type": "string",
910 "description": "The text to replace oldString with.",
911 },
912 },
913 "required": ["filePath", "oldString", "newString"],
914 }
915
916 async def execute(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
917 from .pa_provider import get_workspace_dir
918
919 rel_path = arguments.get("filePath", "")
920 old_string = arguments.get("oldString")
921 new_string = arguments.get("newString")
922
923 if not rel_path:
924 return {"error": "filePath parameter is required"}
925 if old_string is None:
926 return {"error": "oldString parameter is required"}
927 if new_string is None:
928 return {"error": "newString parameter is required"}
929
930 workspace = get_workspace_dir().resolve()
931 try:
932 target = (workspace / rel_path).resolve()
933 if not str(target).startswith(str(workspace)):
934 return {"error": "Access outside the workspace is not allowed"}
935 if not target.exists():
936 return {"error": f"File not found: {rel_path}"}
937 if not target.is_file():
938 return {"error": f"Path is not a file: {rel_path}"}
939
940 content = target.read_text(encoding="utf-8")
941 if old_string not in content:
942 return {
943 "error": "oldString not found in file. Include more surrounding context to uniquely identify the location."
944 }
945
946 new_content = content.replace(old_string, new_string, 1)
947 target.write_text(new_content, encoding="utf-8")
948 return {
949 "filePath": rel_path,
950 "replaced": True,
951 "size": len(new_content),
952 }
953 except Exception as exc:
954 return {"error": f"Replace failed: {exc}"}
955
956
884 957 class FetchWebpageTool(MCPTool):
885 958 """Fetch and return the main content from one or more web pages."""
886 959