pygpt-net 2.5.93__py3-none-any.whl → 2.5.94__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.
Files changed (49) hide show
  1. pygpt_net/CHANGELOG.txt +8 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +6 -2
  4. pygpt_net/controller/chat/image.py +0 -3
  5. pygpt_net/controller/chat/response.py +5 -1
  6. pygpt_net/controller/config/field/slider.py +9 -5
  7. pygpt_net/controller/ctx/ctx.py +23 -18
  8. pygpt_net/controller/settings/editor.py +0 -6
  9. pygpt_net/controller/ui/tabs.py +2 -2
  10. pygpt_net/core/models/models.py +6 -1
  11. pygpt_net/core/render/web/body.py +67 -2
  12. pygpt_net/core/types/openai.py +14 -1
  13. pygpt_net/data/config/config.json +4 -4
  14. pygpt_net/data/config/models.json +203 -532
  15. pygpt_net/data/config/presets/agent_openai_b2b.json +54 -0
  16. pygpt_net/data/config/settings.json +16 -13
  17. pygpt_net/data/css/web-blocks.css +14 -0
  18. pygpt_net/data/css/web-blocks.dark.css +4 -0
  19. pygpt_net/data/css/web-blocks.light.css +4 -0
  20. pygpt_net/data/css/web-chatgpt.css +14 -0
  21. pygpt_net/data/css/web-chatgpt.dark.css +4 -0
  22. pygpt_net/data/css/web-chatgpt.light.css +4 -0
  23. pygpt_net/data/css/web-chatgpt_wide.css +14 -0
  24. pygpt_net/data/css/web-chatgpt_wide.dark.css +4 -0
  25. pygpt_net/data/css/web-chatgpt_wide.light.css +4 -0
  26. pygpt_net/data/locale/locale.de.ini +14 -0
  27. pygpt_net/data/locale/locale.en.ini +16 -0
  28. pygpt_net/data/locale/locale.es.ini +14 -0
  29. pygpt_net/data/locale/locale.fr.ini +14 -0
  30. pygpt_net/data/locale/locale.it.ini +14 -0
  31. pygpt_net/data/locale/locale.pl.ini +16 -1
  32. pygpt_net/data/locale/locale.uk.ini +14 -0
  33. pygpt_net/data/locale/locale.zh.ini +14 -0
  34. pygpt_net/item/model.py +6 -14
  35. pygpt_net/provider/agents/openai/agent_b2b.py +391 -0
  36. pygpt_net/provider/core/config/patch.py +19 -1
  37. pygpt_net/provider/core/model/patch.py +16 -1
  38. pygpt_net/provider/core/preset/patch.py +17 -0
  39. pygpt_net/provider/llms/hugging_face_router.py +132 -0
  40. pygpt_net/tools/code_interpreter/ui/html.py +2 -2
  41. pygpt_net/ui/dialog/image.py +0 -6
  42. pygpt_net/ui/widget/option/combo.py +2 -0
  43. pygpt_net/ui/widget/textarea/html.py +2 -2
  44. pygpt_net/ui/widget/textarea/web.py +3 -2
  45. {pygpt_net-2.5.93.dist-info → pygpt_net-2.5.94.dist-info}/METADATA +35 -26
  46. {pygpt_net-2.5.93.dist-info → pygpt_net-2.5.94.dist-info}/RECORD +49 -46
  47. {pygpt_net-2.5.93.dist-info → pygpt_net-2.5.94.dist-info}/LICENSE +0 -0
  48. {pygpt_net-2.5.93.dist-info → pygpt_net-2.5.94.dist-info}/WHEEL +0 -0
  49. {pygpt_net-2.5.93.dist-info → pygpt_net-2.5.94.dist-info}/entry_points.txt +0 -0
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,11 @@
1
+ 2.5.94 (2025-08-09)
2
+
3
+ - Added a new LLM provider: HuggingFace Router.
4
+ - Introduced a new model: gpt-oss (OpenAI open-source model available in HuggingFace and Ollama).
5
+ - Added a new agent mode in OpenAI Agents: Bot 2 Bot.
6
+ - Fixed: Storing the last used context ID when empty.
7
+ - Fixed: Reloading items when an agent run is stopped.
8
+
1
9
  2.5.93 (2025-08-08)
