pygpt-net 2.4.42__py3-none-any.whl → 2.4.43__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.
CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 2.4.43 (2024-12-15)
4
+
5
+ - Fix: Bug on attachment upload.
6
+ - Added: Attachments uploaded in groups are now available for all contexts in the group (beta).
7
+
3
8
  ## 2.4.42 (2024-12-15)
4
9
 
5
10
  - Added Mailer plugin, which allows sending and retrieving emails from the server, and reading them. It currently supports only SMTP.
README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
4
4
 
5
- Release: **2.4.42** | build: **2024.12.15** | Python: **>=3.10, <3.12**
5
+ Release: **2.4.43** | build: **2024.12.15** | Python: **>=3.10, <3.12**
6
6
 
7
7
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
8
8
  >
@@ -785,6 +785,8 @@ You can use your own files (for example, to analyze them) during any conversatio
785
785
 
786
786
  **PyGPT** makes it simple for users to upload files and send them to the model for tasks like analysis, similar to attaching files in `ChatGPT`. There's a separate `Attachments` tab next to the text input area specifically for managing file uploads.
787
787
 
788
+ **Tip: Attachments uploaded in group are available in all contexts in group**.
789
+
788
790
  ![v2_file_input](https://github.com/user-attachments/assets/db8467b6-2d07-4e20-a795-430fc09443a7)
789
791
 
790
792
  You can use attachments to provide additional context to the conversation. Uploaded files will be converted into text using loaders from LlamaIndex, and then embedded into the vector store. You can upload any file format supported by the application through LlamaIndex. Supported formats include:
@@ -3934,6 +3936,11 @@ may consume additional tokens that are not displayed in the main window.
3934
3936
 
3935
3937
  ## Recent changes:
3936
3938
 
3939
+ **2.4.43 (2024-12-15)**
3940
+
3941
+ - Fix: Bug on attachment upload.
3942
+ - Added: Attachments uploaded in groups are now available for all contexts in the group (beta).
3943
+
3937
3944
  **2.4.42 (2024-12-15)**
3938
3945
 
3939
3946
  - Added Mailer plugin, which allows sending and retrieving emails from the server, and reading them. It currently supports only SMTP.
pygpt_net/CHANGELOG.txt CHANGED
@@ -1,3 +1,8 @@
1
+ 2.4.43 (2024-12-15)
2
+
3
+ - Fix: Bug on attachment upload.
4
+ - Added: Attachments uploaded in groups are now available for all contexts in the group (beta).
5
+
1
6
  2.4.42 (2024-12-15)
2
7
 
3
8
  - Added Mailer plugin, which allows sending and retrieving emails from the server, and reading them. It currently supports only SMTP.
pygpt_net/__init__.py CHANGED
@@ -6,14 +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: 2024.12.15 04:00:00 #
9
+ # Updated Date: 2024.12.15 11:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  __author__ = "Marcin Szczygliński"
13
13
  __copyright__ = "Copyright 2024, Marcin Szczygliński"
14
14
  __credits__ = ["Marcin Szczygliński"]
15
15
  __license__ = "MIT"
16
- __version__ = "2.4.42"
16
+ __version__ = "2.4.43"
17
17
  __build__ = "2024.12.15"
18
18
  __maintainer__ = "Marcin Szczygliński"
19
19
  __github__ = "https://github.com/szczyglis-dev/py-gpt"
@@ -180,7 +180,7 @@ class Attachment(QObject):
180
180
  if tmp_path:
181
181
  for root, dirs, files in os.walk(tmp_path):
182
182
  for file in files:
183
- path = os.path.join(root, file)
183
+ path = str(os.path.join(root, file))
184
184
  sub_attachment = AttachmentItem()
185
185
  sub_attachment.path = path
186
186
  sub_attachment.name = os.path.basename(path)
@@ -197,11 +197,9 @@ class Attachment(QObject):
197
197
  auto_index=auto_index,
198
198
  )
199
199
  if item:
200
- item["path"] = os.path.basename(attachment.path) + "/" + path_relative
200
+ item["path"] = os.path.basename(attachment.path) + "/" + str(path_relative)
201
201
  item["size"] = os.path.getsize(path)
202
- if meta.additional_ctx is None:
203
- meta.additional_ctx = []
204
- meta.additional_ctx.append(item)
202
+ self.append_to_meta(meta, item)
205
203
  uploaded = True
206
204
  sub_attachment.consumed = True
207
205
  attachment.consumed = True
@@ -215,14 +213,27 @@ class Attachment(QObject):
215
213
  auto_index=auto_index,
216
214
  )
217
215
  if item:
218
- if meta.additional_ctx is None:
219
- meta.additional_ctx = []
220
- meta.additional_ctx.append(item)
216
+ self.append_to_meta(meta, item)
221
217
  attachment.consumed = True # allow for deletion
222
218
  uploaded = True
223
-
224
219
  return uploaded
225
220
 
221
+ def append_to_meta(self, meta: CtxMeta, item: Dict[str, Any]):
222
+ """
223
+ Append item to meta
224
+
225
+ :param meta: CtxMeta instance
226
+ :param item: Attachment item
227
+ """
228
+ if meta.group:
229
+ if meta.group.additional_ctx is None:
230
+ meta.group.additional_ctx = []
231
+ meta.group.additional_ctx.append(item)
232
+ return
233
+ if meta.additional_ctx is None:
234
+ meta.additional_ctx = []
235
+ meta.additional_ctx.append(item)
236
+
226
237
  def upload_web(
227
238
  self,
228
239
  attachment: AttachmentItem,
@@ -248,9 +259,9 @@ class Attachment(QObject):
248
259
  :param meta: CtxMeta
249
260
  :return: True if has context
250
261
  """
251
- if meta is None or meta.additional_ctx is None:
262
+ if meta is None:
252
263
  return False
253
- return len(meta.additional_ctx) > 0
264
+ return meta.has_additional_ctx()
254
265
 
255
266
  def current_has_context(self) -> bool:
256
267
  """
@@ -334,7 +345,7 @@ class Attachment(QObject):
334
345
  :param meta: CtxMeta instance
335
346
  """
336
347
  # update list of attachments
337
- if meta is None or meta.additional_ctx is None:
348
+ if meta is None or not meta.has_additional_ctx():
338
349
  items = []
339
350
  else:
340
351
  items = self.window.core.attachments.context.get_all(meta)
@@ -347,7 +358,7 @@ class Attachment(QObject):
347
358
 
348
359
  :param meta: CtxMeta instance
349
360
  """
350
- if meta is None or meta.additional_ctx is None:
361
+ if meta is None or not meta.has_additional_ctx():
351
362
  num_files = 0
352
363
  else:
353
364
  num_files = self.window.core.attachments.context.count(meta)
@@ -402,13 +413,14 @@ class Attachment(QObject):
402
413
  )
