返回提交历史
Modified
docker/update.sh
+1
-1
Modified
g4f/Provider/needs_auth/PuterJS.py
+25
-14
Modified
g4f/gui/server/website.py
+4
-4
XFEstudio/gpt4free
Update PuterJS
e18297f3
代码差异
3 个文件
+30
-19
@@ -5,7 +5,7 @@ do
5
5
python -m etc.tool.update
6
6
sleep 600
7
7
done
8
echo "I have broken out of the interminably long for loop"
8
echo "STOPPED."
9
9
trap - INT
10
10
sleep 1
11
11
echo "END."
@@ -11,6 +11,7 @@ from ...providers.response import FinishReason, Usage, Reasoning, ToolCalls
11
11
from ...tools.media import render_messages
12
12
from ...requests import see_stream, raise_for_status
13
13
from ...errors import ResponseError, ModelNotFoundError, MissingAuthError
14
from ..helper import format_media_prompt
14
15
from .. import debug
15
16
16
17
class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
@@ -263,11 +264,13 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
263
264
try:
264
265
url = "https://api.puter.com/puterai/chat/models/"
265
266
cls.models = requests.get(url).json().get("models", [])
266
cls.models = [model for model in cls.models if model not in ["abuse", "costly", "fake"]]
267
cls.models = [model for model in cls.models if "/" not in model and model not in ["abuse", "costly", "fake", "model-fallback-test-1"]]
267
268
except Exception as e:
268
269
debug.log(f"PuterJS: Failed to fetch models from API: {e}")
269
270
cls.models = []
270
271
cls.models += [model for model in cls.model_aliases.keys() if model not in cls.models]
272
openrouter_models = [model for model in cls.models if "openrouter:" in model]
273
cls.models = [model for model in cls.models if model not in openrouter_models] + openrouter_models
271
274
cls.vision_models = []
272
275
for model in cls.models:
273
276
for tag in ["vision", "multimodal", "gpt", "o1", "o3", "o4"]:
@@ -325,6 +328,7 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
325
328
cls,
326
329
model: str,
327
330
messages: Messages,
331
prompt: str = None,
328
332
proxy: str = None,
329
333
stream: bool = True,
330
334
api_key: str = None,
@@ -334,6 +338,9 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
334
338
if not api_key:
335
339
raise MissingAuthError("API key is required for Puter.js API")
336
340
341
if not cls.models:
342
cls.get_models()
343
337
344
# Check if we need to use a vision model
338
345
if not model and media is not None and len(media) > 0:
339
346
model = cls.default_vision_model
@@ -375,11 +382,11 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
375
382
driver = cls.get_driver_for_model(model)
376
383
377
384
json_data = {
378
"interface": "puter-chat-completion",
385
"interface": "puter-image-generation" if model in cls.image_models else "puter-chat-completion",
379
386
"driver": driver,
380
"test_mode": False,
381
"method": "complete",
382
"args": {
387
"test_mode": messages[0]["content"] == "test",
388
"method": "generate" if model in cls.image_models else "complete",
389
"args": {"prompt": format_media_prompt(messages, prompt)} if model in cls.image_models else {
383
390
"messages": list(render_messages(messages, media)),
384
391
"model": model,
385
392
"stream": stream,
@@ -402,25 +409,26 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
402
409
async for result in see_stream(response.content):
403
410
if "error" in result:
404
411
raise ResponseError(result["error"].get("message", result["error"]))
405
if result.get("usage") is not None:
406
yield Usage(**result["usage"])
407
412
choices = result.get("choices", [{}])
408
413
choice = choices.pop() if choices else {}
409
414
content = choice.get("delta", {}).get("content")
410
if content:
411
yield content
412
tool_calls = choice.get("delta", {}).get("tool_calls")
413
if tool_calls:
414
yield ToolCalls(choice["delta"]["tool_calls"])
415
415
reasoning_content = choice.get("delta", {}).get("reasoning_content")
416
416
if reasoning_content:
417
417
reasoning = True
418
418
yield Reasoning(reasoning_content)
419
elif content:
420
if reasoning:
421
yield Reasoning(status="")
422
reasoning = False
423
yield content
424
if result.get("usage") is not None:
425
yield Usage(**result["usage"])
426
tool_calls = choice.get("delta", {}).get("tool_calls")
427
if tool_calls:
428
yield ToolCalls(choice["delta"]["tool_calls"])
419
429
finish_reason = choice.get("finish_reason")
420
430
if finish_reason:
421
431
yield FinishReason(finish_reason)
422
if reasoning:
423
yield Reasoning(status="Done")
424
432
elif mime_type.startswith("application/json"):
425
433
result = await response.json()
426
434
if "choices" in result:
@@ -430,6 +438,9 @@ class PuterJS(AsyncGeneratorProvider, ProviderModelMixin):
430
438
else:
431
439
raise ResponseError(result)
432
440
message = choice.get("message", {})
441
reasoning_content = message.get("reasoning_content")
442
if reasoning_content:
443
yield Reasoning(reasoning_content)
433
444
content = message.get("content", "")
434
445
if isinstance(content, list):
435
446
for item in content:
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
import os
4
4
import requests
5
5
from datetime import datetime
6
from flask import send_from_directory, redirect
6
from flask import send_from_directory, redirect, request
7
7
8
8
from ...image.copy_images import secure_filename
9
9
from ...cookies import get_cookies_dir
@@ -15,7 +15,7 @@ def redirect_home():
15
15
return redirect('/chat/')
16
16
17
17
def render(filename = "chat"):
18
if os.path.exists(DIST_DIR):
18
if os.path.exists(DIST_DIR) and not request.args.get("debug"):
19
19
path = os.path.abspath(os.path.join(os.path.dirname(DIST_DIR), (filename + ("" if "." in filename else ".html"))))
20
20
return send_from_directory(os.path.dirname(path), os.path.basename(path))
21
21
try:
@@ -24,7 +24,7 @@ def render(filename = "chat"):
24
24
latest_version = version.utils.current_version
25
25
today = datetime.today().strftime('%Y-%m-%d')
26
26
cache_dir = os.path.join(get_cookies_dir(), ".gui_cache")
27
cache_file = os.path.join(cache_dir, f"{filename}.{today}.{secure_filename(f'{version.utils.current_version}-{latest_version}')}.html")
27
cache_file = os.path.join(cache_dir, f"{secure_filename(filename)}.{today}.{secure_filename(f'{version.utils.current_version}-{latest_version}')}.html")
28
28
is_temp = False
29
29
if not os.path.exists(cache_file):
30
30
if os.access(cache_file, os.W_OK):
@@ -36,7 +36,7 @@ def render(filename = "chat"):
36
36
found = None
37
37
for root, _, files in os.walk(cache_dir):
38
38
for file in files:
39
if file.startswith(filename):
39
if file.startswith(secure_filename(filename)):
40
40
found = os.path.abspath(root), file
41
41
break
42
42
if found: