返回提交历史
Modified
g4f/mcp/pa_downloader.py
+17
-4
Modified
g4f/mcp/pa_provider.py
+1
-1
Modified
g4f/mcp/tools.py
+2
-2
Modified
g4f/tools/optimize_request.py
+7
-7
Modified
g4f/tools/run_tools.py
+6
-4
XFEstudio/gpt4free
Add is pa file
17d22c40
代码差异
5 个文件
+33
-18
@@ -91,8 +91,21 @@ def _github_request(
91
91
return urlopen(req, **kwargs).read()
92
92
93
93
94
def _is_pa_file(name: str) -> bool:
95
"""Return ``True`` for PA provider / helper files.
96
97
Accepted: ``*.py``, ``*.wasm``, plus browser scripts named ``pa-*.js``
98
or ``*.pa.js``.
99
"""
100
if name.endswith(".py") or name.endswith(".wasm"):
101
return True
102
if name.endswith(".js"):
103
return name.startswith("pa-") or name.endswith(".pa.js")
104
return False
105
106
94
107
def _list_repo_files(repo: str, ref: str, timeout: float) -> List[str]:
95
"""Return the list of ``*.pa.py`` paths in the root of *repo* at *ref*.
108
"""Return the list of PA provider paths in the root of *repo* at *ref*.
96
109
97
110
Uses the GitHub contents API. Subdirectories are not recursed — the
98
111
pa-providers repo is flat by convention.
@@ -107,7 +120,7 @@ def _list_repo_files(repo: str, ref: str, timeout: float) -> List[str]:
107
120
if not isinstance(entry, dict):
108
121
continue
109
122
name = entry.get("name", "")
110
if (name.endswith(".py") or name.endswith(".wasm")) and entry.get("type") == "file":
123
if _is_pa_file(name) and entry.get("type") == "file":
111
124
files.append(name)
112
125
return files
113
126
@@ -170,7 +183,7 @@ def run_pa_download(
170
183
return written
171
184
172
185
for name in names:
173
if not name.endswith(".py") and not name.endswith(".wasm"):
186
if not _is_pa_file(name):
174
187
continue
175
188
dest = target / name
176
189
if dest.exists() and not force:
@@ -184,7 +197,7 @@ def run_pa_download(
184
197
try:
185
198
dest.write_bytes(content)
186
199
written.append(dest)
187
print(f"pa-providers: downloaded {name} -> {dest}")
200
print(f"pa-providers: downloaded {name} ({len(content)} bytes)")
188
201
except OSError as e:
189
202
debug.error(f"pa-providers: failed to write {name}:", e)
190
203
@@ -84,7 +84,7 @@ def get_workspace_dir() -> Path:
84
84
85
85
def is_hidden_file(path: str) -> bool:
86
86
"""Return True if *path* is a hidden file (starts with a dot)."""
87
return any(part.startswith(".") for part in str(path).replace("\\", "/").split("/"))
87
return any(part.startswith(".") or part.startswith("__") for part in str(path).replace("\\", "/").split("/"))
88
88
89
89
90
90
# ---------------------------------------------------------------------------
@@ -632,9 +632,9 @@ class FileListTool(MCPTool):
632
632
iterator = target.rglob("*") if recursive else target.iterdir()
633
633
for entry in sorted(iterator):
634
634
try:
635
if is_hidden_file(entry):
636
continue
637
635
rel = str(entry.relative_to(workspace))
636
if is_hidden_file(rel):
637
continue
638
638
info: Dict[str, Any] = {
639
639
"path": rel,
640
640
"type": "file" if entry.is_file() else "directory",
@@ -1248,13 +1248,13 @@ def optimize_request(messages: Messages, tools: Any) -> Tuple[int, Dict[str, str
1248
1248
"reasoning_echo"
1249
1249
] = f"stripped repeated reasoning blocks (-{echo_saved} bytes)"
1250
1250
1251
# ── Tool result truncation ──
1252
tool_trunc_saved = _truncate_tool_results(messages)
1253
if tool_trunc_saved:
1254
saved_bytes += tool_trunc_saved
1255
logs[
1256
"tool_trunc"
1257
] = f"truncated oversized tool results (-{tool_trunc_saved} bytes)"
1251
# # ── Tool result truncation ──
1252
# tool_trunc_saved = _truncate_tool_results(messages)
1253
# if tool_trunc_saved:
1254
# saved_bytes += tool_trunc_saved
1255
# logs[
1256
# "tool_trunc"
1257
# ] = f"truncated oversized tool results (-{tool_trunc_saved} bytes)"
1258
1258
1259
1259
# ── Strip redundant tool_call fields ──
1260
1260
# tool_field_saved = _strip_redundant_tool_fields(messages)
@@ -485,11 +485,13 @@ async def async_iter_run_tools(
485
485
usage_dir.mkdir(parents=True, exist_ok=True)
486
486
if has_aiofile:
487
487
async with async_open(usage_file, "a") as f:
488
try:
489
async def write_usage():
490
await f.write(f"{json.dumps(usage)}\n")
488
491
489
async def write_usage():
490
await f.write(f"{json.dumps(usage)}\n")
491
492
asyncio.create_task(write_usage())
492
asyncio.create_task(write_usage())
493
except Exception as e:
494
debug.log(f"Failed to write usage asynchronously: {e}")
493
495
else:
494
496
with usage_file.open("a") as f:
495
497
json.dump(usage, f)