403
414
  return
404
415
  meta = self.window.core.ctx.get_current_meta()
405
- if meta is None or meta.additional_ctx is None:
416
+ if meta is None or not meta.has_additional_ctx():
406
417
  return
407
418
  items = self.window.core.attachments.context.get_all(meta)
408
419
  if idx < len(items):
409
420
  item = items[idx]
410
421
  self.window.core.attachments.context.delete(meta, item, delete_files=remove_local)
411
422
  self.update_list(meta)
423
+ self.window.controller.ctx.update()
412
424
 
413
425
  def clear(
414
426
  self,
@@ -432,10 +444,11 @@ class Attachment(QObject):
432
444
  return
433
445
 
434
446
  meta = self.window.core.ctx.get_current_meta()
435
- if meta is None or meta.additional_ctx is None:
447
+ if meta is None or not meta.has_additional_ctx():
436
448
  return
437
449
  self.window.core.attachments.context.clear(meta, delete_files=remove_local)
438
450
  self.update_list(meta)
451
+ self.window.controller.ctx.update()
439
452
 
440
453
  def select(self, idx: int):
441
454
  """
@@ -452,7 +465,7 @@ class Attachment(QObject):
452
465
  :param idx: Index on list
453
466
  """
454
467
  meta = self.window.core.ctx.get_current_meta()
455
- if meta is None or meta.additional_ctx is None:
468
+ if meta is None or not meta.has_additional_ctx():
456
469
  return
457
470
  items = self.window.core.attachments.context.get_all(meta)
458
471
  if idx < len(items):
@@ -471,7 +484,7 @@ class Attachment(QObject):
471
484
  :param idx: Index on list
472
485
  """
473
486
  meta = self.window.core.ctx.get_current_meta()
474
- if meta is None or meta.additional_ctx is None:
487
+ if meta is None or not meta.has_additional_ctx():
475
488
  return
476
489
  items = self.window.core.attachments.context.get_all(meta)
477
490
  if idx < len(items):
@@ -491,7 +504,7 @@ class Attachment(QObject):
491
504
  :param idx: Index on list
492
505
  """
493
506
  meta = self.window.core.ctx.get_current_meta()
494
- if meta is None or meta.additional_ctx is None:
507
+ if meta is None or not meta.has_additional_ctx():
495
508
  return
496
509
  items = self.window.core.attachments.context.get_all(meta)
497
510
  if idx < len(items):
@@ -510,7 +523,7 @@ class Attachment(QObject):
510
523
  :return: True if has file
511
524
  """
512
525
  meta = self.window.core.ctx.get_current_meta()
513
- if meta is None or meta.additional_ctx is None:
526
+ if meta is None or not meta.has_additional_ctx():
514
527
  return False
515
528
  items = self.window.core.attachments.context.get_all(meta)
516
529
  if idx < len(items):
@@ -529,7 +542,7 @@ class Attachment(QObject):
529
542
  :return: True if has source directory
530
543
  """
531
544
  meta = self.window.core.ctx.get_current_meta()
532
- if meta is None or meta.additional_ctx is None:
545
+ if meta is None or not meta.has_additional_ctx():
533
546
  return False
534
547
  items = self.window.core.attachments.context.get_all(meta)
535
548
  if idx < len(items):
@@ -549,7 +562,7 @@ class Attachment(QObject):
549
562
  :return: True if has destination directory
550
563
  """
551
564
  meta = self.window.core.ctx.get_current_meta()
552
- if meta is None or meta.additional_ctx is None:
565
+ if meta is None or not meta.has_additional_ctx():
553
566
  return False
554
567
  items = self.window.core.attachments.context.get_all(meta)
555
568
  if idx < len(items):
@@ -570,10 +583,10 @@ class Attachment(QObject):
570
583
  meta = self.window.core.ctx.get_current_meta()
571
584
  if meta is None:
572
585
  return 0
573
- if meta.additional_ctx is None:
586
+ if not meta.has_additional_ctx():
574
587
  return 0
575
588
  tokens = 0
576
- for item in meta.additional_ctx:
589
+ for item in meta.get_additional_ctx():
577
590
  if "tokens" in item:
578
591
  try:
579
592
  tokens += int(item["tokens"])
@@ -161,7 +161,7 @@ class Attachments:
161
161
  if meta is None:
162
162
  return []
163
163
  attachments = []
164
- for attachment in meta.additional_ctx:
164
+ for attachment in meta.get_additional_ctx():
165
165
  item = AttachmentItem()
166
166
  if 'uuid' not in attachment:
167
167
  continue
@@ -125,7 +125,7 @@ class Context:
125
125
  meta_path = self.get_dir(meta)
126
126
  context = ""
127
127
  if os.path.exists(meta_path) and os.path.isdir(meta_path):
128
- for file in meta.additional_ctx:
128
+ for file in meta.get_additional_ctx():
129
129
  if ("type" not in file
130
130
  or file["type"] not in ["local_file", "url"]):
131
131
  continue
@@ -183,7 +183,7 @@ class Context:
183
183
 
184
184
  indexed = False
185
185
  # index files if not indexed by auto_index
186
- for i, file in enumerate(meta.additional_ctx):
186
+ for i, file in enumerate(meta.get_additional_ctx()):
187
187
  if "indexed" not in file or not file["indexed"]:
188
188
  file_id = file["uuid"]
189
189
  file_idx_path = os.path.join(meta_path, file_id)
@@ -496,7 +496,7 @@ class Context:
496
496
  :param meta: CtxMeta instance
497
497
  :return: list of attachments
498
498
  """
499
- return meta.additional_ctx
499
+ return meta.get_additional_ctx()
500
500
 
501
501
  def get_dir(self, meta: CtxMeta) -> str:
502
502
  """
@@ -506,6 +506,8 @@ class Context:
506
506
  :return: directory path
507
507
  """
508
508
  meta_uuid = str(meta.uuid)
509
+ if meta.group:
510
+ meta_uuid = str(meta.group.uuid)
509
511
  return os.path.join(self.window.core.config.get_user_dir("ctx_idx"), meta_uuid)
510
512
 
511
513
  def get_selected_model(self, mode: str = "summary"):
@@ -562,7 +564,7 @@ class Context:
562
564
  :param meta: CtxMeta instance
563
565
  :return: number of attachments
564
566
  """
565
- return len(meta.additional_ctx)
567
+ return len(meta.get_additional_ctx())
566
568
 
567
569
  def delete(
568
570
  self,
@@ -577,11 +579,11 @@ class Context:
577
579
  :param item: Attachment item dict
578
580
  :param delete_files: delete files
579
581
  """
580
- meta.additional_ctx.remove(item)
582
+ meta.remove_additional_ctx(item)
581
583
  self.window.core.ctx.save(meta.id)
582
584
  if delete_files:
583
585
  self.delete_local(meta, item)
584
- if len(meta.additional_ctx) == 0:
586
+ if len(meta.get_additional_ctx()) == 0:
585
587
  self.delete_index(meta)
586
588
 
587
589
  def delete_by_meta(self, meta: CtxMeta):
@@ -613,7 +615,7 @@ class Context:
613
615
  :param meta: CtxMeta instance
614
616
  :param delete_files: delete files
615
617
  """
616
- meta.additional_ctx = []
618
+ meta.reset_additional_ctx()
617
619
  self.window.core.ctx.save(meta.id)
618
620
  if delete_files:
619
621
  self.delete_index(meta)
@@ -644,7 +646,7 @@ class Context:
644
646
  :param meta: CtxMeta instance
645
647
  :param delete_files: delete files
646
648
  """
647
- meta.additional_ctx = []
649
+ meta.reset_additional_ctx()
648
650
  self.window.core.ctx.save(meta.id)
649
651
  if delete_files:
650
652
  self.delete_index(meta)
@@ -122,6 +122,7 @@ class Database:
122
122
  'updated_ts',
123
123
  'created_ts',
124
124
  'uuid',
125
+ 'additional_ctx_json',
125
126
  ]
