pygpt-net 2.4.37__py3-none-any.whl → 2.4.41__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 (255) hide show
  1. CHANGELOG.md +29 -0
  2. README.md +44 -115
  3. pygpt_net/CHANGELOG.txt +29 -0
  4. pygpt_net/__init__.py +3 -3
  5. pygpt_net/controller/__init__.py +7 -3
  6. pygpt_net/controller/access/control.py +1 -1
  7. pygpt_net/controller/access/voice.py +11 -5
  8. pygpt_net/controller/agent/experts.py +11 -6
  9. pygpt_net/controller/agent/legacy.py +8 -6
  10. pygpt_net/controller/agent/llama.py +4 -2
  11. pygpt_net/controller/assistant/__init__.py +9 -4
  12. pygpt_net/controller/assistant/batch.py +38 -21
  13. pygpt_net/controller/assistant/editor.py +7 -6
  14. pygpt_net/controller/assistant/files.py +23 -7
  15. pygpt_net/controller/assistant/store.py +20 -7
  16. pygpt_net/controller/assistant/threads.py +34 -8
  17. pygpt_net/controller/attachment.py +29 -10
  18. pygpt_net/controller/audio/__init__.py +25 -4
  19. pygpt_net/controller/calendar/__init__.py +23 -4
  20. pygpt_net/controller/calendar/note.py +57 -11
  21. pygpt_net/controller/camera.py +3 -2
  22. pygpt_net/controller/chat/__init__.py +5 -3
  23. pygpt_net/controller/chat/attachment.py +34 -7
  24. pygpt_net/controller/chat/command.py +4 -2
  25. pygpt_net/controller/chat/common.py +11 -4
  26. pygpt_net/controller/chat/files.py +10 -3
  27. pygpt_net/controller/chat/image.py +17 -5
  28. pygpt_net/controller/chat/input.py +10 -7
  29. pygpt_net/controller/chat/output.py +21 -6
  30. pygpt_net/controller/chat/render.py +100 -21
  31. pygpt_net/controller/chat/response.py +34 -7
  32. pygpt_net/controller/chat/stream.py +4 -2
  33. pygpt_net/controller/chat/text.py +6 -4
  34. pygpt_net/controller/command.py +11 -3
  35. pygpt_net/controller/config/__init__.py +34 -6
  36. pygpt_net/controller/config/field/checkbox.py +7 -4
  37. pygpt_net/controller/config/field/cmd.py +7 -5
  38. pygpt_net/controller/config/field/combo.py +14 -6
  39. pygpt_net/controller/config/field/dictionary.py +14 -11
  40. pygpt_net/controller/config/field/input.py +9 -6
  41. pygpt_net/controller/config/field/slider.py +11 -8
  42. pygpt_net/controller/config/field/textarea.py +8 -5
  43. pygpt_net/controller/config/placeholder.py +52 -21
  44. pygpt_net/controller/ctx/__init__.py +138 -49
  45. pygpt_net/controller/ctx/common.py +15 -4
  46. pygpt_net/controller/ctx/extra.py +11 -3
  47. pygpt_net/controller/ctx/summarizer.py +24 -5
  48. pygpt_net/controller/debug/__init__.py +27 -6
  49. pygpt_net/controller/dialogs/confirm.py +34 -7
  50. pygpt_net/controller/dialogs/debug.py +4 -2
  51. pygpt_net/controller/dialogs/info.py +7 -2
  52. pygpt_net/controller/files.py +48 -10
  53. pygpt_net/controller/finder.py +11 -5
  54. pygpt_net/controller/idx/__init__.py +10 -3
  55. pygpt_net/controller/idx/common.py +4 -2
  56. pygpt_net/controller/idx/indexer.py +25 -17
  57. pygpt_net/controller/idx/settings.py +9 -3
  58. pygpt_net/controller/kernel/__init__.py +34 -8
  59. pygpt_net/controller/kernel/reply.py +12 -3
  60. pygpt_net/controller/kernel/stack.py +5 -3
  61. pygpt_net/controller/lang/custom.py +2 -7
  62. pygpt_net/controller/lang/mapping.py +5 -3
  63. pygpt_net/controller/layout.py +2 -2
  64. pygpt_net/controller/mode.py +16 -4
  65. pygpt_net/controller/model/__init__.py +14 -3
  66. pygpt_net/controller/model/editor.py +8 -3
  67. pygpt_net/controller/notepad.py +26 -12
  68. pygpt_net/controller/painter/capture.py +23 -4
  69. pygpt_net/controller/painter/common.py +9 -7
  70. pygpt_net/controller/plugins/__init__.py +19 -5
  71. pygpt_net/controller/plugins/presets.py +15 -6
  72. pygpt_net/controller/plugins/settings.py +9 -3
  73. pygpt_net/controller/presets/__init__.py +55 -16
  74. pygpt_net/controller/presets/editor.py +26 -10
  75. pygpt_net/controller/settings/__init__.py +3 -2
  76. pygpt_net/controller/settings/editor.py +29 -7
  77. pygpt_net/controller/settings/profile.py +22 -5
  78. pygpt_net/controller/theme/__init__.py +54 -12
  79. pygpt_net/controller/theme/common.py +24 -2
  80. pygpt_net/controller/theme/markdown.py +32 -16
  81. pygpt_net/controller/theme/menu.py +26 -5
  82. pygpt_net/controller/theme/nodes.py +2 -5
  83. pygpt_net/controller/tools/__init__.py +40 -2
  84. pygpt_net/controller/ui/__init__.py +4 -6
  85. pygpt_net/controller/ui/tabs.py +363 -65
  86. pygpt_net/core/access/actions.py +6 -4
  87. pygpt_net/core/access/shortcuts.py +4 -3
  88. pygpt_net/core/access/voice.py +6 -5
  89. pygpt_net/core/agents/legacy.py +4 -2
  90. pygpt_net/core/agents/memory.py +7 -2
  91. pygpt_net/core/agents/observer/evaluation.py +15 -7
  92. pygpt_net/core/agents/provider.py +9 -4
  93. pygpt_net/core/agents/runner.py +61 -15
  94. pygpt_net/core/agents/tools.py +23 -5
  95. pygpt_net/core/assistants/__init__.py +6 -4
  96. pygpt_net/core/assistants/files.py +35 -12
  97. pygpt_net/core/assistants/store.py +20 -10
  98. pygpt_net/core/attachments/__init__.py +54 -15
  99. pygpt_net/core/attachments/context.py +92 -29
  100. pygpt_net/core/audio/__init__.py +71 -3
  101. pygpt_net/core/audio/context.py +7 -2
  102. pygpt_net/core/bridge/__init__.py +22 -6
  103. pygpt_net/core/bridge/context.py +5 -3
  104. pygpt_net/core/calendar/__init__.py +57 -11
  105. pygpt_net/core/chain/__init__.py +8 -2
  106. pygpt_net/core/chain/chat.py +10 -8
  107. pygpt_net/core/chain/completion.py +10 -7
  108. pygpt_net/core/command.py +62 -17
  109. pygpt_net/core/ctx/__init__.py +260 -58
  110. pygpt_net/core/ctx/bag.py +25 -4
  111. pygpt_net/core/ctx/container.py +28 -17
  112. pygpt_net/core/ctx/idx.py +45 -8
  113. pygpt_net/core/ctx/output.py +95 -74
  114. pygpt_net/core/ctx/reply.py +5 -2
  115. pygpt_net/core/db/__init__.py +8 -7
  116. pygpt_net/core/db/viewer.py +17 -11
  117. pygpt_net/core/debug/__init__.py +10 -9
  118. pygpt_net/core/debug/tabs.py +5 -2
  119. pygpt_net/core/docker/__init__.py +11 -5
  120. pygpt_net/core/docker/builder.py +11 -3
  121. pygpt_net/core/events/app.py +5 -3
  122. pygpt_net/core/events/base.py +11 -5
  123. pygpt_net/core/events/control.py +5 -3
  124. pygpt_net/core/events/event.py +17 -7
  125. pygpt_net/core/events/kernel.py +5 -3
  126. pygpt_net/core/events/render.py +5 -3
  127. pygpt_net/core/experts/__init__.py +5 -4
  128. pygpt_net/core/filesystem/__init__.py +52 -34
  129. pygpt_net/core/filesystem/actions.py +8 -5
  130. pygpt_net/core/filesystem/editor.py +13 -3
  131. pygpt_net/core/filesystem/types.py +12 -7
  132. pygpt_net/core/filesystem/url.py +7 -3
  133. pygpt_net/core/idx/__init__.py +34 -25
  134. pygpt_net/core/idx/chat.py +40 -16
  135. pygpt_net/core/idx/context.py +6 -2
  136. pygpt_net/core/idx/indexing.py +84 -35
  137. pygpt_net/core/idx/llm.py +11 -3
  138. pygpt_net/core/idx/metadata.py +13 -3
  139. pygpt_net/core/idx/types/ctx.py +32 -6
  140. pygpt_net/core/idx/types/external.py +41 -7
  141. pygpt_net/core/idx/types/files.py +31 -6
  142. pygpt_net/core/image.py +15 -4
  143. pygpt_net/core/llm/__init__.py +13 -3
  144. pygpt_net/core/locale.py +34 -8
  145. pygpt_net/core/models.py +4 -3
  146. pygpt_net/core/notepad.py +9 -4
  147. pygpt_net/core/plugins.py +7 -6
  148. pygpt_net/core/presets.py +19 -10
  149. pygpt_net/core/profile.py +12 -6
  150. pygpt_net/core/prompt/__init__.py +10 -3
  151. pygpt_net/core/prompt/custom.py +7 -6
  152. pygpt_net/core/prompt/template.py +9 -3
  153. pygpt_net/core/render/base.py +117 -22
  154. pygpt_net/core/render/markdown/body.py +27 -7
  155. pygpt_net/core/render/markdown/renderer.py +119 -22
  156. pygpt_net/core/render/plain/body.py +22 -5
  157. pygpt_net/core/render/plain/renderer.py +97 -21
  158. pygpt_net/core/render/web/body.py +75 -25
  159. pygpt_net/core/render/web/renderer.py +313 -63
  160. pygpt_net/core/settings.py +9 -4
  161. pygpt_net/core/tabs/__init__.py +290 -103
  162. pygpt_net/core/tabs/tab.py +17 -4
  163. pygpt_net/core/tokens.py +44 -11
  164. pygpt_net/core/updater/__init__.py +20 -7
  165. pygpt_net/core/vision/analyzer.py +29 -6
  166. pygpt_net/core/web.py +130 -2
  167. pygpt_net/data/config/config.json +15 -4
  168. pygpt_net/data/config/models.json +3 -3
  169. pygpt_net/data/config/modes.json +3 -3
  170. pygpt_net/data/config/settings.json +55 -10
  171. pygpt_net/data/config/settings_section.json +3 -0
  172. pygpt_net/data/css/style.light.css +1 -0
  173. pygpt_net/data/css/{web.css → web-blocks.css} +162 -133
  174. pygpt_net/data/css/{web.light.css → web-blocks.light.css} +7 -0
  175. pygpt_net/data/css/web-chatgpt.css +350 -0
  176. pygpt_net/data/css/web-chatgpt.dark.css +64 -0
  177. pygpt_net/data/css/web-chatgpt.light.css +75 -0
  178. pygpt_net/data/css/web-chatgpt_wide.css +350 -0
  179. pygpt_net/data/css/web-chatgpt_wide.dark.css +64 -0
  180. pygpt_net/data/css/web-chatgpt_wide.light.css +75 -0
  181. pygpt_net/data/icons/split_screen.svg +1 -0
  182. pygpt_net/data/locale/locale.de.ini +12 -0
  183. pygpt_net/data/locale/locale.en.ini +17 -2
  184. pygpt_net/data/locale/locale.es.ini +12 -0
  185. pygpt_net/data/locale/locale.fr.ini +12 -0
  186. pygpt_net/data/locale/locale.it.ini +12 -0
  187. pygpt_net/data/locale/locale.pl.ini +12 -0
  188. pygpt_net/data/locale/locale.uk.ini +12 -0
  189. pygpt_net/data/locale/locale.zh.ini +12 -0
  190. pygpt_net/data/locale/plugin.cmd_web.de.ini +2 -0
  191. pygpt_net/data/locale/plugin.cmd_web.en.ini +20 -10
  192. pygpt_net/data/locale/plugin.cmd_web.es.ini +2 -0
  193. pygpt_net/data/locale/plugin.cmd_web.fr.ini +2 -0
  194. pygpt_net/data/locale/plugin.cmd_web.it.ini +2 -0
  195. pygpt_net/data/locale/plugin.cmd_web.pl.ini +2 -0
  196. pygpt_net/data/locale/plugin.cmd_web.uk.ini +2 -0
  197. pygpt_net/data/locale/plugin.cmd_web.zh.ini +2 -0
  198. pygpt_net/icons.qrc +1 -0
  199. pygpt_net/icons_rc.py +165 -136
  200. pygpt_net/item/ctx.py +46 -24
  201. pygpt_net/plugin/audio_input/simple.py +21 -5
  202. pygpt_net/plugin/audio_output/__init__.py +4 -1
  203. pygpt_net/plugin/base/config.py +4 -2
  204. pygpt_net/plugin/base/plugin.py +26 -6
  205. pygpt_net/plugin/base/worker.py +37 -9
  206. pygpt_net/plugin/cmd_code_interpreter/__init__.py +39 -37
  207. pygpt_net/plugin/cmd_code_interpreter/runner.py +25 -12
  208. pygpt_net/plugin/cmd_web/__init__.py +46 -6
  209. pygpt_net/plugin/cmd_web/config.py +74 -48
  210. pygpt_net/plugin/cmd_web/websearch.py +61 -28
  211. pygpt_net/plugin/cmd_web/worker.py +79 -13
  212. pygpt_net/provider/core/config/patch.py +43 -1
  213. pygpt_net/provider/core/ctx/base.py +4 -1
  214. pygpt_net/provider/core/ctx/db_sqlite/__init__.py +10 -1
  215. pygpt_net/provider/core/ctx/db_sqlite/storage.py +22 -1
  216. pygpt_net/provider/gpt/assistants.py +10 -9
  217. pygpt_net/provider/gpt/audio.py +3 -2
  218. pygpt_net/provider/gpt/chat.py +8 -7
  219. pygpt_net/provider/gpt/completion.py +6 -4
  220. pygpt_net/provider/gpt/image.py +9 -2
  221. pygpt_net/provider/gpt/store.py +14 -13
  222. pygpt_net/provider/gpt/vision.py +6 -5
  223. pygpt_net/tools/__init__.py +9 -1
  224. pygpt_net/tools/base.py +15 -1
  225. pygpt_net/tools/code_interpreter/__init__.py +174 -75
  226. pygpt_net/tools/code_interpreter/ui/dialogs.py +21 -103
  227. pygpt_net/tools/code_interpreter/ui/widgets.py +284 -9
  228. pygpt_net/tools/html_canvas/__init__.py +78 -23
  229. pygpt_net/tools/html_canvas/ui/dialogs.py +46 -62
  230. pygpt_net/tools/html_canvas/ui/widgets.py +96 -3
  231. pygpt_net/ui/base/context_menu.py +2 -2
  232. pygpt_net/ui/layout/chat/input.py +10 -18
  233. pygpt_net/ui/layout/chat/output.py +26 -44
  234. pygpt_net/ui/layout/ctx/ctx_list.py +13 -4
  235. pygpt_net/ui/layout/toolbox/footer.py +18 -2
  236. pygpt_net/ui/main.py +2 -2
  237. pygpt_net/ui/menu/config.py +7 -11
  238. pygpt_net/ui/menu/debug.py +11 -1
  239. pygpt_net/ui/menu/theme.py +9 -2
  240. pygpt_net/ui/widget/filesystem/explorer.py +2 -2
  241. pygpt_net/ui/widget/lists/context.py +27 -5
  242. pygpt_net/ui/widget/tabs/Input.py +2 -2
  243. pygpt_net/ui/widget/tabs/body.py +2 -1
  244. pygpt_net/ui/widget/tabs/layout.py +195 -0
  245. pygpt_net/ui/widget/tabs/output.py +218 -55
  246. pygpt_net/ui/widget/textarea/html.py +11 -1
  247. pygpt_net/ui/widget/textarea/output.py +10 -1
  248. pygpt_net/ui/widget/textarea/search_input.py +4 -1
  249. pygpt_net/ui/widget/textarea/web.py +49 -9
  250. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/METADATA +45 -116
  251. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/RECORD +255 -247
  252. /pygpt_net/data/css/{web.dark.css → web-blocks.dark.css} +0 -0
  253. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/LICENSE +0 -0
  254. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/WHEEL +0 -0
  255. {pygpt_net-2.4.37.dist-info → pygpt_net-2.4.41.dist-info}/entry_points.txt +0 -0