2
10
 
3
11
  - Added a new tool: Translate - in menu Tools - feature #123.
pygpt_net/__init__.py CHANGED
@@ -6,15 +6,15 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.08 00:00:00 #
9
+ # Updated Date: 2025.08.09 00:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2025, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.5.93"
17
- __build__ = "2025-08-08"
16
+ __version__ = "2.5.94"
17
+ __build__ = "2025-08-09"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
20
20
  __report__ = "https://github.com/szczyglis-dev/py-gpt/issues"
pygpt_net/app.py CHANGED
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.08 05:00:00 #
9
+ # Updated Date: 2025.08.09 01:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -16,7 +16,7 @@ import platform
16
16
 
17
17
  # disable warnings
18
18
  os.environ["TRANSFORMERS_NO_ADVISORY_WARNINGS"] = "1"
19
- os.environ["QT_LOGGING_RULES"] = "qt.multimedia.ffmpeg=false"
19
+ os.environ["QT_LOGGING_RULES"] = "qt.multimedia.ffmpeg=false;qt.qpa.fonts=false"
20
20
 
21
21
  if platform.system() == 'Windows':
22
22
  # fix ffmpeg bug: [SWR] Output channel layout "" is invalid or unsupported.
@@ -85,6 +85,7 @@ from pygpt_net.provider.agents.openai.agent_with_feedback import Agent as OpenAI
85
85
  from pygpt_net.provider.agents.openai.bot_researcher import Agent as OpenAIAgentBotResearcher
86
86
  from pygpt_net.provider.agents.openai.agent_planner import Agent as OpenAIAgentPlanner
87
87
  from pygpt_net.provider.agents.openai.evolve import Agent as OpenAIAgentsEvolve
88
+ from pygpt_net.provider.agents.openai.agent_b2b import Agent as OpenAIAgentsB2B
88
89
 
89
90
  # LLM wrapper providers (langchain, llama-index, embeddings)
90
91
  from pygpt_net.provider.llms.anthropic import AnthropicLLM
@@ -93,6 +94,7 @@ from pygpt_net.provider.llms.deepseek_api import DeepseekApiLLM
93
94
  from pygpt_net.provider.llms.google import GoogleLLM
94
95
  # from pygpt_net.provider.llms.hugging_face import HuggingFaceLLM
95
96
  from pygpt_net.provider.llms.hugging_face_api import HuggingFaceApiLLM
97
+ from pygpt_net.provider.llms.hugging_face_router import HuggingFaceRouterLLM
96
98
  from pygpt_net.provider.llms.local import LocalLLM
97
99
  from pygpt_net.provider.llms.mistral import MistralAILLM
98
100
  from pygpt_net.provider.llms.ollama import OllamaLLM
@@ -390,6 +392,7 @@ def run(**kwargs):
390
392
  launcher.add_llm(GoogleLLM())
391
393
  # launcher.add_llm(HuggingFaceLLM())
392
394
  launcher.add_llm(HuggingFaceApiLLM())
395
+ launcher.add_llm(HuggingFaceRouterLLM())
393
396
  launcher.add_llm(LocalLLM())
394
397
  launcher.add_llm(MistralAILLM())
395
398
  launcher.add_llm(OllamaLLM())
@@ -430,6 +433,7 @@ def run(**kwargs):
430
433
  launcher.add_agent(OpenAIAgentBotResearcher()) # openai-agents
431
434
  launcher.add_agent(OpenAIAgentsExpertsFeedback()) # openai-agents
432
435
  launcher.add_agent(OpenAIAgentsEvolve()) # openai-agents
436
+ launcher.add_agent(OpenAIAgentsB2B()) # openai-agents
433
437
 
434
438
  # register custom agents
435
439
  agents = kwargs.get('agents', None)
@@ -149,9 +149,6 @@ class Image:
149
149
  string += "[{}]({})".format(basename, path) + "\n"
150
150
  i += 1
151
151
 
152
- if self.window.core.config.get('img_dialog_open'):
153
- self.window.tools.get("viewer").open_images(paths) # use viewer tool
154
-
155
152
  if not self.window.core.config.get('img_raw'):
156
153
  string += "\nPrompt: "
157
154
  string += prompt