126
127
  columns["idx_ctx"] = [
127
128
  'id',
@@ -242,7 +243,7 @@ class Database:
242
243
  'sort_by': columns["ctx_group"],
243
244
  'search_fields': ['id', 'name'],
244
245
  'timestamp_columns': ['created_ts', 'updated_ts'],
245
- 'json_columns': [],
246
+ 'json_columns': ['additional_ctx_json'],
246
247
  'default_sort': 'id',
247
248
  'default_order': 'DESC',
248
249
  'primary_key': 'id',
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.4.42",
4
- "app.version": "2.4.42",
3
+ "version": "2.4.43",
4
+ "app.version": "2.4.43",
5
5
  "updated_at": "2024-12-15T00:00:00"
6
6
  },
7
7
  "access.audio.event.speech": false,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.4.42",
4
- "app.version": "2.4.42",
3
+ "version": "2.4.43",
4
+ "app.version": "2.4.43",
5
5
  "updated_at": "2024-12-15T00:00:00"
6
6
  },
7
7
  "items": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "__meta__": {
3
- "version": "2.4.42",
4
- "app.version": "2.4.42",
3
+ "version": "2.4.43",
4
+ "app.version": "2.4.43",
5
5
  "updated_at": "2024-12-15T00:00:00"
6
6
  },