@@ -6,39 +6,48 @@
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.07 23:00:00 #
9
+ # Updated Date: 2024.12.14 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
- from PySide6.QtWidgets import QVBoxLayout
12
+ from typing import List
13
13
 
14
- from .bag import Bag
14
+ from PySide6.QtWidgets import QVBoxLayout, QWidget
15
+
16
+ from pygpt_net.core.tabs.tab import Tab
15
17
  from pygpt_net.ui.widget.textarea.output import ChatOutput
16
18
 
19
+ from .bag import Bag
20
+ from ...item.ctx import CtxItem
21
+
17
22
 
18
23
  class Container:
19
24
  def __init__(self, window=None):
20
25
  """
21
- Context container
26
+ Context output container
27
+
28
+ :param window: Window
22
29
  """
23
30
  self.window = window
24
31
  self.bags = {}
25
32
  self.bags[0] = Bag(window) # always create initial bag
26
33
 
27
- def register_output(self, id: int = 0):
34
+ def get(self, tab: Tab) -> QWidget:
28
35
  """
29
- Register output
36
+ Register and return output
30
37
 
31
- :param id: ID
38
+ :param tab: Tab
32
39
  :return: Widget
33
40
  """
34
41
  # plain output
35
42
  output_plain = ChatOutput(self.window)