@@ -19,7 +19,7 @@ from pygpt_net.core.types import (
19
19
  MODE_CHAT,
20
20
  )
21
21
  from pygpt_net.core.bridge.context import BridgeContext
22
- from pygpt_net.core.events import RenderEvent, KernelEvent
22
+ from pygpt_net.core.events import RenderEvent, KernelEvent, AppEvent
23
23
  from pygpt_net.item.ctx import CtxItem
24
24
  from pygpt_net.utils import trans
25
25
 
@@ -172,6 +172,10 @@ class Response:
172
172
  ctx.msg_id = None
173
173
  self.window.core.ctx.add(ctx) # store context to prevent current output from being lost
174
174
  self.window.controller.ctx.prepare_name(ctx) # summarize if not yet
175
+
176
+ # finish render
177
+ self.window.dispatch(AppEvent(AppEvent.CTX_END)) # app event
178
+ self.window.dispatch(RenderEvent(RenderEvent.RELOAD)) # reload chat window
175
179
  return
176
180
 
177
181
  # at first, handle previous context (user input) if not handled yet
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.06.29 18:00:00 #
9
+ # Updated Date: 2025.08.08 21:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any, Optional, Dict, Union
@@ -65,7 +65,8 @@ class Slider:
65
65
  value = option["max"]
66
66
 
67
67
  # update connected input field
68
- self.window.ui.config[parent_id][key].input.setText(str(value))
68
+ if parent_id in self.window.ui.config and key in self.window.ui.config[parent_id]:
69
+ self.window.ui.config[parent_id][key].input.setText(str(value))
69
70
 
70
71
  slider_value = round(float(value) * multiplier, 0)
71
72
 
@@ -83,12 +84,15 @@ class Slider:
83
84
  slider_value = option["min"] * multiplier
84
85
  elif "max" in option and slider_value > option["max"] * multiplier:
85
86
  slider_value = option["max"] * multiplier
86
- self.window.ui.config[parent_id][key].slider.setValue(slider_value)
87
+
88
+ if parent_id in self.window.ui.config and key in self.window.ui.config[parent_id]:
89
+ self.window.ui.config[parent_id][key].slider.setValue(slider_value)
87
90
 
88
91
  # from value
89
92
  else:
90
- self.window.ui.config[parent_id][key].input.setText(str(value))
91
- self.window.ui.config[parent_id][key].slider.setValue(slider_value)
93
+ if parent_id in self.window.ui.config and key in self.window.ui.config[parent_id]:
94
+ self.window.ui.config[parent_id][key].input.setText(str(value))
95
+ self.window.ui.config[parent_id][key].slider.setValue(slider_value)
92
96
 
