pygpt-net 2.7.5__py3-none-any.whl → 2.7.6__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 (51) hide show
  1. pygpt_net/CHANGELOG.txt +8 -0
  2. pygpt_net/__init__.py +2 -2
  3. pygpt_net/controller/chat/handler/worker.py +9 -31
  4. pygpt_net/controller/chat/handler/xai_stream.py +621 -52
  5. pygpt_net/controller/debug/fixtures.py +3 -2
  6. pygpt_net/controller/files/files.py +65 -4
  7. pygpt_net/core/filesystem/url.py +4 -1
  8. pygpt_net/core/render/web/body.py +3 -2
  9. pygpt_net/core/types/chunk.py +27 -0
  10. pygpt_net/data/config/config.json +2 -2
  11. pygpt_net/data/config/models.json +2 -2
  12. pygpt_net/data/config/settings.json +1 -1
  13. pygpt_net/data/js/app/template.js +1 -1
  14. pygpt_net/data/js/app.min.js +2 -2
  15. pygpt_net/data/locale/locale.de.ini +3 -0
  16. pygpt_net/data/locale/locale.en.ini +3 -0
  17. pygpt_net/data/locale/locale.es.ini +3 -0
  18. pygpt_net/data/locale/locale.fr.ini +3 -0
  19. pygpt_net/data/locale/locale.it.ini +3 -0
  20. pygpt_net/data/locale/locale.pl.ini +3 -0
  21. pygpt_net/data/locale/locale.uk.ini +3 -0
  22. pygpt_net/data/locale/locale.zh.ini +3 -0
  23. pygpt_net/data/locale/plugin.cmd_mouse_control.en.ini +2 -2
  24. pygpt_net/item/ctx.py +3 -5
  25. pygpt_net/js_rc.py +2449 -2447
  26. pygpt_net/plugin/cmd_mouse_control/config.py +8 -7
  27. pygpt_net/plugin/cmd_mouse_control/plugin.py +3 -4
  28. pygpt_net/provider/api/anthropic/__init__.py +10 -8
  29. pygpt_net/provider/api/google/__init__.py +6 -5
  30. pygpt_net/provider/api/google/chat.py +1 -2
  31. pygpt_net/provider/api/openai/__init__.py +7 -3
  32. pygpt_net/provider/api/openai/responses.py +0 -0
  33. pygpt_net/provider/api/x_ai/__init__.py +10 -9
  34. pygpt_net/provider/api/x_ai/chat.py +272 -102
  35. pygpt_net/tools/image_viewer/ui/dialogs.py +298 -12
  36. pygpt_net/tools/text_editor/ui/widgets.py +5 -1
  37. pygpt_net/ui/base/context_menu.py +44 -1
  38. pygpt_net/ui/layout/toolbox/indexes.py +22 -19
  39. pygpt_net/ui/layout/toolbox/model.py +28 -5
  40. pygpt_net/ui/widget/image/display.py +25 -8
  41. pygpt_net/ui/widget/tabs/output.py +9 -1
  42. pygpt_net/ui/widget/textarea/editor.py +14 -1
  43. pygpt_net/ui/widget/textarea/input.py +20 -7
  44. pygpt_net/ui/widget/textarea/notepad.py +24 -1
  45. pygpt_net/ui/widget/textarea/output.py +23 -1
  46. pygpt_net/ui/widget/textarea/web.py +16 -1
  47. {pygpt_net-2.7.5.dist-info → pygpt_net-2.7.6.dist-info}/METADATA +10 -2
  48. {pygpt_net-2.7.5.dist-info → pygpt_net-2.7.6.dist-info}/RECORD +50 -49
  49. {pygpt_net-2.7.5.dist-info → pygpt_net-2.7.6.dist-info}/LICENSE +0 -0
  50. {pygpt_net-2.7.5.dist-info → pygpt_net-2.7.6.dist-info}/WHEEL +0 -0
  51. {pygpt_net-2.7.5.dist-info → pygpt_net-2.7.6.dist-info}/entry_points.txt +0 -0