43
+ output_plain.set_tab(tab)
36
44
 
37
45
  # web
38
46
  if self.window.core.config.get("render.engine") == "web":
39
47
  from pygpt_net.ui.widget.textarea.web import ChatWebOutput, CustomWebEnginePage
40
48
  # build output
41
49
  output_html = ChatWebOutput(self.window)
50
+ output_html.set_tab(tab)
42
51
  output_html.setPage(
43
52
  CustomWebEnginePage(self.window, output_html)
44
53
  )
@@ -48,13 +57,15 @@ class Container:
48
57
  else:
49
58
  # legacy
50
59
  output_html = ChatOutput(self.window)
60
+ output_html.set_tab(tab)
51
61
 
52
62
  if 'output_plain' not in self.window.ui.nodes:
53
63
  self.window.ui.nodes['output_plain'] = {}
54
64
  if 'output' not in self.window.ui.nodes:
55
65
  self.window.ui.nodes['output'] = {}
56
- self.window.ui.nodes['output_plain'][id] = output_plain
57
- self.window.ui.nodes['output'][id] = output_html
66
+
67
+ self.window.ui.nodes['output_plain'][tab.pid] = output_plain
68
+ self.window.ui.nodes['output'][tab.pid] = output_html
58
69
 
59
70
  # show/hide plain/html
