pygpt-net 2.6.1__py3-none-any.whl → 2.6.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 (131) hide show
  1. pygpt_net/CHANGELOG.txt +23 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +20 -1
  4. pygpt_net/config.py +55 -65
  5. pygpt_net/controller/__init__.py +5 -2
  6. pygpt_net/controller/calendar/note.py +101 -126
  7. pygpt_net/controller/chat/chat.py +38 -35
  8. pygpt_net/controller/chat/render.py +154 -214
  9. pygpt_net/controller/chat/response.py +5 -3
  10. pygpt_net/controller/chat/stream.py +92 -27
  11. pygpt_net/controller/config/config.py +39 -42
  12. pygpt_net/controller/config/field/checkbox.py +16 -12
  13. pygpt_net/controller/config/field/checkbox_list.py +36 -31
  14. pygpt_net/controller/config/field/cmd.py +51 -57
  15. pygpt_net/controller/config/field/combo.py +33 -16
  16. pygpt_net/controller/config/field/dictionary.py +48 -55
  17. pygpt_net/controller/config/field/input.py +50 -32
  18. pygpt_net/controller/config/field/slider.py +40 -45
  19. pygpt_net/controller/config/field/textarea.py +20 -6
  20. pygpt_net/controller/config/placeholder.py +110 -231
  21. pygpt_net/controller/ctx/common.py +48 -48
  22. pygpt_net/controller/ctx/ctx.py +91 -132
  23. pygpt_net/controller/lang/mapping.py +57 -95
  24. pygpt_net/controller/lang/plugins.py +64 -55
  25. pygpt_net/controller/lang/settings.py +39 -38
  26. pygpt_net/controller/layout/layout.py +176 -109
  27. pygpt_net/controller/mode/mode.py +88 -85
  28. pygpt_net/controller/model/model.py +73 -73
  29. pygpt_net/controller/plugins/plugins.py +209 -223
  30. pygpt_net/controller/plugins/presets.py +54 -55
  31. pygpt_net/controller/plugins/settings.py +54 -69
  32. pygpt_net/controller/presets/editor.py +33 -88
  33. pygpt_net/controller/presets/experts.py +20 -1
  34. pygpt_net/controller/presets/presets.py +293 -298
  35. pygpt_net/controller/settings/profile.py +16 -4
  36. pygpt_net/controller/theme/theme.py +72 -81
  37. pygpt_net/controller/ui/mode.py +118 -186
  38. pygpt_net/controller/ui/tabs.py +69 -90
  39. pygpt_net/controller/ui/ui.py +47 -56
  40. pygpt_net/controller/ui/vision.py +24 -23
  41. pygpt_net/core/agents/runner.py +15 -7
  42. pygpt_net/core/bridge/bridge.py +5 -5
  43. pygpt_net/core/command/command.py +149 -219
  44. pygpt_net/core/ctx/ctx.py +94 -146
  45. pygpt_net/core/debug/debug.py +48 -58
  46. pygpt_net/core/experts/experts.py +3 -3
  47. pygpt_net/core/models/models.py +74 -112
  48. pygpt_net/core/modes/modes.py +13 -21
  49. pygpt_net/core/plugins/plugins.py +154 -177
  50. pygpt_net/core/presets/presets.py +103 -176
  51. pygpt_net/core/render/web/body.py +217 -215
  52. pygpt_net/core/render/web/renderer.py +330 -474
  53. pygpt_net/core/text/utils.py +28 -44
  54. pygpt_net/core/tokens/tokens.py +104 -203
  55. pygpt_net/data/config/config.json +3 -3
  56. pygpt_net/data/config/models.json +3 -3
  57. pygpt_net/data/locale/locale.de.ini +2 -0
  58. pygpt_net/data/locale/locale.en.ini +2 -0
  59. pygpt_net/data/locale/locale.es.ini +2 -0
  60. pygpt_net/data/locale/locale.fr.ini +2 -0
  61. pygpt_net/data/locale/locale.it.ini +2 -0
  62. pygpt_net/data/locale/locale.pl.ini +3 -1
  63. pygpt_net/data/locale/locale.uk.ini +2 -0
  64. pygpt_net/data/locale/locale.zh.ini +2 -0
  65. pygpt_net/item/ctx.py +141 -139
  66. pygpt_net/plugin/agent/plugin.py +2 -1
  67. pygpt_net/plugin/audio_output/plugin.py +5 -2
  68. pygpt_net/plugin/base/plugin.py +101 -85
  69. pygpt_net/plugin/bitbucket/__init__.py +12 -0
  70. pygpt_net/plugin/bitbucket/config.py +267 -0
  71. pygpt_net/plugin/bitbucket/plugin.py +126 -0
  72. pygpt_net/plugin/bitbucket/worker.py +569 -0
  73. pygpt_net/plugin/cmd_code_interpreter/plugin.py +3 -2
  74. pygpt_net/plugin/cmd_custom/plugin.py +3 -2
  75. pygpt_net/plugin/cmd_files/plugin.py +3 -2
  76. pygpt_net/plugin/cmd_history/plugin.py +3 -2
  77. pygpt_net/plugin/cmd_mouse_control/plugin.py +5 -2
  78. pygpt_net/plugin/cmd_serial/plugin.py +3 -2
  79. pygpt_net/plugin/cmd_system/plugin.py +3 -6
  80. pygpt_net/plugin/cmd_web/plugin.py +3 -2
  81. pygpt_net/plugin/experts/plugin.py +2 -2
  82. pygpt_net/plugin/facebook/__init__.py +12 -0
  83. pygpt_net/plugin/facebook/config.py +359 -0
  84. pygpt_net/plugin/facebook/plugin.py +113 -0
  85. pygpt_net/plugin/facebook/worker.py +698 -0
  86. pygpt_net/plugin/github/__init__.py +12 -0
  87. pygpt_net/plugin/github/config.py +441 -0
  88. pygpt_net/plugin/github/plugin.py +126 -0
  89. pygpt_net/plugin/github/worker.py +674 -0
  90. pygpt_net/plugin/google/__init__.py +12 -0
  91. pygpt_net/plugin/google/config.py +367 -0
  92. pygpt_net/plugin/google/plugin.py +126 -0
  93. pygpt_net/plugin/google/worker.py +826 -0
  94. pygpt_net/plugin/idx_llama_index/plugin.py +3 -2
  95. pygpt_net/plugin/mailer/plugin.py +3 -5
  96. pygpt_net/plugin/openai_vision/plugin.py +3 -2
  97. pygpt_net/plugin/real_time/plugin.py +52 -60
  98. pygpt_net/plugin/slack/__init__.py +12 -0
  99. pygpt_net/plugin/slack/config.py +349 -0
  100. pygpt_net/plugin/slack/plugin.py +115 -0
  101. pygpt_net/plugin/slack/worker.py +639 -0
  102. pygpt_net/plugin/telegram/__init__.py +12 -0
  103. pygpt_net/plugin/telegram/config.py +308 -0
  104. pygpt_net/plugin/telegram/plugin.py +117 -0
  105. pygpt_net/plugin/telegram/worker.py +563 -0
  106. pygpt_net/plugin/twitter/__init__.py +12 -0
  107. pygpt_net/plugin/twitter/config.py +491 -0
  108. pygpt_net/plugin/twitter/plugin.py +125 -0
  109. pygpt_net/plugin/twitter/worker.py +837 -0
  110. pygpt_net/provider/agents/llama_index/legacy/openai_assistant.py +35 -3
  111. pygpt_net/tools/code_interpreter/tool.py +0 -1
  112. pygpt_net/tools/translator/tool.py +1 -1
  113. pygpt_net/ui/base/config_dialog.py +86 -100
  114. pygpt_net/ui/base/context_menu.py +48 -46
  115. pygpt_net/ui/dialog/preset.py +34 -77
  116. pygpt_net/ui/layout/ctx/ctx_list.py +10 -6
  117. pygpt_net/ui/layout/toolbox/presets.py +41 -41
  118. pygpt_net/ui/main.py +49 -31
  119. pygpt_net/ui/tray.py +61 -60
  120. pygpt_net/ui/widget/calendar/select.py +86 -70
  121. pygpt_net/ui/widget/lists/attachment.py +86 -44
  122. pygpt_net/ui/widget/lists/base_list_combo.py +85 -33
  123. pygpt_net/ui/widget/lists/context.py +135 -188
  124. pygpt_net/ui/widget/lists/preset.py +59 -61
  125. pygpt_net/ui/widget/textarea/web.py +161 -48
  126. pygpt_net/utils.py +8 -1
  127. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/METADATA +164 -2
  128. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/RECORD +131 -103
  129. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/LICENSE +0 -0
  130. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/WHEEL +0 -0
  131. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.6.dist-info}/entry_points.txt +0 -0
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.06.28 16:00:00 #
9
+ # Updated Date: 2025.08.15 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from pygpt_net.core.events import Event, AppEvent
@@ -24,18 +24,21 @@ class Mode:
24
24
  self.window = window
25
25
  self.locked = False
26
26
 
27
+ @staticmethod
28
+ def _normalize_mode(mode: str) -> str:
29
+ if mode == "langchain":
30
+ print("Langchain mode is deprecated from v2.5.20 and no longer supported. "
31
+ "Please use LlamaIndex or Chat mode instead.")
32
+ return "chat"
33
+ return mode
34
+
27
35
  def select(self, mode: str):
28
36
  """
29
37
  Select mode by id
30
38
 
31
39
  :param mode
32
40
  """
33
- # --- deprecated from v2.5.20 ---
34
- if mode == "langchain":
35
- print("Langchain mode is deprecated from v2.5.20 and no longer supported. "
36
- "Please use LlamaIndex or Chat mode instead.")
37
- mode = "chat"
38
- # --- end of deprecated ---
41
+ mode = self._normalize_mode(mode)
39
42
 
40
43
  # check if mode change is not locked
41
44
  if self.change_locked() or mode is None:
@@ -45,11 +48,13 @@ class Mode:
45
48
  event = Event(Event.MODE_SELECT, {
46
49
  'value': mode,
47
50
  })
48
- self.window.dispatch(event)
49
- self.window.controller.attachment.update()
50
- self.window.controller.chat.attachment.update()
51
- self.window.controller.chat.audio.update()
52
- self.window.dispatch(AppEvent(AppEvent.MODE_SELECTED)) # app event
51
+ w = self.window
52
+ w.dispatch(event)
53
+ c = w.controller
54
+ c.attachment.update()
55
+ c.chat.attachment.update()
56
+ c.chat.audio.update()
57
+ w.dispatch(AppEvent(AppEvent.MODE_SELECTED)) # app event
53
58
 