@@ -6,13 +6,14 @@
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.09.12 20:00:00 #
9
+ # Updated Date: 2026.01.03 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
  from typing import Iterable
14
14
 
15
15
  from pygpt_net.core.fixtures.stream.generator import FakeOpenAIStream
16
+ from pygpt_net.core.types.chunk import ChunkType
16
17
  from pygpt_net.item.ctx import CtxItem
17
18
 
18
19
 
@@ -83,7 +84,7 @@ class Fixtures:
83
84
  :param ctx: context item
84
85
  :return: stream generator
85
86
  """
86
- ctx.use_responses_api = False
87
+ ctx.chunk_type = ChunkType.API_CHAT
87
88
  path = os.path.join(self.window.core.config.get_app_path(), "data", "fixtures", "fake_stream.txt")
88
89
  return FakeOpenAIStream(code_path=path).stream(
89
90
  api="raw",
@@ -1,3 +1,5 @@
1
+ # controller/files.py
2
+
1
3
  #!/usr/bin/env python3
2
4
  # -*- coding: utf-8 -*-
3
5
  # ================================================== #
@@ -6,7 +8,7 @@
6
8
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
9
  # MIT License #
8
10
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.12.31 17:00:00 #
11
+ # Updated Date: 2026.01.03 00:00:00 #
10
12
  # ================================================== #
11
13
 
12
14
  import datetime
@@ -203,14 +205,73 @@ class Files:
203
205
 
204
206
  def download_local(self, path: Union[str, list]):
205
207
  """
206
- Download (copy) file or directory to local filesystem
208
+ Download (copy) file or directory to local filesystem.
207
209
 