60
71
  if self.window.core.config.get("render.plain") is True:
@@ -66,8 +77,8 @@ class Container:
66
77
 
67
78
  # build layout
68
79
  layout = QVBoxLayout()
69
- layout.addWidget(self.window.ui.nodes['output_plain'][id])
70
- layout.addWidget(self.window.ui.nodes['output'][id])
80
+ layout.addWidget(self.window.ui.nodes['output_plain'][tab.pid])
81
+ layout.addWidget(self.window.ui.nodes['output'][tab.pid])
71
82
  layout.setContentsMargins(0, 0, 0, 0)
72
83
  widget = self.window.core.tabs.from_layout(layout)
73
84
  return widget
@@ -102,29 +113,29 @@ class Container:
102
113
  self.bags[tab_id] = Bag(self.window) # crate new empty bag if not exists
103
114
  return self.bags[tab_id]
104
115
 
105
- def get_items(self) -> list:
116
+ def get_items(self) -> List[CtxItem]:
106
117
  """
107
- Get items
118
+ Get ctx items
108
119
 
109
120
  :return: Items
110
121
  """
111
122
  return self.get_active_bag().get_items()
112
123
 
113
- def set_items(self, items: list):
124
+ def set_items(self, items: List[CtxItem]):
114
125
  """
115
- Set items
126
+ Set ctx items
116
127
 
117
128
  :param items: Items
118
129
  """