7
7
  "items": {
pygpt_net/item/ctx.py CHANGED
@@ -362,18 +362,65 @@ class CtxMeta:
362
362
  self.label = 0 # label color
363
363
  self.indexes = {} # indexes data
364
364
  self.additional_ctx = [] # additional context data
365
+ self.group = None # parent group
365
366
  self.group_id = None
366
367
  self.root_id = None
367
368
  self.parent_id = None
368
369
  self.owner_uuid = None
369
370
 
371
+ def has_additional_ctx(self) -> bool:
372
+ """
373
+ Check if additional context data is attached
374
+
375
+ :return: True if additional context data is present
376
+ """
377
+ if self.additional_ctx is not None and len(self.additional_ctx) > 0:
378
+ return True
379
+ if self.group:
380
+ if self.group.additional_ctx is not None and len(self.group.additional_ctx) > 0:
381
+ return True
382
+ return False
383
+
384
+ def get_additional_ctx(self) -> list:
385
+ """
386
+ Get additional context data
387
+
388
+ :return: list
389
+ """
390
+ if self.group:
391
+ if self.group.additional_ctx:
392
+ return self.group.additional_ctx
393
+ if self.additional_ctx:
394
+ return self.additional_ctx
395
+ return []
396
+
397
+ def reset_additional_ctx(self):
398
+ """Delete additional context data"""
399
+ if self.group:
400
+ self.group.additional_ctx = []
401
+ else:
402
+ self.additional_ctx = []
403
+
404
+ def remove_additional_ctx(self, item: dict):
405
+ """
406
+ Remove additional context data item
407
+
408
+ :param item: dict
409
+ """
410
+ if self.group:
411
+ if item in self.group.additional_ctx:
412
+ self.group.additional_ctx.remove(item)
413
+ else:
414
+ if item in self.additional_ctx:
415
+ self.additional_ctx.remove(item)
416
+
370
417
  def to_dict(self) -> dict:
371
418
  """
372
419
  Dump context meta to dict
373
420
 
374
421
  :return: dict
375
422
  """
376
- return {
423
+ data = {
377
424
  "id": self.id,
378
425
  "external_id": self.external_id,
379
426
  "uuid": self.uuid,
@@ -404,6 +451,9 @@ class CtxMeta:
404
451
  "parent_id": self.parent_id,
405
452
  "owner_uuid": self.owner_uuid,
406
453
  }
454
+ if self.group:
455
+ data["__group__"] = self.group.to_dict()
456
+ return data
407
457
 
408
458
  def from_dict(self, data: dict):
409
459
  """
@@ -458,6 +508,7 @@ class CtxGroup:
458
508
  self.items = []
459
509
  self.created = int(time.time())
460
510
  self.updated = int(time.time())
511
+ self.additional_ctx = []
461
512
  self.count = 0
462
513
 
463
514
  def to_dict(self) -> dict:
@@ -471,6 +522,7 @@ class CtxGroup:
471
522
  "uuid": self.uuid,
472
523
  "name": self.name,
473
524
  "items": self.items,
525
+ "additional_ctx": self.additional_ctx,
474
526
  "created": self.created,
475
527
  "updated": self.updated,
476
528
  "count": self.count,
@@ -0,0 +1,25 @@
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: 2024.11.23 00:00:00 #
10
+ # ================================================== #
11
+
12
+ from sqlalchemy import text
13
+
14
+ from .base import BaseMigration
15
+
16
+
17
+ class Version20241215110000(BaseMigration):
18
+ def __init__(self, window=None):
19
+ super(Version20241215110000, self).__init__(window)
20
+ self.window = window
21
+
22
+ def up(self, conn):
23
+ conn.execute(text("""
24
+ ALTER TABLE ctx_group ADD COLUMN additional_ctx_json TEXT;
25
+ """))
@@ -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: 2024.11.26 19:00:00 #
9
+ # Updated Date: 2024.12.15 11:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from .Version20231227152900 import Version20231227152900 # 2.0.59
@@ -22,6 +22,7 @@ from .Version20240426050000 import Version20240426050000 # 2.1.79
22
22
  from .Version20240501030000 import Version20240501030000 # 2.2.7
23
23
  from .Version20241122130000 import Version20241122130000 # 2.4.21
24
24
  from .Version20241126170000 import Version20241126170000 # 2.4.34
25
+ from .Version20241215110000 import Version20241215110000 # 2.4.43
25
26
 
26
27
  class Migrations:
27
28
  def __init__(self):
@@ -48,4 +49,5 @@ class Migrations:
48
49
  Version20240501030000(), # 2.2.7
49
50
  Version20241122130000(), # 2.4.21
50
51
  Version20241126170000(), # 2.4.34
52
+ Version20241215110000(), # 2.4.43
51
53
  ]
@@ -68,6 +68,9 @@ class Storage:
68
68
  # only base by default
69
69
  where_clauses.append("(m.root_id IS NULL OR m.root_id = 0)")
70
70
 
71
+ # join group
72
+ join_clauses.append("LEFT JOIN ctx_group g ON m.group_id = g.id")
73
+
71
74
  # search_string
72
75
  if search_string:
73
76
  date_ranges = search_by_date_string(search_string)
@@ -106,15 +109,16 @@ class Storage:
106
109
  continue
107
110
  mode = filter.get('mode', '=')
108
111
  value = filter.get('value', '')
112
+ key_name = 'm.' + key
109
113
  if isinstance(value, int):
110
- where_clauses.append(f"{key} {mode} :{key}")
114
+ where_clauses.append(f"{key_name} {mode} :{key}")
111
115
  bind_params[key] = value
112
116
  elif isinstance(value, str):
113
- where_clauses.append(f"{key} {mode} :{key}")
117
+ where_clauses.append(f"{key_name} {mode} :{key}")
114
118
  bind_params[key] = f"%{value}%"
115
119
  elif isinstance(value, list):
116
120
  values = "(" + ",".join([str(x) for x in value]) + ")"
117
- where_clauses.append(f"{key} {mode} {values}")
121
+ where_clauses.append(f"{key_name} {mode} {values}")
118
122
 
119
123
  where_statement = " AND ".join(where_clauses) if where_clauses else "1"
120
124
  join_statement = " ".join(join_clauses) if join_clauses else ""
@@ -154,8 +158,18 @@ class Storage:
154
158
  append_date_ranges=True,
155
159
  )
156
160
  stmt_text = f"""
157
- SELECT m.* FROM ctx_meta m {join_statement} WHERE {where_statement}
158
- ORDER BY m.updated_ts DESC {limit_suffix}
161
+ SELECT
162
+ m.*,
163
+ g.name as group_name,
164
+ g.uuid as group_uuid,
165
+ g.additional_ctx_json as group_additional_ctx_json
166
+ FROM
167
+ ctx_meta m
168
+ {join_statement}
169
+ WHERE
170
+ {where_statement}
171
+ ORDER BY
172
+ m.updated_ts DESC {limit_suffix}
159
173
  """
160
174
  stmt = text(stmt_text).bindparams(**bind_params)
161
175
 
@@ -177,7 +191,17 @@ class Storage:
177
191
  :return: dict of CtxMeta
178
192
  """
179
193
  stmt_text = f"""
180
- SELECT * FROM ctx_meta WHERE indexed_ts > 0
194
+ SELECT
195
+ m.*,
196
+ g.name as group_name,
197
+ g.uuid as group_uuid,
198
+ g.additional_ctx_json as group_additional_ctx_json
199
+ FROM
200
+ ctx_meta m
201
+ LEFT JOIN
202
+ ctx_group g ON m.group_id = g.id
203
+ WHERE
204
+ indexed_ts > 0
181
205
  """
182
206
  stmt = text(stmt_text)
183
207
  items = {}
@@ -431,7 +455,26 @@ class Storage:
431
455
  )
432
456
  with db.begin() as conn:
433
457
  conn.execute(stmt)
434
- return True
458
+
459
+ # update group
460
+ if meta.group:
461
+ stmt = text("""
462
+ UPDATE ctx_group
463
+ SET
464
+ name = :name,
465
+ additional_ctx_json = :additional_ctx_json,
466
+ updated_ts = :updated_ts
467
+ WHERE id = :id
468
+ """).bindparams(
469
+ id=meta.group.id,
470
+ name=meta.group.name,
471
+ additional_ctx_json=pack_item_value(meta.group.additional_ctx),
472
+ updated_ts=int(time.time()),
473
+ )
474
+ with db.begin() as conn:
475
+ conn.execute(stmt)
476
+
477
+ return True
435
478
 
436
479
  def update_meta_all(
437
480
  self,
@@ -125,7 +125,10 @@ def unpack_item_value(value: Any) -> Any:
125
125
  return value
126
126
 
127
127
 
128
- def unpack_item(item: CtxItem, row: Dict[str, Any]) -> CtxItem:
128
+ def unpack_item(
129
+ item: CtxItem,
130
+ row: Dict[str, Any]
131
+ ) -> CtxItem:
129
132
  """
130
133
  Unpack context item from DB row
131
134
 
@@ -185,9 +188,12 @@ def unpack_item(item: CtxItem, row: Dict[str, Any]) -> CtxItem:
185
188
  return item
186
189
 
187
190
 
188
- def unpack_meta(meta: CtxMeta, row: Dict[str, Any]) -> CtxMeta:
191
+ def unpack_meta(
192
+ meta: CtxMeta,
193
+ row: Dict[str, Any]
194
+ ) -> CtxMeta:
189
195
  """
190
- Unpack context meta data from DB row
196
+ Unpack context meta-data from DB row
191
197
 
192
198
  :param meta: Context meta (CtxMeta)
193
199
  :param row: DB row
@@ -221,20 +227,38 @@ def unpack_meta(meta: CtxMeta, row: Dict[str, Any]) -> CtxMeta:
221
227
 
222
228
  if meta.additional_ctx is None:
223
229
  meta.additional_ctx = []
230
+
231
+ # add group if exists
232
+ if meta.group_id:
233
+ group = CtxGroup()
234
+ group.id = meta.group_id
235
+ group.uuid = row['group_uuid']
236
+ group.name = row['group_name']
237
+ group.additional_ctx = unpack_item_value(row['group_additional_ctx_json'])
238
+ if group.additional_ctx is None:
239
+ group.additional_ctx = []
240
+ meta.group = group
241
+
224
242
  return meta
225
243
 
226
244
 
227
- def unpack_group(group: CtxGroup, row: Dict[str, Any]) -> CtxGroup:
245
+ def unpack_group(
246
+ group: CtxGroup,
247
+ row: Dict[str, Any]
248
+ ) -> CtxGroup:
228
249
  """
229
250
  Unpack context group data from DB row
230
251
 
231
252
  :param group: Context group (CtxGroup)
232
253
  :param row: DB row
233
- :return: context meta
254
+ :return: context group
234
255
  """
235
256
  group.id = unpack_var(row['id'], 'int')
236
257
  group.uuid = row['uuid']
237
258
  group.created = unpack_var(row['created_ts'], 'int')
238
259
  group.updated = unpack_var(row['updated_ts'], 'int')
239
260
  group.name = row['name']
261
+ group.additional_ctx = unpack_item_value(row['additional_ctx_json'])
262
+ if group.additional_ctx is None:
263
+ group.additional_ctx = []
240
264
  return group
@@ -50,7 +50,7 @@ class CtxAttachmentProvider(BaseStore):
50
50
 
51
51
  :return: True if exists
52
52
  """
53
- path = self.get_path()
53
+ path = self.get_path("")
54
54
  if os.path.exists(path):
55
55
  store = os.path.join(path, "docstore.json")
56
56
  if os.path.exists(store):
@@ -216,7 +216,7 @@ class CtxList:
216
216
  label = data.label
217
217
  if data.important:
218
218
  is_important = True
219
- if data.additional_ctx and len(data.additional_ctx) > 0:
219
+ if data.has_additional_ctx():
220
220
  is_attachment = True
221
221
  custom_data = {
222
222
  "label": label,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pygpt-net
3
- Version: 2.4.42
3
+ Version: 2.4.43
4
4
  Summary: Desktop AI Assistant powered by models: OpenAI o1, GPT-4o, GPT-4, GPT-4 Vision, GPT-3.5, DALL-E 3, Llama 3, Mistral, Gemini, Claude, Bielik, and other models supported by Langchain, Llama Index, and Ollama. Features include chatbot, text completion, image generation, vision analysis, speech-to-text, internet access, file handling, command execution and more.
5
5
  Home-page: https://pygpt.net
6
6
  License: MIT
@@ -92,7 +92,7 @@ Description-Content-Type: text/markdown
92
92
 
93
93
  [![pygpt](https://snapcraft.io/pygpt/badge.svg)](https://snapcraft.io/pygpt)
94
94
 
95
- Release: **2.4.42** | build: **2024.12.15** | Python: **>=3.10, <3.12**
95
+ Release: **2.4.43** | build: **2024.12.15** | Python: **>=3.10, <3.12**
96
96
 
97
97
  > Official website: https://pygpt.net | Documentation: https://pygpt.readthedocs.io
98
98
  >
@@ -875,6 +875,8 @@ You can use your own files (for example, to analyze them) during any conversatio
875
875
 
876
876
  **PyGPT** makes it simple for users to upload files and send them to the model for tasks like analysis, similar to attaching files in `ChatGPT`. There's a separate `Attachments` tab next to the text input area specifically for managing file uploads.
877
877
 
878
+ **Tip: Attachments uploaded in group are available in all contexts in group**.
879
+
878
880
  ![v2_file_input](https://github.com/user-attachments/assets/db8467b6-2d07-4e20-a795-430fc09443a7)
879
881
 
880
882
  You can use attachments to provide additional context to the conversation. Uploaded files will be converted into text using loaders from LlamaIndex, and then embedded into the vector store. You can upload any file format supported by the application through LlamaIndex. Supported formats include:
@@ -4024,6 +4026,11 @@ may consume additional tokens that are not displayed in the main window.
4024
4026
 
4025
4027
  ## Recent changes:
4026
4028
 
4029
+ **2.4.43 (2024-12-15)**
4030
+
4031
+ - Fix: Bug on attachment upload.
4032
+ - Added: Attachments uploaded in groups are now available for all contexts in the group (beta).
4033
+
4027
4034
  **2.4.42 (2024-12-15)**
4028
4035
 
4029
4036
  - Added Mailer plugin, which allows sending and retrieving emails from the server, and reading them. It currently supports only SMTP.
@@ -1,9 +1,9 @@
1
- CHANGELOG.md,sha256=4oUMtqTYrqJV3eCnvJa2WL3WqJR3YXTJqNBUO5HgEzA,79569
2
- README.md,sha256=D3vQEy0DZ8NbsU354mOw6MmT0ndQ5SEIdtd-LwI2T1w,162643
1
+ CHANGELOG.md,sha256=gWqK96Azkkf7FDN-W4BnMUkW5IGQuNPmaagHACm46hk,79723
2
+ README.md,sha256=CGBPIf6CopvQGVm0_3sIFMZzart9DYD9tNuqrDSnfV0,162878
3
3
  icon.png,sha256=CzcINJaU23a9hNjsDlDNbyuiEvKZ4Wg6DQVYF6SpuRg,13970
4
- pygpt_net/CHANGELOG.txt,sha256=pf4ClWevbIuqpk4B5wA1_xhy_AsksBUUJD5lj7Nqwj8,78107
4
+ pygpt_net/CHANGELOG.txt,sha256=MW1HexcMa_3hrQltStE9GmZkrPERXrxDztEJLFheIW8,78258
5
5
  pygpt_net/LICENSE,sha256=6Ku72-zJ8wO5VIR87UoJ5P_coCVjPghaFL9ZF2jLp7E,1146
6
- pygpt_net/__init__.py,sha256=ONDdzmuOgYz8TO10sxD_QMmCCxEJp2DWfbRXriB2dr8,1067
6
+ pygpt_net/__init__.py,sha256=yqHBqZHDgm5q2I9jx4JwYL4JDZ2CZUqiazeAAyiBbRM,1067
7
7
  pygpt_net/app.py,sha256=i02M96uLngAs_XZCS1Mi84vb3Okx8ZZewbTdhCqFolM,16029
8
8
  pygpt_net/config.py,sha256=Qc1FOBtTf3O6A6-6KoqUGtoJ0u8hXQeowvCVbZFwtik,16405
9
9
  pygpt_net/container.py,sha256=BemiVZPpPNIzfB-ZvnZeeBPFu-AcX2c30OqYFylEjJc,4023
@@ -28,7 +28,7 @@ pygpt_net/controller/calendar/__init__.py,sha256=s55RkCFQPFzdDoQ2zp3kohlNdpiWxdS
28
28
  pygpt_net/controller/calendar/note.py,sha256=y8Gkg35-aM1MfQ9P2NsRnmfSJw4Ps__9g6I1RhonR6s,11428
29
29
  pygpt_net/controller/camera.py,sha256=chf19kngEXzMJt54Gnj1bJGHVsYaCX0QimJnJa9uigE,16207
30
30
  pygpt_net/controller/chat/__init__.py,sha256=JUDt_DqxgpBROpr6k2jFQ03EIqXwmrAkwkkN0hN6jFU,3086
31
- pygpt_net/controller/chat/attachment.py,sha256=TXvPm0ifYBqHtbQ170SlE7IXrGTx8oT56N4DQMv96wg,20882
31
+ pygpt_net/controller/chat/attachment.py,sha256=2OUGeN54qlKPxSXyT5GEPrHeF9tRYkHqbe9l5QLKFiw,21261
32
32
  pygpt_net/controller/chat/audio.py,sha256=QsU36McxqlRoP6B-NSeck968g1M8JhlLkLwGLunbapw,3210
33
33
  pygpt_net/controller/chat/command.py,sha256=sop5xP9Sm0sLx7iTdBmCifGnF_nQw2cIb_pT6-0_ETg,2857
34
34
  pygpt_net/controller/chat/common.py,sha256=-BJa2wHRHLDY-BHgp36GFhSr0yGNclkJGMiJQDktHaA,13958
@@ -121,8 +121,8 @@ pygpt_net/core/agents/tools.py,sha256=Fq9PtkFWWebT3-Sd9P8UsoqmdNFuJJNC4vgLNLYknF
121
121
  pygpt_net/core/assistants/__init__.py,sha256=JVseBSjDJh9vJYjxoZVwU93EFTBJk_rUtRh_Ml550H0,4391
122
122
  pygpt_net/core/assistants/files.py,sha256=rmIVxDNfLrpA95Ghs_mc5s8Yn4xiC7POynpZMzaBcd0,10150
123
123
  pygpt_net/core/assistants/store.py,sha256=4zz8_10_f6o8gdRekEPo5Ox0tLwuZO8tKyVsz-AhYfs,8211
124
- pygpt_net/core/attachments/__init__.py,sha256=7YXB1dD8yFPIDEQrQxkkCR-CWSdUMM6zZ2SiWeuiF_8,12771
125
- pygpt_net/core/attachments/context.py,sha256=d7IhVswoBnrEmLNHslkm2-0dG_spJE31_SzJVbbTE1c,24121
124
+ pygpt_net/core/attachments/__init__.py,sha256=ZZpOteha2oN3KJOdDoPA4xwoaibkrkQcFplpurZaQyE,12777
125
+ pygpt_net/core/attachments/context.py,sha256=SCJVbjRJ05_tn6qp2DHGhiweEFPfJWWyOH0JBpCOXts,24225
126
126
  pygpt_net/core/attachments/worker.py,sha256=_aUCyi5-Mbz0IGfgY6QKBZ6MFz8aKRDfKasbBVXg7kU,1341
127
127
  pygpt_net/core/audio/__init__.py,sha256=78xr4fNQbj-0eWGwq3XuSdbIi7iLYn414C5cn_TWp18,4766
128
128
  pygpt_net/core/audio/context.py,sha256=2XpXWhDC09iUvc0FRMq9BF2_rnQ60ZG4Js6LbO5MohY,1115
@@ -142,7 +142,7 @@ pygpt_net/core/ctx/container.py,sha256=tdPHPRfTi8yGY1MZGgFtYtx2lvc5K9OTqhjde16wi
142
142
  pygpt_net/core/ctx/idx.py,sha256=3Zi-48OWlU80si-Z7mVjnsc7TYATXK9g1dM0M5sXsV4,8167
143
143
  pygpt_net/core/ctx/output.py,sha256=_F3RHOXIzApB3Gw9tFkfW9OC4Vb91CTOgrrN_yXziTY,7276
144
144
  pygpt_net/core/ctx/reply.py,sha256=sgXe0YlkHbaITVhGU3NyMCa9Ph8EWFQjuA_BybohZQ4,1834
145
- pygpt_net/core/db/__init__.py,sha256=KUczKfytHXeFAnUWG6IHovB50xgUoVxS4sgxtNOrVY0,16316
145
+ pygpt_net/core/db/__init__.py,sha256=GJBz5Y8fbnpcBm9sFvo1c-5DzuEkg9YOwW1hOQPwCgg,16372
146
146
  pygpt_net/core/db/viewer.py,sha256=mXn94mwP5A-GOrVwY6gtEVBfvg7Fq5F79rK-Ap1hkwE,9131
147
147
  pygpt_net/core/debug/__init__.py,sha256=yK1g62SRqatrnod8HCUGSuqa-rdNg9utGUX49FAF018,9559
148
148
  pygpt_net/core/debug/agent.py,sha256=BylgNCl8n8aV2GCK5cQZVwobm1kjH_ETtgEiObilvgQ,1922
@@ -244,9 +244,9 @@ pygpt_net/css_rc.py,sha256=i13kX7irhbYCWZ5yJbcMmnkFp_UfS4PYnvRFSPF7XXo,11349
244
244
  pygpt_net/data/audio/click_off.mp3,sha256=aNiRDP1pt-Jy7ija4YKCNFBwvGWbzU460F4pZWZDS90,65201
245
245
  pygpt_net/data/audio/click_on.mp3,sha256=qfdsSnthAEHVXzeyN4LlC0OvXuyW8p7stb7VXtlvZ1k,65201
246
246
  pygpt_net/data/audio/ok.mp3,sha256=LTiV32pEBkpUGBkKkcOdOFB7Eyt_QoP2Nv6c5AaXftk,32256
247
- pygpt_net/data/config/config.json,sha256=upqX3hVET-NT2_v92M46MoXWUljOW3TF9SyFSaBSryY,19536
248
- pygpt_net/data/config/models.json,sha256=rraM00QONZd-Rv1eaGey0NzNOokEK1dx1K623AhYXJI,48872
249
- pygpt_net/data/config/modes.json,sha256=fYXjJDpcgBFLZWefl1EITBkMrrKOLFCJLaBtuWH8f7o,1923
247
+ pygpt_net/data/config/config.json,sha256=bqQQQho8T98iabdx1ssCaRjMrLaoHcifku0DeqUGilM,19536
248
+ pygpt_net/data/config/models.json,sha256=sDwF9240lA8rX0de3N-PfMtlMPhKhIrQO-6DYORs7_E,48872
249
+ pygpt_net/data/config/modes.json,sha256=JoYON4tl22PW-KCVeQdxI--8S0HkgQTbAwB0PnJhJBU,1923
250
250
  pygpt_net/data/config/presets/agent_openai.json,sha256=vMTR-soRBiEZrpJJHuFLWyx8a3Ez_BqtqjyXgxCAM_Q,733
251
251
  pygpt_net/data/config/presets/agent_openai_assistant.json,sha256=awJw9lNTGpKML6SJUShVn7lv8AXh0oic7wBeyoN7AYs,798
252
252
  pygpt_net/data/config/presets/agent_planner.json,sha256=a6Rv58Bnm2STNWB0Rw_dGhnsz6Lb3J8_GwsUVZaTIXc,742
@@ -1667,7 +1667,7 @@ pygpt_net/item/__init__.py,sha256=jQQgG9u_ZLsZWXustoc1uvC-abUvj4RBKPAM30-f2Kc,48
1667
1667
  pygpt_net/item/assistant.py,sha256=1X34PaUgr993MfVVtBY6rGMNTSdSv6oKKPRqHBQkHuk,9587
1668
1668
  pygpt_net/item/attachment.py,sha256=lsfg8qHYDON2WKoNqPxsWv1U_xp0mz9nYrQlzZqrBOQ,2689
1669
1669
  pygpt_net/item/calendar_note.py,sha256=ZXTIChVaH_E7ju_CJ2LI77C4ikvd2G-c3tRo7UG9uwc,2108
1670
- pygpt_net/item/ctx.py,sha256=zrzsl4XcAlLSdjavaDFv251COJsBAyivbw5_Rhy7yRY,16214
1670
+ pygpt_net/item/ctx.py,sha256=1Rz_eqE7w0fZjC8JICok0LkuBAQsYM14tJzhIaVUq8w,17791
1671
1671
  pygpt_net/item/index.py,sha256=gDQYPlhwHF0QVGwX4TFGxHyO7pt5tqHcuyc3DPgPCA0,1681
1672
1672
  pygpt_net/item/mode.py,sha256=bhX6ZOvTKsiLI6-N-7cuJ_9izlAqq6bsXF1FjufJvfw,600
1673
1673
  pygpt_net/item/model.py,sha256=_VxfztYd0HBnsBsymGLGqemM2zwPjWKlEEWxy3a1cjw,7482
@@ -1690,7 +1690,8 @@ pygpt_net/migrations/Version20240426050000.py,sha256=AK8BMUyUNd1_FJstFOSyZBCdbhP
1690
1690
  pygpt_net/migrations/Version20240501030000.py,sha256=Vt0ullWeCLToNKpyJB7h5ccMRGv6N258HTweegKY4r4,1052
1691
1691
  pygpt_net/migrations/Version20241122130000.py,sha256=tbpeW-6dySV4hq8_8RB-_mLsJlWzLFbLlWJ4c-MzBRQ,1174
1692
1692
  pygpt_net/migrations/Version20241126170000.py,sha256=XRjS3W5H0D99l_4CM_YGLInsL0VVkDlIJYE1lNONalk,956
1693
- pygpt_net/migrations/__init__.py,sha256=zEPwZXi45unXb7U_oR14i_lDE_Bh3fzh3Nf9Xd-cHyE,2202
1693
+ pygpt_net/migrations/Version20241215110000.py,sha256=ATf9IoiY62Mi77zSz5z_Pu0DTn1pTAIVFMEq-LtshIY,858
1694
+ pygpt_net/migrations/__init__.py,sha256=tZXoFSMVQqmbG3Se3ZpuYAmA51p772HhoSoCXbXblJE,2316
1694
1695
  pygpt_net/migrations/base.py,sha256=TXkG1Fe2kn-cMCSYZ2e-IzuGqpkuvTej0bbOOj2ZJNU,614
1695
1696
  pygpt_net/plugin/__init__.py,sha256=1SGZ5i2G1UnKQpyj_HYkN0t-HLepD6jU_ICw1waaxlk,488
1696
1697
  pygpt_net/plugin/agent/__init__.py,sha256=GPbnpS9djcfzuPRxM2mu0hpUPRa51KtUR27Al6zqv3g,6188
@@ -1821,8 +1822,8 @@ pygpt_net/provider/core/ctx/__init__.py,sha256=jQQgG9u_ZLsZWXustoc1uvC-abUvj4RBK
1821
1822
  pygpt_net/provider/core/ctx/base.py,sha256=Tfb4MDNe9BXXPU3lbzpdYwJF9S1oa2-mzgu5XT4It9g,3003
1822
1823
  pygpt_net/provider/core/ctx/db_sqlite/__init__.py,sha256=G2pB7kZfREJRLJZmfv3DKTslXC-K7EhNN2sn56q6BFA,11753
1823
1824
  pygpt_net/provider/core/ctx/db_sqlite/patch.py,sha256=rQO893JsyYxXdL2sFSPvcsF1KgXv13VonpY-tU284go,3101
1824
- pygpt_net/provider/core/ctx/db_sqlite/storage.py,sha256=L2x8aYx6R79_lZ9Z7mDxRWmPJWfakJaV6KlpWmoxcSs,42402
1825
- pygpt_net/provider/core/ctx/db_sqlite/utils.py,sha256=NsC6b5RZPFEG7gkGxuUvbrIcgy2QZneMxJA-h2WNuRw,8377
1825
+ pygpt_net/provider/core/ctx/db_sqlite/storage.py,sha256=YkyS29h3vroGyiAdHdW5A3T5zF3KbQXpG3pd6hsQRJk,43714
1826
+ pygpt_net/provider/core/ctx/db_sqlite/utils.py,sha256=XuZYx-z9FEmt_TG5yFZ-5Zf6PgbSkG7Svx5oLEHXigY,8953
1826
1827
  pygpt_net/provider/core/ctx/json_file.py,sha256=g1U4vOxfyA2jydwYvPQ9HpUIQihyBK2K4K6SQ75jEEs,11665
1827
1828
  pygpt_net/provider/core/history/__init__.py,sha256=jQQgG9u_ZLsZWXustoc1uvC-abUvj4RBKPAM30-f2Kc,488
1828
1829
  pygpt_net/provider/core/history/base.py,sha256=Y724aEXVA5uPAhXAdWGm9_4BmGR3n4uRrf3aQenru0U,863
@@ -1949,7 +1950,7 @@ pygpt_net/provider/loaders/web_yt.py,sha256=V1OUjWFDov-ITtcqWiFfKaStTIolgkEvnbAx
1949
1950
  pygpt_net/provider/vector_stores/__init__.py,sha256=ep6B8xlMHcvQTq48Z_4Tr2csO4xEJ4Lqr0Pu--_eTHk,8338
1950
1951
  pygpt_net/provider/vector_stores/base.py,sha256=5beaRqewHzJonWzSAc0M3FWt-RNd90HT_emazkVUEeA,4318
1951
1952
  pygpt_net/provider/vector_stores/chroma.py,sha256=fjSLEqiLcaM7Xnqlo8ARuBjI8tgBoiohXEjnNdfc1Zo,3186
1952
- pygpt_net/provider/vector_stores/ctx_attachment.py,sha256=dVhg25BYXYsIteJfvlAd_xLDslWZ5zoQnNTOVI4QBls,3322
1953
+ pygpt_net/provider/vector_stores/ctx_attachment.py,sha256=wRU2rtsTl2p3KR6uSOliGXLHRweTJ3aM1TrpQyKUvGc,3324
1953
1954
  pygpt_net/provider/vector_stores/elasticsearch.py,sha256=iuSo7s4B1XgOzIV5GZR_l0QXKwW25LN72jsaZ04tQJk,3165
1954
1955
  pygpt_net/provider/vector_stores/pinecode.py,sha256=pKnn7JEYVPnt1yE2sWSg60iS1mHLaCGUhytihsU9ydA,5190
1955
1956
  pygpt_net/provider/vector_stores/redis.py,sha256=qfYS7MZq3hrU4QP3a--7itQYBZheqUuxAyUYzedpu2Q,3196
@@ -2035,7 +2036,7 @@ pygpt_net/ui/layout/chat/markdown.py,sha256=hjYY8Da1z0IZZD086_csMcDY1wwagpuQTDZ-
2035
2036
  pygpt_net/ui/layout/chat/output.py,sha256=pS6s2tn1yZU1kukR1s6G3B_FFw6CRiTQtodvu9_9QeM,9978
2036
2037
  pygpt_net/ui/layout/chat/painter.py,sha256=2yGU9GET5PpcGteGyWcHTtodKqAL7rxrqxhQ10vhodM,5471
2037
2038
  pygpt_net/ui/layout/ctx/__init__.py,sha256=txpvk6XMqZjBckstlWhn4laQnHBVpcD_7kshER_ymf4,1850
2038
- pygpt_net/ui/layout/ctx/ctx_list.py,sha256=aT3Sra015MIj5gJWPTYMXrwLJXBpLPYrtkmve9QHtcM,9221
2039
+ pygpt_net/ui/layout/ctx/ctx_list.py,sha256=AqK1haTZlAIlUeJbw7VVd3wTXIrzmLHVBsNysQtI85M,9194
2039
2040
  pygpt_net/ui/layout/ctx/search_input.py,sha256=yM_X2sxeR09JRqmkd2R4z82GRo3I1k4rOb75PgIFydE,1441
2040
2041
  pygpt_net/ui/layout/ctx/video.py,sha256=RzzyGObhlXamXIJHRqA9D2o6eVVulF4kNPVf3BkURGI,1068
2041
2042
  pygpt_net/ui/layout/status.py,sha256=_XqhRz0yrCWNjes-2XCAo55wPZst-F8gm6TtyBHpaSA,1954
@@ -2170,8 +2171,8 @@ pygpt_net/ui/widget/textarea/web.py,sha256=9FoL02QY6mOxtc4t4fe8X7fVDIdPn9Sb_fwsv
2170
2171
  pygpt_net/ui/widget/vision/__init__.py,sha256=8HT4tQFqQogEEpGYTv2RplKBthlsFKcl5egnv4lzzEw,488
2171
2172
  pygpt_net/ui/widget/vision/camera.py,sha256=T8b5cmK6uhf_WSSxzPt_Qod8JgMnst6q8sQqRvgQiSA,2584
2172
2173
  pygpt_net/utils.py,sha256=YhMvgy0wNt3roHIbbAnS-5SXOxOOIIvRRGd6FPTa6d0,6153
2173
- pygpt_net-2.4.42.dist-info/LICENSE,sha256=GLKQTnJOPK4dDIWfkAIM4GwOxKJXi5zcMGt7FjLR1xk,1126
2174
- pygpt_net-2.4.42.dist-info/METADATA,sha256=RsyKqEaRdpaMoQc3MIFtOHk_3hue51xdhMBOk704DaA,167445
2175
- pygpt_net-2.4.42.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
2176
- pygpt_net-2.4.42.dist-info/entry_points.txt,sha256=qvpII6UHIt8XfokmQWnCYQrTgty8FeJ9hJvOuUFCN-8,43
2177
- pygpt_net-2.4.42.dist-info/RECORD,,
2174
+ pygpt_net-2.4.43.dist-info/LICENSE,sha256=GLKQTnJOPK4dDIWfkAIM4GwOxKJXi5zcMGt7FjLR1xk,1126
2175
+ pygpt_net-2.4.43.dist-info/METADATA,sha256=QKTWWE2uRN6aDxdt-StQ2pwAsK6fp5_3vsYH6WqNa8Q,167680
2176
+ pygpt_net-2.4.43.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
2177
+ pygpt_net-2.4.43.dist-info/entry_points.txt,sha256=qvpII6UHIt8XfokmQWnCYQrTgty8FeJ9hJvOuUFCN-8,43
2178
+ pygpt_net-2.4.43.dist-info/RECORD,,