54
59
  def set(self, mode: str):
55
60
  """
@@ -57,49 +62,49 @@ class Mode:
57
62
 
58
63
  :param mode: mode name
59
64
  """
60
- # --- deprecated from v2.5.20 ---
61
- if mode == "langchain":
62
- print("Langchain mode is deprecated from v2.5.20 and no longer supported. "
63
- "Please use LlamaIndex or Chat mode instead.")
64
- mode = "chat"
65
- # --- end of deprecated ---
65
+ mode = self._normalize_mode(mode)
66
66
 
67
67
  self.locked = True
68
- # if ctx loaded with assistant ID assigned then switch to assistant from ctx
69
- if mode == "assistant":
70
- self.window.controller.presets.select_default()
71
- if self.window.core.ctx.get_current() is not None \
72
- and self.window.core.ctx.get_assistant() is not None:
73
- self.window.controller.assistant.select_by_id(
74
- self.window.core.ctx.get_assistant()
75
- )
76
- else:
77
- self.window.controller.assistant.select_current()
78
-
79
- self.window.core.config.set('mode', mode)
80
-
81
- # reset model and preset at start
82
- self.window.core.config.set('model', "")
83
- self.window.core.config.set('preset', "")
84
-
85
- # update
86
- self.window.controller.attachment.update()
87
- self.window.controller.ctx.update_ctx()
88
-
89
- # update toolbox, mode, presets, model, assistant and rest of the UI
90
- self.window.controller.ui.update()
91
-
92
- # update model list
93
- self.window.controller.model.init_list()
94
- self.window.controller.model.select_current()
95
-
96
- # set status: ready
97
- self.window.update_status(trans('status.started'))
98
-
99
- # if assistant mode then update ctx label
100
- if mode == "assistant":
101
- self.window.controller.ctx.common.update_label_by_current()
102
- self.locked = False
68
+ w = self.window
69
+ c = w.controller
70
+ core = w.core
71
+ cfg = core.config
72
+ try:
73
+ if mode == "assistant":
74
+ c.presets.select_default()
75
+ core_ctx = core.ctx
76
+ current = core_ctx.get_current()
77
+ assistant_id = core_ctx.get_assistant()
78
+ if current is not None and assistant_id is not None:
79
+ c.assistant.select_by_id(assistant_id)
80
+ else:
81
+ c.assistant.select_current()
82
+
83
+ cfg.set('mode', mode)
84
+
85
+ # reset model and preset at start
86
+ cfg.set('model', "")
87
+ cfg.set('preset', "")
88
+
89
+ # update
90
+ c.attachment.update()
91
+ c.ctx.update_ctx()
92
+
93
+ # update toolbox, mode, presets, model, assistant and rest of the UI
94
+ c.ui.update()
95
+
96
+ # update model list
97
+ c.model.init_list()
98
+ c.model.select_current()
99
+
100
+ # set status: ready
101
+ w.update_status(trans('status.started'))
102
+
103
+ # if assistant mode then update ctx label
104
+ if mode == "assistant":
105
+ c.ctx.common.update_label_by_current()
106
+ finally:
107
+ self.locked = False
103
108
 