119
130
  self.get_active_bag().set_items(items)
120
131
 
121
132
  def clear_items(self):
122
- """Clear items"""
133
+ """Clear ctx items"""
123
134
  self.get_active_bag().clear_items()
124
135
 
125
136
  def count_items(self) -> int:
126
137
  """
127
- Count items
138
+ Count ctx items
128
139
 
129
140
  :return: Items count
130
141
  """
pygpt_net/core/ctx/idx.py CHANGED
@@ -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: 2024.02.27 04:00:00 #
9
+ # Updated Date: 2024.12.14 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import time
13
+ from typing import Optional
13
14
 
14
15
  from pygpt_net.item.ctx import CtxMeta
15
16
  from pygpt_net.provider.core.ctx.base import BaseProvider
@@ -32,7 +33,12 @@ class Idx:
32
33
  """
33
34
  return self.window.core.ctx.get_provider()
34
35
 
35
- def set_meta_indexed_by_id(self, id: int, doc_id: str, ts: int) -> bool:
36
+ def set_meta_indexed_by_id(
37
+ self,
38
+ id: int,
39
+ doc_id: str,
40
+ ts: int
41
+ ) -> bool:
36
42
  """
37
43
  Update ctx meta indexed timestamp
38
44
 
@@ -43,7 +49,11 @@ class Idx:
43
49
  """
44
50
  return self.get_provider().set_meta_indexed_by_id(id, ts)
45
51
 
46
- def update_meta_indexed_by_id(self, id: int, doc_id: str) -> bool:
52
+ def update_meta_indexed_by_id(
53
+ self,
54
+ id: int,
55
+ doc_id: str
56
+ ) -> bool:
47
57
  """
48
58
  Update ctx meta indexed timestamp
49
59
 
@@ -79,7 +89,13 @@ class Idx:
79
89
  """
80
90
  return self.get_provider().clear_meta_indexed_all()
81
91
 
82
- def remove_meta_from_indexed(self, store: str, id: int, idx: str, doc_id: str = None) -> bool:
92
+ def remove_meta_from_indexed(
93
+ self,
94
+ store: str,
95
+ id: int,
96
+ idx: str,
97
+ doc_id: Optional[str] = None
98
+ ) -> bool:
83
99
  """
84
100
  Remove ctx meta from indexed
85
101
 
@@ -114,7 +130,12 @@ class Idx:
114
130
  self.clear_meta_indexed_by_id(id)
115
131
  return True
116
132
 
117
- def set_meta_as_indexed(self, id: int, idx: str, doc_id: str) -> bool:
133
+ def set_meta_as_indexed(
134
+ self,
135
+ id: int,
136
+ idx: str,
137
+ doc_id: str
138
+ ) -> bool:
118
139
  """
119
140
  Set ctx meta as indexed
120
141
 
@@ -157,7 +178,13 @@ class Idx:
157
178
  self.get_provider().update_meta_indexes_by_id(id, meta)
158
179
  return True
159
180
 
160
- def store_idx_data_in_meta(self, ctx: CtxMeta, store_id: str, idx: str, doc_id: str):
181
+ def store_idx_data_in_meta(
182
+ self,
183
+ ctx: CtxMeta,
184
+ store_id: str,
185
+ idx: str,
186
+ doc_id: str
187
+ ):
161
188
  """
162
189
  Append index data to ctx meta object
163
190
 
@@ -176,7 +203,13 @@ class Idx:
176
203
  current[store_id][idx][doc_id] = int(time.time()) # key = doc_id, value = last indexed timestamp
177
204
  ctx.indexes = current # update ctx meta object
178
205
 
179
- def remove_idx_data_from_meta(self, ctx: CtxMeta, store_id: str, idx: str, doc_id: str = None):
206
+ def remove_idx_data_from_meta(
207
+ self,
208
+ ctx: CtxMeta,
209
+ store_id: str,
210
+ idx: str,
211
+ doc_id: Optional[str] = None
212
+ ):
180
213
  """
181
214
  Remove index data from ctx meta object
182
215
 
@@ -209,7 +242,11 @@ class Idx:
209
242
 
210
243
  ctx.indexes = current # update ctx meta object
211
244
 
212
- def truncate_indexed(self, store_id: str = None, idx: str = None) -> bool:
245
+ def truncate_indexed(
246
+ self,
247
+ store_id: Optional[str] = None,
248
+ idx: Optional[str] = None
249
+ ) -> bool:
213
250
  """
214
251
  Truncate ctx meta indexed timestamps and statuses
215
252
 
@@ -6,9 +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: 2024.11.05 23:00:00 #
9
+ # Updated Date: 2024.12.14 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ from typing import Optional, List
13
+
12
14
  from pygpt_net.item.ctx import CtxItem, CtxMeta
13
15
  from pygpt_net.core.tabs.tab import Tab
14
16
 
@@ -16,11 +18,28 @@ class Output:
16
18
  def __init__(self, window=None):
17
19
  """
18
20
  Context output mapping
21
+
22
+ :param window: Window
19
23
  """