93
97
  def on_update(
94
98
  self,
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.07 03:00:00 #
9
+ # Updated Date: 2025.08.08 23:00:00 #
10
10
  # ================================================== #
11
11
  import gc
12
12
  from typing import Optional, List
@@ -15,7 +15,7 @@ from PySide6.QtCore import QModelIndex, QTimer
15
15
  from PySide6.QtGui import QStandardItem
16
16
 
17
17
  from pygpt_net.core.events import Event, AppEvent, RenderEvent
18
- from pygpt_net.item.ctx import CtxItem
18
+ from pygpt_net.item.ctx import CtxItem, CtxMeta
19
19
 
20
20
  from .common import Common
21
21
  from .summarizer import Summarizer
@@ -283,12 +283,7 @@ class Ctx:
283
283
  self.window.core.config.set('assistant_thread', None) # reset assistant thread id
284
284
  self.update()
285
285
 
286
- # render reset
287
- data = {
288
- "meta": meta,
289
- }
290
- event = RenderEvent(RenderEvent.FRESH, data)
291
- self.window.dispatch(event)
286
+ self.fresh_output(meta) # render reset
292
287
 
293
288
  if not force: # only if real click on new context button
294
289
  self.window.controller.chat.common.unlock_input()
@@ -407,16 +402,7 @@ class Ctx:
407
402
 
408
403
  # reset appended data / prepare new ctx
409
404
  if meta is not None:
410
- data = {
411
- "meta": meta,
412
- }
413
- event = RenderEvent(RenderEvent.FRESH, data)
414
- self.window.dispatch(event)
415
- data = {
416
- "meta": meta,
417
- }
418
- event = RenderEvent(RenderEvent.ON_LOAD, data)
419
- self.window.dispatch(event)
405
+ self.fresh_output(meta) # render reset
420
406
 
421
407
  self.reload_config()
422
408
 
@@ -1244,3 +1230,22 @@ class Ctx:
1244
1230
  def clear_selected(self):
1245
1231
  """Clear selected list"""
1246
1232
  self.selected = []
1233
+
1234
+
1235
+ def fresh_output(self, meta: CtxMeta):
1236
+ """
1237
+ Fresh output for new context
1238
+
1239
+ :param meta: CtxItem
1240
+ """
1241
+ # render reset
1242
+ data = {
1243
+ "meta": meta,
1244
+ }
1245
+ event = RenderEvent(RenderEvent.FRESH, data)
1246
+ self.window.dispatch(event)
1247
+ data = {
1248
+ "meta": meta,
1249
+ }
1250
+ event = RenderEvent(RenderEvent.ON_LOAD, data)
1251
+ self.window.dispatch(event)
@@ -60,7 +60,6 @@ class Editor:
60
60
  self.window.ui.add_hook("update.config.ctx.records.folders.top", self.hook_update)
61
61
  self.window.ui.add_hook("update.config.layout.density", self.hook_update)
62
62
  self.window.ui.add_hook("update.config.layout.tooltips", self.hook_update)
63
- self.window.ui.add_hook("update.config.img_dialog_open", self.hook_update)
64
63
  self.window.ui.add_hook("update.config.access.voice_control", self.hook_update)
65
64
  self.window.ui.add_hook("update.config.debug", self.hook_update)
66
65
  self.window.ui.add_hook("update.config.notepad.num", self.hook_update)
@@ -327,11 +326,6 @@ class Editor:
327
326
  self.window.controller.theme.reload()
328
327
  self.window.controller.theme.menu.update_density()
329
328
 
330
- # toggle image dialog auto-open
331
- elif key == "img_dialog_open":
332
- self.window.core.config.set(key, value)
333
- self.window.ui.nodes['dialog.image.open.toggle'].setChecked(value)
334
-
335
329
  # debug: menu
336
330
  elif key == "debug":
337
331
  self.window.core.config.set(key, value)
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.07 18:00:00 #
9
+ # Updated Date: 2025.08.08 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Any, Optional, Tuple
@@ -614,7 +614,7 @@ class Tabs:
614
614
  :param name: new title
615
615
  :param close: close dialog
616
616
  """
617
- self.window.core.tabs.update_title(idx, name)
617
+ self.window.core.tabs.update_title(idx, name, name)
618
618
  if close:
619
619
  self.window.ui.dialog['rename'].close()
620
620
  self.debug()
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.07.19 00:00:00 #
9
+ # Updated Date: 2025.08.08 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -527,6 +527,11 @@ class Models:
527
527
  args["api_key"] = self.window.core.config.get('api_key_mistral', "")
528
528
  args["base_url"] = self.window.core.config.get('api_endpoint_mistral', "")
529
529
  self.window.core.debug.info("[api] Using client: Mistral AI API")
530
+ # HuggingFace Router
531
+ elif model.provider == "huggingface_router":
532
+ args["api_key"] = self.window.core.config.get('api_key_hugging_face', "")
533
+ args["base_url"] = self.window.core.config.get('api_endpoint_hugging_face', "")
534
+ self.window.core.debug.info("[api] Using client: HuggingFace Router API")
530
535
  else:
531
536
  self.window.core.debug.info("[api] Using client: OpenAI (default)")
532
537
 
@@ -6,10 +6,11 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.05 00:00:00 #
9
+ # Updated Date: 2025.08.08 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
+ import random
13
14
  from typing import Optional, List, Dict
14
15
 
15
16
  from pygpt_net.core.events import Event
@@ -24,6 +25,8 @@ import pygpt_net.fonts_rc
24
25
 
25
26
  class Body:
26
27
 
28
+ NUM_TIPS = 13
29
+
27
30
  def __init__(self, window=None):
28
31
  """
29
32
  HTML Body
@@ -402,12 +405,28 @@ class Body:
402
405
  html += "</div>"
403
406
  return html
404
407
 
408
+ def get_all_tips(self) -> str:
409
+ """
410
+ Generuje listę wszystkich tipów jako elementy HTML,
411
+ tasuje je i zwraca jako string JSON.
412
+ """
413
+ if not self.window.core.config.get("layout.tooltips", False):
414
+ return "[]"
415
+ tips_list = []
416
+ for i in range(1, self.NUM_TIPS + 1):
417
+ tip_html = "<p><b>" + trans("output.tips.prefix") + "</b>: " + trans("output.tips." + str(i)) + "</p>"
418
+ tips_list.append(tip_html)
419
+ random.shuffle(tips_list)
420
+ import json
421
+ return json.dumps(tips_list)
422
+
405
423
  def get_html(self, pid: int) -> str:
406
424
  """
407
425
  Build webview HTML code
408
426
 
409
427
  :return: HTML code
410
428
  """
429
+ tips_json = self.get_all_tips()
411
430
  classes = []
412
431
  classes_str = ""
413
432
  style = self.window.core.config.get("theme.style", "blocks")
@@ -449,6 +468,8 @@ class Body:
449
468
  let domLastCodeBlock = null;
450
469
  let domLastParagraphBlock = null;
451
470
  let htmlBuffer = "";
471
+ let tips = """ + tips_json + """;
472
+ let tips_hidden = false;
452
473
 
453
474
  history.scrollRestoration = "manual";
454
475
  document.addEventListener('keydown', function(event) {
@@ -473,6 +494,7 @@ class Body:
473
494
  }
474
495
  function prepare() {
475
496
  collapsed_idx = []; // clear collapsed code
497
+ hideTips();
476
498
  }
477
499
  function sanitize(content) {
478
500
  var parser = new DOMParser();
@@ -494,6 +516,37 @@ class Body:
494
516
  }
495
517
  restoreCollapsedCode();
496
518
  }
519
+ function hideTips() {
520
+ if (tips_hidden) return;
521
+ document.getElementById('tips').style.display = 'none';
522
+ tips_hidden = true;
523
+ }
524
+ function showTips() {
525
+ if (tips_hidden) return;
526
+ if (tips.length === 0) return;
527
+ document.getElementById('tips').style.display = 'block';
528
+ tips_hidden = false;
529
+ }
530
+ function cycleTips() {
531
+ if (tips_hidden) return;
532
+ if (tips.length === 0) return;
533
+ let tipContainer = document.getElementById('tips');
534
+ let currentTip = 0;
535
+ function showNextTip() {
536
+ if (tips_hidden) return;
537
+ tipContainer.innerHTML = tips[currentTip];
538
+ tipContainer.classList.add('visible');
539
+ setTimeout(function() {
540
+ if (tips_hidden) return;
541
+ tipContainer.classList.remove('visible');
542
+ setTimeout(function(){
543
+ currentTip = (currentTip + 1) % tips.length;
544
+ showNextTip();
545
+ }, 1000);
546
+ }, 10000);
547
+ }
548
+ showNextTip();
549
+ }
497
550
  function renderMath() {
498
551
  const scripts = document.querySelectorAll('script[type^="math/tex"]');
499
552
  scripts.forEach(function(script) {
@@ -525,6 +578,7 @@ class Body:
525
578
  scrollToBottom();
526
579
  }
527
580
  function appendToOutput(bot_name, content) {
581
+ hideTips();
528
582
  const element = document.getElementById('_append_output_');
529
583
  if (element) {
530
584
  let box = element.querySelector('.msg-box');
@@ -564,6 +618,7 @@ class Body:
564
618
  scrollToBottom();
565
619
  }
566
620
  function appendExtra(id, content) {
621
+ hideTips();
567
622
  prevScroll = 0;
568
623
  const element = document.getElementById('msg-bot-' + id);
569
624
  if (element) {
@@ -619,6 +674,7 @@ class Body:
619
674
  return element;
620
675
  }
621
676
  function clearStream() {
677
+ hideTips();
622
678
  domLastParagraphBlock = null;
623
679
  domLastCodeBlock = null;
624
680
  domOutputStream = null;
@@ -649,12 +705,14 @@ class Body:
649
705
  }
650
706
  }
651
707
  function beginStream() {
708
+ hideTips();
652
709
  clearOutput();
653
710
  }
654
711
  function endStream() {
655
712
  clearOutput();
656
713
  }
657
714
  function appendStream(bot_name, content, chunk, replace = false, is_code_block = false) {
715
+ hideTips();
658
716
  const element = getStreamContainer();
659
717
  doHighlight = true;
660
718
  doMath = true;
@@ -742,6 +800,7 @@ class Body:
742
800
  }
743
801
  }
744
802
  function replaceOutput(bot_name, content) {
803
+ hideTips();
745
804
  const element = getStreamContainer();
746
805
  if (element) {
747
806
  let box = element.querySelector('.msg-box');
@@ -770,6 +829,7 @@ class Body:
770
829
  scrollToBottom();
771
830
  }
772
831
  function nextStream() {
832
+ hideTips();
773
833
  // Clear the current stream output and copy it to the before output
774
834
  // 1. copy current output from _append_output_ to _append_output_before_
775
835
  // 2. clear _append_output_
@@ -784,12 +844,14 @@ class Body:
784
844
  }
785
845
  }
786
846
  function clearStreamBefore() {
847
+ hideTips();
787
848
  const element = document.getElementById('_append_output_before_');
788
849
  if (element) {
789
850
  element.innerHTML = ''; // clear previous content
790
851
  }
791
852
  }
792
- function replaceOutput(bot_name, content) {
853
+ function replaceOutput(bot_name, content) {
854
+ hideTips();
793
855
  const element = getStreamContainer();
794
856
  if (element) {
795
857
  let box = element.querySelector('.msg-box');
@@ -1074,6 +1136,7 @@ class Body:
1074
1136
  prevScroll = parseInt(pos);
1075
1137
  }
1076
1138
  function showLoading() {
1139
+ hideTips();
1077
1140
  const el = document.getElementById('_loader_');
1078
1141
  if (el) {
1079
1142
  if (el.classList.contains('hidden')) {
@@ -1196,6 +1259,7 @@ class Body:
1196
1259
  }
1197
1260
  });
1198
1261
  });
1262
+ setTimeout(cycleTips, 20000);
1199
1263
  </script>
1200
1264
  </head>
1201
1265
  <body """ + classes_str + """>
@@ -1209,6 +1273,7 @@ class Body:
1209
1273
  <div id="_loader_" class="loader-global hidden">
1210
1274
  <div class="lds-ring"><div></div><div></div><div></div><div></div></div>
1211
1275
  </div>
1276
+ <div id="tips" class="tips"></div>
1212
1277
  </div>
1213
1278
  </body>
1214
1279
  </html>
@@ -6,9 +6,22 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.03 14:00:00 #
9
+ # Updated Date: 2025.08.08 19:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ OPENAI_COMPATIBLE_PROVIDERS = [
13
+ "anthropic",
14
+ "openai",
15
+ "azure_openai",
16
+ "google",
17
+ "huggingface_router",
18
+ "local_ai",
19
+ "mistral_ai",
20
+ "perplexity",
21
+ "deepseek_api",
22
+ "x_ai",
23
+ ]
24
+
12
25
  OPENAI_DISABLE_TOOLS = [
13
26
  "o1-mini",
14
27
  "o1-preview"
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.5.93",
4
- "app.version": "2.5.93",
5
- "updated_at": "2025-08-08T00:00:00"
3
+ "version": "2.5.94",
4
+ "app.version": "2.5.94",
5
+ "updated_at": "2025-08-09T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
8
8
  "access.audio.event.speech.disabled": [],
@@ -71,6 +71,7 @@
71
71
  "api_endpoint_xai": "https://api.x.ai/v1",
72
72
  "api_endpoint_anthropic": "https://api.anthropic.com/v1",
73
73
  "api_endpoint_mistral": "https://api.mistral.ai/v1",
74
+ "api_endpoint_hugging_face": "https://router.huggingface.co/v1",
74
75
  "api_key": "",
75
76
  "api_key_google": "",
76
77
  "api_key_anthropic": "",
@@ -182,7 +183,6 @@
182
183
  "font_size.toolbox": 12,
183
184
  "func_call.native": true,
184
185
  "frequency_penalty": 0.0,
185
- "img_dialog_open": false,
186
186
  "img_prompt_model": "gpt-4o",
187
187
  "img_raw": true,
188
188
  "img_resolution": "1792x1024",