104
109
  def select_on_list(self, mode: str):
105
110
  """
@@ -107,21 +112,13 @@ class Mode:
107
112
 
108
113
  :param mode: mode name
109
114
  """
110
- # --- deprecated from v2.5.20 ---
111
- if mode == "langchain":
112
- print("Langchain mode is deprecated from v2.5.20 and no longer supported. "
113
- "Please use LlamaIndex or Chat mode instead.")
114
- mode = "chat"
115
- # --- end of deprecated ---
116
-
115
+ mode = self._normalize_mode(mode)
117
116
  self.window.ui.nodes["prompt.mode"].set_value(mode)
118
117
 
119
118
  def init_list(self):
120
119
  """Init modes list"""
121
- items = {}
122
120
  data = self.window.core.modes.get_all()
123
- for k in data:
124
- items[k] = trans(data[k].label)
121
+ items = {k: trans(v.label) for k, v in data.items()}
125
122
  self.window.ui.nodes["prompt.mode"].set_keys(items)
126
123
 
127
124
  def select_current(self):
@@ -132,16 +129,18 @@ class Mode:
132
129
 
133
130
  def select_default(self):
134
131
  """Set default mode"""
135
- mode = self.window.core.config.get('mode')
132
+ cfg = self.window.core.config
133
+ mode = cfg.get('mode')
136
134
  if mode is None or mode == "":
137
- self.window.core.config.set('mode', self.window.core.modes.get_default())
135
+ cfg.set('mode', self.window.core.modes.get_default())
138
136
 
139
137
  def default_all(self):
140
138
  """Set default mode, model and preset"""
139
+ c = self.window.controller
141
140
  self.select_default()
142
- self.window.controller.model.select_default()
143
- self.window.controller.presets.select_default()
144
- self.window.controller.assistant.select_default()
141
+ c.model.select_default()
142
+ c.presets.select_default()
143
+ c.assistant.select_default()
145
144
 
146
145
  def update_temperature(self, temperature: float = None):
147
146
  """
@@ -151,13 +150,14 @@ class Mode:
151
150
  :type temperature: float or None
152
151
  """