20
24
  self.window = window
21
- self.mapping = {} # pid => meta.id
25
+ self.mapping = {} # [column_idx => [pid => meta.id]]
22
26
  self.last_pids = {} # meta.id => pid
23
27
  self.last_pid = 0 # last used PID
28
+ self.initialized = False
29
+
30
+ def init(self, force: bool = False):
31
+ """
32
+ Initialize mappings
33
+
34
+ :param force: Force reinitialize
35
+ """
36
+ if self.initialized and not force:
37
+ return
38
+ self.clear()
39
+ for n in range(0, self.window.core.tabs.NUM_COLS):
40
+ self.mapping[n] = {}
41
+ self.last_pids[n] = {}
42
+ self.initialized = True
24
43
 
25
44
  def store(self, meta: CtxMeta) -> int:
26
45
  """
@@ -29,31 +48,20 @@ class Output:
29
48
  :param meta: Meta
30
49
  :return: PID
31
50
  """
51
+ self.init()
32
52
  pid = self.window.core.tabs.get_active_pid()
33
- # check if allowed tab
34
53
  tab = self.window.core.tabs.get_tab_by_pid(pid)
35
54
  if tab is None or tab.type != Tab.TAB_CHAT:
36
55
  return 0
37
- self.mapping[pid] = meta.id
38
- self.last_pids[meta.id] = pid
56
+ col_idx = tab.column_idx
57
+ self.mapping[col_idx][pid] = meta.id
58
+ self.last_pids[col_idx][meta.id] = pid
39
59
  self.last_pid = pid
40
60
  tab = self.window.core.tabs.get_tab_by_pid(pid)
41
61
  if tab is not None:
42
62
  tab.data_id = meta.id # store meta id in tab data
43
63
  return pid
44
64
 
45
- def meta_id_in_tab(self, meta_id: int) -> bool:
46
- """
47
- Check if meta id is in tab
48
-
49
- :param meta_id: Meta ID
50
- :return: bool
51
- """
52
- for pid, mid in self.mapping.items():
53
- if mid == meta_id:
54
- return True
55
- return False
56
-
57
65
  def is_mapped(self, meta: CtxMeta) -> bool:
58
66
  """
59
67
  Check if meta is mapped
@@ -61,97 +69,108 @@ class Output:
61
69
  :param meta: Meta
62
70
  :return: bool
63
71
  """
64
- return meta.id in self.mapping.values()
72
+ self.init()
73
+ for col_idx in self.mapping:
74
+ if meta.id in self.mapping[col_idx].values():
75
+ return True
76
+ return False
65
77
 
66
- def get_meta(self, pid: int) -> CtxMeta or None:
78
+ def get_meta(self, pid: int) -> Optional[int]:
67
79
  """
68
80
  Get meta by PID
69
81
 
70
82
  :param pid: PID
71
- :return: Meta or None
83
+ :return: meta ID or None
72
84
  """
73
- if pid in self.mapping:
74
- return self.mapping[pid]
85
+ self.init()
86
+ for col_idx in self.mapping:
87
+ if pid in self.mapping[col_idx]:
88
+ return self.mapping[col_idx][pid]
75
89
  return
76
90
 
77
- def get_mapped(self, meta: CtxMeta) -> int or None:
91
+ def prepare_meta(self, tab: Tab) -> Optional[int]:
92
+ """
93
+ Get meta ID by PID
94
+
95
+ :param tab: Tab
96
+ :return: Meta ID or None
97
+ """
98
+ self.init()
99
+ pid = tab.pid
100
+ col_idx = tab.column_idx
101
+ meta_id = None
102
+ if pid in self.mapping[col_idx]:
103
+ return self.mapping[col_idx][pid]
104
+ if meta_id is None:
105
+ meta_id = tab.data_id
106
+ if meta_id is not None:
107
+ self.mapping[col_idx][pid] = meta_id
108
+ self.last_pids[col_idx][meta_id] = pid
109
+ self.last_pid = pid
110
+ return meta_id
111
+
112
+ def get_mapped(self, meta: CtxMeta) -> Optional[int]:
78
113
  """
79
114
  Get PID by meta
80
115
 
81
116
  :param meta: Meta
82
117
  :return: PID or None
83
118
  """
119
+ self.init()
84
120
  all = []
85
121
  pid = None
86
122
  active_pid = self.window.core.tabs.get_active_pid()
87
- for pid, meta_id in self.mapping.items():
123
+ tab = self.window.core.tabs.get_tab_by_pid(active_pid)
124
+ if tab is None:
125
+ return None
126
+ col_idx = tab.column_idx
127
+ for pid, meta_id in self.mapping[col_idx].items():
88
128
  if meta_id == meta.id:
89
129
  all.append(pid)
90
130
  for pid in all:
91
- if pid == active_pid: # at first check if active
131
+ if pid == active_pid: # at first check for current tab
92
132
  return pid
93
133
  return pid
94
134
 