208
- :param path: path to source file or list of files
210
+ Behavior:
211
+ - Single selection: unchanged, prompts Save As dialog per current implementation.
212
+ - Multi selection (>1 item): prompts once for a target directory and copies all selected items there.
213
+ In case of name collision in the target directory, a timestamp prefix is added to the copied name.
209
214
  """
215
+ # Multi-selection: choose a directory once and copy all into it
210
216
  if isinstance(path, list):
217
+ # Normalize incoming list (decode, map to workdir)
218
+ norm_paths = []
211
219
  for p in path:
212
- self.download_local(p)
220
+ try:
221
+ p_norm = self.window.core.filesystem.to_workdir(unquote(p))
222
+ except Exception:
223
+ p_norm = p
224
+ if p_norm:
225
+ norm_paths.append(p_norm)
226
+
227
+ if not norm_paths:
228
+ return
229
+
230
+ if len(norm_paths) == 1:
231
+ # Defer to single-item path handling
232
+ self.download_local(norm_paths[0])
233
+ return
234
+
235
+ last_dir = self.window.core.config.get_last_used_dir()
236
+ target_dir = QFileDialog.getExistingDirectory(
237
+ self.window,
238
+ "Select target directory",
239
+ last_dir if last_dir else os.path.expanduser("~"),
240
+ )
241
+ if not target_dir:
242
+ return
243
+
244
+ # Remember last used directory
245
+ self.window.core.config.set_last_used_dir(target_dir)
246
+
247
+ copied = 0
248
+
249
+ for src in norm_paths:
250
+ try:
251
+ if not os.path.exists(src):
252
+ continue
253
+
254
+ base_name = os.path.basename(src.rstrip(os.sep))
255
+ dst = os.path.join(target_dir, base_name)
256
+
257
+ # Avoid copying into itself and handle name collisions
258
+ if os.path.abspath(dst) == os.path.abspath(src) or os.path.exists(dst):
259
+ dst = os.path.join(target_dir, f"{self.make_ts_prefix()}_{base_name}")
260
+
261
+ if os.path.isdir(src):
262
+ shutil.copytree(src, dst)
263
+ else:
264
+ copy2(src, dst)
265
+ copied += 1
266
+ except Exception as e:
267
+ self.window.core.debug.log(e)
268
+ print(f"Error downloading item: {src} -> {target_dir} - {e}")
269
+
270
+ if copied > 0:
271
+ self.window.update_status(f"[OK] Downloaded: {copied} items to: {target_dir}")
213
272
  return
273
+
274
+ # Single-item flow (unchanged)
214
275
  path = self.window.core.filesystem.to_workdir(unquote(path))
215
276
  last_dir = self.window.core.config.get_last_used_dir()
216
277
  dialog = QFileDialog(self.window)
@@ -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.12.31 16:00:00 #
9
+ # Updated Date: 2026.01.03 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from PySide6.QtCore import QUrl
@@ -47,6 +47,9 @@ class Url:
47
47
  elif url.toString().startswith('bridge://play_video/'):
48
48
  self.window.controller.media.play_video(url.toString().replace("bridge://play_video/", ""))
49
49
  return
50
+ elif url.toString().startswith('bridge://open_image/'):
51
+ self.window.tools.get("viewer").open_preview(url.toString().replace("bridge://open_image/", ""))
52
+ return
50
53
  elif url.toString().startswith('bridge://download/'):
51
54
  self.window.controller.files.download_local(url.toString().replace("bridge://download/", ""))
52
55
  return
@@ -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.09.13 06:05:00 #
9
+ # Updated Date: 2026.01.03 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
@@ -410,7 +410,8 @@ class Body:
410
410
  <p><a href="bridge://play_video/{url}" class="title">{elide_filename(basename)}</a></p>
411
411
  </div>
412
412
  '''
413
- return f'<div class="extra-src-img-box" title="{url}"><div class="img-outer"><div class="img-wrapper"><a href="{url}"><img src="{path}" class="image"></a></div><a href="{url}" class="title">{elide_filename(basename)}</a></div></div><br/>'
413
+ url_preview = f"bridge://open_image/{url}"
414
+ return f'<div class="extra-src-img-box" title="{url}"><div class="img-outer"><div class="img-wrapper"><a href="{url_preview}"><img src="{path}" class="image"></a></div><a href="{url}" class="title">{elide_filename(basename)}</a></div></div><br/>'
414
415
 
415
416
  def get_url_html(
416
417
  self,
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ # ================================================== #
4
+ # This file is a part of PYGPT package #
5
+ # Website: https://pygpt.net #
6
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
+ # MIT License #
8
+ # Created By : Marcin Szczygliński #
9
+ # Updated Date: 2026.01.03 17:00:00 #
10
+ # ================================================== #
11
+
12
+ from enum import Enum
13
+
14
+ class ChunkType(str, Enum):
15
+ """
16
+ Enum for chunk type classification.
17
+ """
18
+ API_CHAT = "api_chat" # OpenAI Chat Completions / or compatible
19
+ API_CHAT_RESPONSES = "api_chat_responses" # OpenAI Responses
20
+ API_COMPLETION = "api_completion" # OpenAI Completions
21
+ LANGCHAIN_CHAT = "langchain_chat" # LangChain chat (deprecated)
22
+ LLAMA_CHAT = "llama_chat" # LlamaIndex chat
23
+ GOOGLE = "google" # Google SDK
24
+ GOOGLE_INTERACTIONS_API = "api_google_interactions" # Google SDK, deep research - interactions API
25
+ ANTHROPIC = "anthropic" # Anthropic SDK
26
+ XAI_SDK = "xai_sdk" # xAI SDK
27
+ RAW = "raw" # Raw string fallback
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.7.5",
4
- "app.version": "2.7.5",
3
+ "version": "2.7.6",
4
+ "app.version": "2.7.6",
5
5
  "updated_at": "2026-01-03T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.7.5",
4
- "app.version": "2.7.5",
3
+ "version": "2.7.6",
4
+ "app.version": "2.7.6",
5
5
  "updated_at": "2026-01-03T00:00:00"
6
6
  },
7
7
  "items": {
@@ -2032,7 +2032,7 @@
2032
2032
  "advanced": false,
2033
2033
  "tab": "Google",
2034
2034
  "urls": {
2035
- "Google Docs": "https://ai.google.dev/gemini-api/docs/file-search?hl=pl#metadata"
2035
+ "Google Docs": "https://ai.google.dev/gemini-api/docs/file-search#metadata"
2036
2036
  }
2037
2037
  },
2038
2038
  "remote_tools.anthropic.web_search": {
@@ -91,7 +91,7 @@ class NodeTemplateEngine {
91
91
  } else {
92
92
  parts.push(
93
93
  `<div class="extra-src-img-box" title="${url}">` +
94
- `<div class="img-outer"><div class="img-wrapper"><a href="${url}"><img src="${path}" class="image"></a></div>` +
94
+ `<div class="img-outer"><div class="img-wrapper"><a href="bridge://open_image/${path}"><img src="${path}" class="image"></a></div>` +
95
95
  `<a href="${url}" class="title">${this._escapeHtml(bn)}</a></div>` +
96
96
  `</div><br/>`
97
97
  );
@@ -1,4 +1,4 @@
1
- /* app.min.js — generated on 2025-09-28 09:12:33 by bin/minify_js.py using rjsmin */
1
+ /* app.min.js — generated on 2026-01-03 18:07:50 by bin/minify_js.py using rjsmin */
2
2
 
3
3
  /* data/js/app/async.js */
4
4
  class AsyncRunner{constructor(cfg,raf){this.cfg=cfg||{};this.raf=raf||null;const A=this.cfg.ASYNC||{};this.SLICE_MS=Utils.g('ASYNC_SLICE_MS',A.SLICE_MS??12);this.SLICE_HIDDEN_MS=Utils.g('ASYNC_SLICE_HIDDEN_MS',A.SLICE_HIDDEN_MS??Math.min(this.SLICE_MS,6));this.MIN_YIELD_MS=Utils.g('ASYNC_MIN_YIELD_MS',A.MIN_YIELD_MS??0);this._opGen=new Map();}
@@ -776,7 +776,7 @@ _esc(s){return(s==null)?'':String(s);}
776
776
  _escapeHtml(s){return(typeof Utils!=='undefined')?Utils.escapeHtml(s):String(s).replace(/[&<>"']/g,m=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[m]));}
777
777
  _nameHeader(role,name,avatarUrl){if(!name&&!avatarUrl)return'';const cls=(role==='user')?'name-user':'name-bot';const img=avatarUrl?`<img src="${this._esc(avatarUrl)}" class="avatar"> `:'';return`<div class="name-header ${cls}">${img}${this._esc(name || '')}</div>`;}
778
778
  _renderUser(block){const id=block.id;const inp=block.input||{};const msgId=`msg-user-${id}`;const personalize=!!(block&&block.extra&&block.extra.personalize===true);const nameHeader=personalize?this._nameHeader('user',inp.name||'',inp.avatar_img||null):'';const content=this._escapeHtml(inp.text||'').replace(/\r?\n/g,'<br>');const I=(this.cfg&&this.cfg.ICONS)||{};const L=(this.cfg&&this.cfg.LOCALE)||{};const copyIcon=I.CODE_COPY||'';const copyTitle=L.COPY||'Copy';const copyBtn=`<a href="empty:${this._esc(id)}" class="msg-copy-btn" data-id="${this._esc(id)}" data-tip="${this._escapeHtml(copyTitle)}" title="${this._escapeHtml(copyTitle)}" aria-label="${this._escapeHtml(copyTitle)}" role="button"><img src="${this._esc(copyIcon)}" class="copy-img" alt="${this._escapeHtml(copyTitle)}" data-id="${this._esc(id)}"></a>`;return`<div class="msg-box msg-user" id="${msgId}">${nameHeader}<div class="msg">${copyBtn}<p style="margin:0">${content}</p></div></div>`;}
779
- _renderExtras(block){const parts=[];const images=block.images||{};const keysI=Object.keys(images);if(keysI.length){keysI.forEach((k)=>{const it=images[k];if(!it)return;const url=this._esc(it.url);const path=this._esc(it.path);const bn=this._esc(it.basename||'');if(it.is_video){const src=(it.ext==='.webm'||!it.webm_path)?path:this._esc(it.webm_path);const ext=(src.endsWith('.webm')?'webm':(path.split('.').pop()||'mp4'));parts.push(`<div class="extra-src-video-box" title="${url}">`+`<video class="video-player" controls>`+`<source src="${src}" type="video/${ext}">`+`</video>`+`<p><a href="bridge://play_video/${url}" class="title">${this._escapeHtml(bn)}</a></p>`+`</div>`);}else{parts.push(`<div class="extra-src-img-box" title="${url}">`+`<div class="img-outer"><div class="img-wrapper"><a href="${url}"><img src="${path}" class="image"></a></div>`+`<a href="${url}" class="title">${this._escapeHtml(bn)}</a></div>`+`</div><br/>`);}});}
779
+ _renderExtras(block){const parts=[];const images=block.images||{};const keysI=Object.keys(images);if(keysI.length){keysI.forEach((k)=>{const it=images[k];if(!it)return;const url=this._esc(it.url);const path=this._esc(it.path);const bn=this._esc(it.basename||'');if(it.is_video){const src=(it.ext==='.webm'||!it.webm_path)?path:this._esc(it.webm_path);const ext=(src.endsWith('.webm')?'webm':(path.split('.').pop()||'mp4'));parts.push(`<div class="extra-src-video-box" title="${url}">`+`<video class="video-player" controls>`+`<source src="${src}" type="video/${ext}">`+`</video>`+`<p><a href="bridge://play_video/${url}" class="title">${this._escapeHtml(bn)}</a></p>`+`</div>`);}else{parts.push(`<div class="extra-src-img-box" title="${url}">`+`<div class="img-outer"><div class="img-wrapper"><a href="bridge://open_image/${path}"><img src="${path}" class="image"></a></div>`+`<a href="${url}" class="title">${this._escapeHtml(bn)}</a></div>`+`</div><br/>`);}});}
780
780
  const files=block.files||{};const kF=Object.keys(files);if(kF.length){const rows=[];kF.forEach((k)=>{const it=files[k];if(!it)return;const url=this._esc(it.url);const path=this._esc(it.path);const icon=(typeof window!=='undefined'&&window.ICON_ATTACHMENTS)?`<img src="${window.ICON_ATTACHMENTS}" class="extra-src-icon">`:'';rows.push(`${icon} <b> [${k}] </b> <a href="${url}">${path}</a>`);});if(rows.length)parts.push(`<div>${rows.join("<br/><br/>")}</div>`);}
781
781
  const urls=block.urls||{};const kU=Object.keys(urls);if(kU.length){const rows=[];kU.forEach((k)=>{const it=urls[k];if(!it)return;const url=this._esc(it.url);const icon=(typeof window!=='undefined'&&window.ICON_URL)?`<img src="${window.ICON_URL}" class="extra-src-icon">`:'';rows.push(`${icon}<a href="${url}" title="${url}">${url}</a> <small> [${k}] </small>`);});if(rows.length)parts.push(`<div>${rows.join("<br/><br/>")}</div>`);}
782
782
  const extra=block.extra||{};const docsRaw=Array.isArray(extra.docs)?extra.docs:null;if(docsRaw&&docsRaw.length){const icon=(typeof window!=='undefined'&&window.ICON_DB)?`<img src="${window.ICON_DB}" class="extra-src-icon">`:'';const prefix=(typeof window!=='undefined'&&window.LOCALE_DOC_PREFIX)?String(window.LOCALE_DOC_PREFIX):'Doc:';const limit=3;const normalized=[];docsRaw.forEach((it)=>{if(!it||typeof it!=='object')return;if('uuid'in it&&'meta'in it&&typeof it.meta==='object'){normalized.push({uuid:String(it.uuid),meta:it.meta||{}});}else{const keys=Object.keys(it);if(keys.length===1){const uuid=keys[0];const meta=it[uuid];if(meta&&typeof meta==='object'){normalized.push({uuid:String(uuid),meta});}}}});const rows=[];for(let i=0;i<Math.min(limit,normalized.length);i++){const d=normalized[i];const meta=d.meta||{};const entries=Object.keys(meta).map(k=>`<b>${this._escapeHtml(k)}:</b> ${this._escapeHtml(String(meta[k]))}`).join(', ');rows.push(`<p><small>[${i + 1}] ${this._escapeHtml(d.uuid)}: ${entries}</small></p>`);}
@@ -301,6 +301,9 @@ confirm.remote_store.truncate = Alle Vektor-Speicher in der API löschen?
301
301
  context.btn.clear = Erinnerung löschen
302
302
  context.items = Elemente
303
303
  context.label = Kontext
304
+ context_menu.zoom = Zoom
305
+ context_menu.zoom.in = Vergrößern
306
+ context_menu.zoom.out = Verkleinern
304
307
  context.tokens = Tokens
305
308
  ctx.delete.all.confirm = Sind Sie sicher, dass Sie ALLE Verlaufskontexte löschen möchten?
306
309
  ctx.delete.confirm = Sind Sie sicher, dass Sie löschen möchten?
@@ -316,6 +316,9 @@ confirm.remote_store.truncate = Delete all vector stores in API?
316
316
  context.btn.clear = Clear memory
317
317
  context.items = items
318
318
  context.label = Context
319
+ context_menu.zoom = Zoom
320
+ context_menu.zoom.in = Zoom In
321
+ context_menu.zoom.out = Zoom Out
319
322
  context.tokens = tokens
320
323
  ctx.delete.all.confirm = Are you sure you want to delete ALL history contexts?
321
324
  ctx.delete.confirm = Are you sure you want to delete?
@@ -301,6 +301,9 @@ confirm.remote_store.truncate = ¿Eliminar todas las bases vectoriales en la API
301
301
  context.btn.clear = Limpiar memoria
302
302
  context.items = elementos
303
303
  context.label = Contexto
304
+ context_menu.zoom = Zoom
305
+ context_menu.zoom.in = Acercar
306
+ context_menu.zoom.out = Alejar
304
307
  context.tokens = tokens
305
308
  ctx.delete.all.confirm = ¿Está seguro de querer eliminar TODOS los contextos del historial?
306
309
  ctx.delete.confirm = ¿Está seguro de querer eliminar?
@@ -301,6 +301,9 @@ confirm.remote_store.truncate = Supprimer toutes les bases vectorielles dans l'A
301
301
  context.btn.clear = Effacer la mémoire
302
302
  context.items = éléments
303
303
  context.label = Contexte
304
+ context_menu.zoom = Zoom
305
+ context_menu.zoom.in = Zoomer
306
+ context_menu.zoom.out = Dézoomer
304
307
  context.tokens = jetons
305
308
  ctx.delete.all.confirm = Êtes-vous sûr de vouloir supprimer TOUS les contextes d'historique ?
306
309
  ctx.delete.confirm = Êtes-vous sûr de vouloir supprimer ?
@@ -301,6 +301,9 @@ confirm.remote_store.truncate = Cancellare tutte le basi vettoriali in API?
301
301
  context.btn.clear = Pulisci memoria
302
302
  context.items = elementi
303
303
  context.label = Contesto
304
+ context_menu.zoom = Zoom
305
+ context_menu.zoom.in = Ingrandire
306
+ context_menu.zoom.out = Ridurre
304
307
  context.tokens = token
305
308
  ctx.delete.all.confirm = Sei sicuro di voler eliminare TUTTI i contesti della cronologia?
306
309
  ctx.delete.confirm = Sei sicuro di voler eliminare?
@@ -301,6 +301,9 @@ confirm.remote_store.truncate = Usunąć wszystkie bazy wektorowe w API?
301
301
  context.btn.clear = Wyczyść pamięć
302
302
  context.items = elementy
303
303
  context.label = Kontekst
304
+ context_menu.zoom = Powiększenie
305
+ context_menu.zoom.in = Powiększ
306
+ context_menu.zoom.out = Pomniejsz
304
307
  context.tokens = tokeny
305
308
  ctx.delete.all.confirm = Czy na pewno usunąć CAŁĄ historię?
306
309
  ctx.delete.confirm = Czy na pewno usunąć?
@@ -301,6 +301,9 @@ confirm.remote_store.truncate = Видалити всі векторні баз
301
301
  context.btn.clear = Очистити пам'ять
302
302
  context.items = елементи
303
303
  context.label = Контекст
304
+ context_menu.zoom = Масштаб
305
+ context_menu.zoom.in = Збільшити
306
+ context_menu.zoom.out = Зменшити
304
307
  context.tokens = токени
305
308
  ctx.delete.all.confirm = Ви впевнені, що хочете видалити ВСІ контексти історії?
306
309
  ctx.delete.confirm = Ви впевнені, що хочете видалити?
@@ -301,6 +301,9 @@ confirm.remote_store.truncate = 删除 API 中的所有矢量存储?
301
301
  context.btn.clear = 清除記憶體
302
302
  context.items = 項目
303
303
  context.label = 上下文
304
+ context_menu.zoom = 缩放
305
+ context_menu.zoom.in = 放大
306
+ context_menu.zoom.out = 缩小
304
307
  context.tokens = 令牌
305
308
  ctx.delete.all.confirm = 您確定要刪除所有歷史上下文嗎?
306
309
  ctx.delete.confirm = 您確定要刪除嗎?
@@ -48,6 +48,6 @@ sandbox_home.label = Home URL
48
48
  sandbox_path.description = Path to Playwright browsers installation - leave empty to use default
49
49
  sandbox_path.label = Browsers directory
50
50
  sandbox_viewport_h.description = Playwright viewport height in pixels
51
- sandbox_viewport_h.label = Viewport height
51
+ sandbox_viewport_h.label = Viewport (height)
52
52
  sandbox_viewport_w.description = Playwright viewport width in pixels
53
- sandbox_viewport_w.label = Viewport width
53
+ sandbox_viewport_w.label = Viewport (width)
pygpt_net/item/ctx.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: 2026.01.03 02:10:00 #
9
+ # Updated Date: 2026.01.03 17:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -31,6 +31,7 @@ class CtxItem:
31
31
  audio_id: Optional[object] = None
32
32
  audio_output: Optional[object] = None
33
33
  bag: Optional[object] = None
34
+ chunk_type: Optional[str] = None
34
35
  cmds: list = field(default_factory=list)
35
36
  cmds_before: list = field(default_factory=list)
36
37
  current: bool = False
@@ -87,8 +88,6 @@ class CtxItem:
87
88
  urls: list = field(default_factory=list)
88
89
  urls_before: list = field(default_factory=list)
89
90
  use_agent_final_response: bool = False
90
- use_responses_api: bool = False
91
- use_google_interactions_api : bool = False
92
91
  ai_name: Optional[str] = None
93
92
 
94
93
  def __init__(self, mode: Optional[str] = None):
@@ -107,6 +106,7 @@ class CtxItem:
107
106
  self.audio_id = None
108
107
  self.audio_output = None
109
108
  self.bag = None
109
+ self.chunk_type = None
110
110
  self.cmds = []
111
111
  self.cmds_before = []
112
112
  self.current = False
@@ -164,8 +164,6 @@ class CtxItem:
164
164
  self.urls = []
165
165
  self.urls_before = []
166
166
  self.use_agent_final_response = False # use agent final response
167
- self.use_responses_api = False # use responses API format
168
- self.use_google_interactions_api = False # use Google Interactions API format
169
167
  self.ai_name = None # AI name
170
168
 
171
169
  @property