153
152
  if temperature is None:
154
- if self.window.core.config.get('preset') is None or self.window.core.config.get('preset') == "":
153
+ cfg = self.window.core.config
154
+ preset_id = cfg.get('preset')
155
+ if preset_id is None or preset_id == "":
155
156
  temperature = 1.0 # default temperature
156
157
  else:
157
- id = self.window.core.config.get('preset')
158
- if id in self.window.core.presets.items:
159
- temperature = float(self.window.core.presets.items[id].temperature or 1.0)
160
- option = self.window.controller.settings.editor.get_options()["temperature"]
158
+ items = self.window.core.presets.items
159
+ if preset_id in items:
160
+ temperature = float(items[preset_id].temperature or 1.0)
161
161
  '''
162
162
  self.window.controller.config.slider.on_update("global", "current_temperature", option, temperature,
163
163
  hooks=False) # disable hooks to prevent circular update
@@ -178,11 +178,13 @@ class Mode:
178
178
  return # accept call only from slider (has already validated min/max)
179
179
 
180
180
  temperature = value / 100
181
- self.window.core.config.set("temperature", temperature)
182
- preset_id = self.window.core.config.get('preset')
181
+ cfg = self.window.core.config
182
+ cfg.set("temperature", temperature)
183
+ preset_id = cfg.get('preset')
183
184
  if preset_id is not None and preset_id != "":
184
- if preset_id in self.window.core.presets.items:
185
- preset = self.window.core.presets.items[preset_id]
185
+ items = self.window.core.presets.items
186
+ if preset_id in items:
187
+ preset = items[preset_id]
186
188
  preset.temperature = temperature
187
189
  self.window.core.presets.save(preset_id)
188
190
 
@@ -215,21 +217,22 @@ class Mode:
215
217
 
216
218
  def reset_current(self):
217
219
  """Reset current setup"""
218
- self.window.core.config.set('prompt', None)
219
- self.window.core.config.set('ai_name', None)
220
- self.window.core.config.set('user_name', None)
220
+ cfg = self.window.core.config
221
+ cfg.set('prompt', None)
222
+ cfg.set('ai_name', None)
223
+ cfg.set('user_name', None)
221
224
 
222
225
  def next(self):
223
226
  """Select next mode"""
224
227
  mode = self.window.core.config.get('mode')
225
- next = self.window.core.modes.get_next(mode)
226
- self.select(next)
228
+ nxt = self.window.core.modes.get_next(mode)
229
+ self.select(nxt)
227
230
 
228
231
  def prev(self):
229
232
  """Select previous mode"""
230
233
  mode = self.window.core.config.get('mode')
231
- prev = self.window.core.modes.get_prev(mode)
232
- self.select(prev)
234
+ prv = self.window.core.modes.get_prev(mode)
235
+ self.select(prv)
233
236
 
234
237
  def change_locked(self) -> bool:
235
238
  """
@@ -238,4 +241,4 @@ class Mode:
238
241
  :return: True if locked
239
242
  :rtype: bool
240
243
  """
241
- return self.window.controller.chat.input.generating
244
+ return bool(self.window.controller.chat.input.generating)
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2025.08.07 02:00:00 #
9
+ # Updated Date: 2025.08.15 03:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  from typing import Optional
@@ -29,57 +29,55 @@ class Model:
29
29
  self.editor = Editor(window)
30
30
  self.importer = Importer(window)
31
31
 
32
+ def _ensure_current_model_map(self):
33
+ return self.window.core.config.data.setdefault('current_model', {})
34
+
32
35
  def select(self, model: str):
33
36
  """
34
37
  Select model
35
38
 
36
39
  :param model: model ID
37
40
  """
38
- # check if model change is not locked
39
41
  if self.change_locked():
40
42
  return
41
43
 
42
- mode = self.window.core.config.get('mode')
43
- self.window.core.config.set('model', model)
44
- if 'current_model' not in self.window.core.config.data:
45
- self.window.core.config.data['current_model'] = {}
46
- self.window.core.config.data['current_model'][mode] = model
47
-
48
- event = Event(Event.MODEL_SELECT, {
49
- 'value': model,
50
- })
51
- self.window.dispatch(event)
44
+ w = self.window
45
+ cfg = w.core.config
46
+ mode = cfg.get('mode')
47
+ cfg.set('model', model)
48
+ self._ensure_current_model_map()[mode] = model
52
49
 
53
- # update all layout
54
- self.window.controller.ui.update()
55
- self.window.dispatch(AppEvent(AppEvent.MODEL_SELECTED)) # app event
50
+ w.dispatch(Event(Event.MODEL_SELECT, {'value': model}))
51
+ w.controller.ui.update()
52
+ w.dispatch(AppEvent(AppEvent.MODEL_SELECTED))
56
53
 
57
- # update model in preset
58
- preset = self.window.core.config.get('preset')
54
+ preset = cfg.get('preset')
59
55
  if preset and preset != "*":
60
- preset_data = self.window.core.presets.get_by_id(mode, preset)
56
+ preset_data = w.core.presets.get_by_id(mode, preset)
61
57
  if preset_data:
62
58
  preset_data.model = model
63
- self.window.core.presets.save(preset)
59
+ w.core.presets.save(preset)
64
60
 
65
- # update model in current ctx meta
66
- self.window.core.ctx.model = model
67
- self.window.core.ctx.last_model = model
68
- self.window.core.ctx.update_model_in_current(model)
61
+ ctx = w.core.ctx
62
+ ctx.model = model
63
+ ctx.last_model = model
64
+ ctx.update_model_in_current(model)
69
65
 
70
66
  def next(self):
71
67
  """Select next model"""
72
- mode = self.window.core.config.get('mode')
73
- model = self.window.core.config.get('model')
74
- next = self.window.core.models.get_next(model, mode)
75
- self.select(next)
68
+ w = self.window
69
+ mode = w.core.config.get('mode')
70
+ model = w.core.config.get('model')
71
+ next_model = w.core.models.get_next(model, mode)
72
+ self.select(next_model)
76
73
 
77
74
  def prev(self):
78
75
  """Select previous model"""
79
- mode = self.window.core.config.get('mode')
80
- model = self.window.core.config.get('model')
81
- prev = self.window.core.models.get_prev(model, mode)
82
- self.select(prev)
76
+ w = self.window
77
+ mode = w.core.config.get('mode')
78
+ model = w.core.config.get('model')
79
+ prev_model = w.core.models.get_prev(model, mode)
80
+ self.select(prev_model)
83
81
 
84
82
  def set(self, mode: str, model: str):
85
83
  """
@@ -88,10 +86,9 @@ class Model:
88
86
  :param mode: mode name
89
87
  :param model: model name
90
88
  """
91
- self.window.core.config.set('model', model)
92
- if 'current_model' not in self.window.core.config.data:
93
- self.window.core.config.data['current_model'] = {}
94
- self.window.core.config.data['current_model'][mode] = model
89
+ w = self.window
90
+ w.core.config.set('model', model)
91
+ self._ensure_current_model_map()[mode] = model
95
92
 
96
93
  def set_by_idx(self, mode: str, idx: int):
97
94
  """
@@ -100,16 +97,11 @@ class Model:
100
97
  :param mode: mode name
101
98
  :param idx: model index
102
99
  """
103
- model = self.window.core.models.get_by_idx(idx, mode)
104
- self.window.core.config.set('model', model)
105
- if 'current_model' not in self.window.core.config.data:
106
- self.window.core.config.data['current_model'] = {}
107
- self.window.core.config.data['current_model'][mode] = model
108
-
109
- event = Event(Event.MODEL_SELECT, {
110
- 'value': model,
111
- })
112
- self.window.dispatch(event)
100
+ w = self.window
101
+ model = w.core.models.get_by_idx(idx, mode)
102
+ w.core.config.set('model', model)
103
+ self._ensure_current_model_map()[mode] = model
104
+ w.dispatch(Event(Event.MODEL_SELECT, {'value': model}))
113
105
 
114
106
  def select_on_list(self, model: str):
115
107
  """
@@ -121,28 +113,29 @@ class Model:
121
113
 
122
114
  def select_current(self):
123
115
  """Select current model on list"""
124
- mode = self.window.core.config.get('mode')
125
- model = self.window.core.config.get('model')
126
- items = self.window.core.models.get_by_mode(mode)
116
+ w = self.window
117
+ mode = w.core.config.get('mode')
118
+ model = w.core.config.get('model')
119
+ items = w.core.models.get_by_mode(mode)
127
120
  if model in items:
128
121
  self.select_on_list(model)
129
122
 
130
123
  def select_default(self):
131
124
  """Set default model"""
132
- model = self.window.core.config.get('model')
125
+ w = self.window
126
+ model = w.core.config.get('model')
133
127
  if model is None or model == "":
134
- mode = self.window.core.config.get('mode')
135
-
136
- # set previous selected model
137
- current_models = self.window.core.config.get('current_model')
138
- if mode in current_models and \
139
- current_models[mode] is not None and \
140
- current_models[mode] != "" and \
141
- current_models[mode] in self.window.core.models.get_by_mode(mode):
142
- self.window.core.config.set('model', current_models[mode])
128
+ mode = w.core.config.get('mode')
129
+ current_models = w.core.config.get('current_model') or {}
130
+ mode_items = w.core.models.get_by_mode(mode)
131
+ if (
132
+ mode in current_models
133
+ and current_models[mode]
134
+ and current_models[mode] in mode_items
135
+ ):
136
+ w.core.config.set('model', current_models[mode])
143
137
  else:
144
- # or set default model
145
- self.window.core.config.set('model', self.window.core.models.get_default(mode))
138
+ w.core.config.set('model', w.core.models.get_default(mode))
146
139
 
147
140
  def switch_inline(
148
141
  self,
@@ -158,7 +151,7 @@ class Model:
158
151
  """
159
152
  event = Event(Event.MODEL_BEFORE, {
160
153
  'mode': mode,
161
- 'model': model, # model instance
154
+ 'model': model,
162
155
  })
163
156
  self.window.dispatch(event)
164
157
  tmp_model = event.data['model']
@@ -168,21 +161,28 @@ class Model:
168
161
 
169
162
  def init_list(self):
170
163
  """Init models list"""
171
- mode = self.window.core.config.get('mode')
172
- items = {}
173
- data = self.window.core.models.get_by_mode(mode)
174
- for k in data:
175
- items[k] = data[k].name
176
-
177
- providers = self.window.core.llm.get_choices()
164
+ w = self.window
165
+ mode = w.core.config.get('mode')
166
+ data = w.core.models.get_by_mode(mode)
167
+
168
+ items_by_provider = {}
169
+ for k, item in data.items():
170
+ p = item.provider
171
+ d = items_by_provider.get(p)
172
+ if d is None:
173
+ d = {}
174
+ items_by_provider[p] = d
175
+ d[k] = item.name
176
+
177
+ providers = w.core.llm.get_choices()
178
178
  sorted_items = {}
179
- for provider in providers.keys():
180
- provider_items = {k: v for k, v in items.items() if data[k].provider == provider}
179
+ for provider, label in providers.items():
180
+ provider_items = items_by_provider.get(provider)
181
181
  if provider_items:
182
- sorted_items[f"separator::{provider}"] = providers[provider]
182
+ sorted_items[f"separator::{provider}"] = label
183
183
  sorted_items.update(provider_items)
184
184
 
185
- self.window.ui.nodes["prompt.model"].set_keys(sorted_items)
185
+ w.ui.nodes["prompt.model"].set_keys(sorted_items)
186
186
 
187
187
  def reload(self):
188
188
  """Reload models"""
@@ -200,4 +200,4 @@ class Model:
200
200
 
201
201
  :return: True if locked
202
202
  """
203
- return self.window.controller.chat.input.generating
203
+ return self.window.controller.chat.input.generating