95
- def get_mapped_last(self, meta: CtxMeta) -> int or None:
96
- """
97
- Get last PID by meta
98
-
99
- :param meta: Meta
100
- :return: PID or None
101
- """
102
- active_pid = self.window.core.tabs.get_active_pid()
103
- if self.mapping[active_pid] == meta.id:
104
- return active_pid # return active PID at first
105
- if meta.id in self.last_pids:
106
- return self.last_pids[meta.id]
107
- return
108
-
109
- def prepare(self, meta: CtxMeta):
110
- """
111
- Clear mapping
112
-
113
- :param meta: meta to prepare
114
- """
115
- active_pid = self.window.core.tabs.get_active_pid()
116
- if active_pid in self.mapping:
117
- del self.mapping[active_pid] # remove from mapping
118
-
119
- def clear(self):
120
- """
121
- Clear mapping
122
- """
123
- self.mapping = {}
124
- self.last_pids = {}
125
- self.last_pid = 0
126
-
127
135
  def is_empty(self) -> bool:
128
136
  """
129
137
  Check if mapping is empty
130
138
 
131
139
  :return: bool
132
140
  """
141
+ self.init()
133
142
  active_pid = self.window.core.tabs.get_active_pid()
134
- if active_pid in self.mapping:
135
- return False
143
+ for col_idx in list(self.mapping.keys()):
144
+ if active_pid in self.mapping[col_idx]:
145
+ return False
136
146
  return True
137
147
 
138
- def get_pid(self, meta: CtxMeta = None) -> int:
148
+ def get_pid(self, meta: Optional[CtxMeta] = None) -> Optional[int]:
139
149
  """
140
150
  Get PID by meta
141
151
 
142
152
  :param meta: Meta
143
153
  :return: PID
144
154
  """
155
+ self.init()
156
+ active_pid = self.window.core.tabs.get_active_pid()
145
157
  if meta is None:
146
- return self.window.core.tabs.get_active_pid()
158
+ return None
147
159
  if self.is_mapped(meta):
148
- if self.window.core.tabs.get_active_pid() != self.get_mapped(meta): # if loaded in another tab
149
- return self.store(meta) # update to current
150
- return self.get_mapped_last(meta)
151
- else:
152
- return self.store(meta)
160
+ if active_pid == self.get_mapped(meta): # if loaded in current tab
161
+ return active_pid # return current
162
+ return self.store(meta)
163
+
164
+ def clear(self):
165
+ """
166
+ Clear mapping
167
+ """
168
+ self.mapping = {}
169
+ self.last_pids = {}
170
+ self.last_pid = 0
171
+ self.initialized = False
153
172
 
154
- def get_current(self, meta: CtxMeta = None):
173
+ def get_current(self, meta: Optional[CtxMeta] = None):
155
174
  """
156
175
  Get current output node by meta
157
176
 
@@ -165,7 +184,7 @@ class Output:
165
184
  for pid in self.window.ui.nodes['output']:
166
185
  return self.window.ui.nodes['output'][pid] # get first available
167
186
 
168
- def get_current_plain(self, meta: CtxMeta = None):
187
+ def get_current_plain(self, meta: Optional[CtxMeta] = None):
169
188
  """
170
189
  Get current output plain node by meta
171
190
 
@@ -176,9 +195,10 @@ class Output:
176
195
  if pid in self.window.ui.nodes['output_plain']:
177
196
  return self.window.ui.nodes['output_plain'][pid]
178
197
  else:
179
- return self.window.ui.nodes['output_plain'][0]
198
+ for pid in self.window.ui.nodes['output_plain']:
199
+ return self.window.ui.nodes['output_plain'][pid]
180
200
 
181
- def get_by_pid(self, pid = None):
201
+ def get_by_pid(self, pid: Optional[int] = None):
182
202
  """
183
203
  Get output node by PID
184
204
 
@@ -191,7 +211,7 @@ class Output:
191
211
  for pid in self.window.ui.nodes['output']:
192
212
  return self.window.ui.nodes['output'][pid] # get first available
193
213
 
194
- def get_by_pid_plain(self, pid = None):
214
+ def get_by_pid_plain(self, pid: Optional[int] = None):
195
215
  """
196
216
  Get output plain node by PID
197
217
 
@@ -201,9 +221,10 @@ class Output:
201
221
  if pid in self.window.ui.nodes['output_plain']:
202
222
  return self.window.ui.nodes['output_plain'][pid]
203
223
  else:
204
- return self.window.ui.nodes['output_plain'][0]
224
+ for pid in self.window.ui.nodes['output_plain']:
225
+ return self.window.ui.nodes['output_plain'][pid]
205
226
 
206
- def get_all(self) -> list:
227
+ def get_all(self) -> List:
207
228
  """
208
229
  Get all output nodes
209
230
 
@@ -214,7 +235,7 @@ class Output:
214
235
  nodes.append(node)
215
236
  return nodes
216
237
 
217
- def get_all_plain(self) -> list:
238
+ def get_all_plain(self) -> List:
218
239
  """
219
240
  Get all output plain nodes
220
241
 
@@ -6,9 +6,12 @@
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.08.28 20:00:00 #
9
+ # Updated Date: 2024.12.14 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
+ from typing import Dict, Any
13
+
14
+
12
15
  class ReplyContext:
13
16
 
14
17
  AGENT_CONTINUE = "agent.continue"
@@ -27,7 +30,7 @@ class ReplyContext:
27
30
  self.input = ""
28
31
  self.cmds = []
29
32
 
30
- def to_dict(self) -> dict:
33
+ def to_dict(self) -> Dict[str, Any]:
31
34
  """
32
35
  Dump to dictionary
33
36
 
@@ -6,12 +6,13 @@
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.14 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import os
13
13
  import shutil
14
14
  import time
15
+ from typing import Optional, Any, Dict
15
16
 
16
17
  from sqlalchemy import create_engine, text
17
18
 
@@ -320,7 +321,7 @@ class Database:
320
321
  self.db_path = os.path.join(self.window.core.config.path, self.db_name)
321
322
  self.prepare()
322
323
 
323
- def get_tables(self) -> dict:
324
+ def get_tables(self) -> Dict[str, Dict[str, Any]]:
324
325
  """
325
326
  Get tables configuration
326
327
 
@@ -402,7 +403,7 @@ class Database:
402
403
  self.set_param_exec("db_version", migration_version, conn)
403
404
  print("[DB] Executed DB migration: {}".format(migration.__class__.__name__).replace('Version', ''))
404
405
 
405
- def has_migrations_to_apply(self, migrations) -> bool:
406
+ def has_migrations_to_apply(self, migrations: list) -> bool:
406
407
  """
407
408
  Check if there are any migrations to apply
408
409
 
@@ -417,7 +418,7 @@ class Database:
417
418
  break
418
419
  return has_migrations
419
420
 
420
- def make_backup(self) -> str or None:
421
+ def make_backup(self) -> Optional[str]:
421
422
  """
422
423
  Make backup of database before migration
423
424
 
@@ -446,7 +447,7 @@ class Database:
446
447
  for migration in sorted_migrations:
447
448
  self.apply_migration(migration, conn, db_version)
448
449
 
449
- def get_param(self, key: str) -> str or None:
450
+ def get_param(self, key: str) -> Optional[str]:
450
451
  """
451
452
  Get parameter from database
452
453
 
@@ -460,7 +461,7 @@ class Database:
460
461
  result = conn.execute(sel_stmt).fetchone()
461
462
  return result[0] if result else None
462
463
 
463
- def set_param(self, key: str, value: any):
464
+ def set_param(self, key: str, value: Any):
464
465
  """
465
466
  Insert or update parameter in database
466
467
 
@@ -471,7 +472,7 @@ class Database:
471
472
  with self.engine.begin() as conn:
472
473
  self.set_param_exec(key, value, conn)
473
474
 
474
- def set_param_exec(self, key: str, value: any, conn):
475
+ def set_param_exec(self, key: str, value: Any, conn):
475
476
  """
476
477
  Insert or update parameter in database
477
478
 
@@ -6,16 +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: 2024.11.20 21:00:00 #
9
+ # Updated Date: 2024.12.14 08:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import json
13
+ from typing import Optional, List, Dict, Any
13
14
 
14
15
  from sqlalchemy import text
15
16
 
16
17
 
17
18
  class Viewer:
18
19
  def __init__(self, database):
20
+ """
21
+ Database viewer.
22
+
23
+ :param database: Database instance
24
+ """
19
25
  self.database = database
20
26
  self.tables = {}
21
27
  self.auto_backup = True
@@ -23,14 +29,14 @@ class Viewer:
23
29
  def fetch_data(
24
30
  self,
25
31
  table: str,
26
- columns: list,
32
+ columns: List[str],
27
33
  sort_by: str,
28
34
  order: str,
29
- search_query: str = None,
30
- search_column: str = None,
35
+ search_query: Optional[str] = None,
36
+ search_column: Optional[str] = None,
31
37
  offset: int = 0,
32
38
  limit: int = 100,
33
- filters: dict = None
39
+ filters: Optional[dict] = None
34
40
  ) -> list:
35
41
  """
36
42
  Fetch data from the database with the given parameters.
@@ -87,9 +93,9 @@ class Viewer:
87
93
  def count_rows(
88
94
  self,
89
95
  table: str,
90
- search_query: str = None,
91
- search_column: str = None,
92
- filters: dict = None
96
+ search_query: Optional[str] = None,
97
+ search_column: Optional[str] = None,
98
+ filters: Optional[Dict[str, Any]] = None
93
99
  ) -> int:
94
100
  """
95
101
  Count the number of rows in the table with an optional search query.
@@ -142,7 +148,7 @@ class Viewer:
142
148
  """
143
149
  return self.database.window.ui.debug["db"].browser.is_auto_backup()
144
150
 
145
- def delete_row(self, data: dict):
151
+ def delete_row(self, data: Dict[str, Any]):
146
152
  """
147
153
  Delete row from the database.
148
154
 
@@ -165,7 +171,7 @@ class Viewer:
165
171
  self.log(msg)
166
172
  self.database.window.ui.debug["db"].browser.update_table_view()
167
173
 
168
- def update_row(self, data: dict):
174
+ def update_row(self, data: Dict[str, Any]):
169
175
  """
170
176
  Update row in the database.
171
177
 
@@ -216,7 +222,7 @@ class Viewer:
216
222
  self.log(msg)
217
223
  self.database.window.ui.debug["db"].browser.update_table_view()
218
224
 
219
- def truncate_table(self, data: dict, reset: bool = False):
225
+ def truncate_table(self, data: Dict[str, Any], reset: bool = False):
220
226
  """
221
227
  Truncate table in the database.
222
228