pygpt-net 2.6.27__py3-none-any.whl → 2.6.29__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 (44) hide show
  1. pygpt_net/CHANGELOG.txt +12 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +5 -1
  4. pygpt_net/controller/kernel/kernel.py +2 -0
  5. pygpt_net/controller/notepad/notepad.py +10 -1
  6. pygpt_net/controller/theme/common.py +2 -0
  7. pygpt_net/controller/theme/markdown.py +2 -0
  8. pygpt_net/controller/theme/theme.py +3 -0
  9. pygpt_net/controller/ui/tabs.py +5 -0
  10. pygpt_net/core/audio/backend/native.py +1 -3
  11. pygpt_net/core/command/command.py +2 -0
  12. pygpt_net/core/idx/llm.py +21 -3
  13. pygpt_net/core/render/web/helpers.py +13 -3
  14. pygpt_net/core/render/web/renderer.py +3 -3
  15. pygpt_net/data/config/config.json +3 -3
  16. pygpt_net/data/config/models.json +3 -3
  17. pygpt_net/data/config/settings.json +27 -28
  18. pygpt_net/data/css/web-blocks.darkest.css +91 -0
  19. pygpt_net/data/css/web-chatgpt.css +7 -5
  20. pygpt_net/data/css/web-chatgpt.dark.css +5 -2
  21. pygpt_net/data/css/web-chatgpt.darkest.css +91 -0
  22. pygpt_net/data/css/web-chatgpt.light.css +8 -2
  23. pygpt_net/data/css/web-chatgpt_wide.css +7 -4
  24. pygpt_net/data/css/web-chatgpt_wide.dark.css +5 -2
  25. pygpt_net/data/css/web-chatgpt_wide.darkest.css +91 -0
  26. pygpt_net/data/css/web-chatgpt_wide.light.css +9 -6
  27. pygpt_net/data/themes/dark_darkest.css +31 -0
  28. pygpt_net/data/themes/dark_darkest.xml +10 -0
  29. pygpt_net/plugin/tuya/__init__.py +12 -0
  30. pygpt_net/plugin/tuya/config.py +256 -0
  31. pygpt_net/plugin/tuya/plugin.py +117 -0
  32. pygpt_net/plugin/tuya/worker.py +588 -0
  33. pygpt_net/plugin/wikipedia/__init__.py +12 -0
  34. pygpt_net/plugin/wikipedia/config.py +228 -0
  35. pygpt_net/plugin/wikipedia/plugin.py +114 -0
  36. pygpt_net/plugin/wikipedia/worker.py +430 -0
  37. pygpt_net/provider/core/config/patch.py +11 -0
  38. pygpt_net/ui/widget/tabs/output.py +2 -0
  39. pygpt_net/ui/widget/textarea/input.py +10 -7
  40. {pygpt_net-2.6.27.dist-info → pygpt_net-2.6.29.dist-info}/METADATA +50 -6
  41. {pygpt_net-2.6.27.dist-info → pygpt_net-2.6.29.dist-info}/RECORD +44 -31
  42. {pygpt_net-2.6.27.dist-info → pygpt_net-2.6.29.dist-info}/LICENSE +0 -0
  43. {pygpt_net-2.6.27.dist-info → pygpt_net-2.6.29.dist-info}/WHEEL +0 -0
  44. {pygpt_net-2.6.27.dist-info → pygpt_net-2.6.29.dist-info}/entry_points.txt +0 -0
@@ -55,10 +55,11 @@ p {{
55
55
 
56
56
  /* cmd */
57
57
  .cmd {{
58
- font-family: 'Lato';
58
+ font-family: 'Monaspace Neon';
59
59
  text-decoration: none;
60
+ padding-top: 5px;
60
61
  padding-bottom: 0px;
61
- font-size: 0.8rem;
62
+ font-size: 0.75rem;
62
63
  }}
63
64
 
64
65
  /* lists, code */
@@ -245,12 +246,14 @@ code {{
245
246
  color: gray;
246
247
  }}
247
248
  .tool-output .content {{
249
+ font-family: 'Monaspace Neon';
248
250
  padding: 10px;
249
251
  color: gray !important;
252
+ font-size: 0.75rem;
250
253
  }}
251
254
  .tool-output .toggle-cmd-output {{
252
255
  cursor: pointer;
253
- padding-top: 10px;
256
+ padding-top: 0px;
254
257
  display: block;
255
258
  color: gray;
256
259
  }}
@@ -303,7 +306,7 @@ code {{
303
306
  height: 150px;
304
307
  margin: 0;
305
308
  margin-bottom: 0px !important;
306
- border-radius: 5px;
309
+ border-radius: 0;
307
310
  width: auto;
308
311
  }}
309
312
  .extra-src-img-box .img-wrapper:hover {{
@@ -18,7 +18,7 @@ p {{
18
18
  color: #fff;
19
19
  }}
20
20
  a {{
21
- color: #a1b5c4 !important;
21
+ color: #b5c3cd !important;
22
22
  }}
23
23
  a:hover {{
24
24
  color: #b8cad7 !important;
@@ -37,7 +37,7 @@ a:hover {{
37
37
  color: #fff;
38
38
  }}
39
39
  .cmd {{
40
- color: #4d4d4d;
40
+ color: #4d4d4d !important;
41
41
  }}
42
42
  .ts {{
43
43
  color: #4d4d4d;
@@ -71,6 +71,9 @@ code {{
71
71
  .name-user::before {{
72
72
  background-color: silver;
73
73
  }}
74
+ .tool-output .content {{
75
+ color: #4d4d4d !important;
76
+ }}
74
77
 
75
78
  /* loader */
76
79
  .lds-ring {{
@@ -0,0 +1,91 @@
1
+ body {{
2
+ color: #fff;
3
+ background-color: #202020;
4
+ }}
5
+ ::-webkit-scrollbar {{
6
+ background: #1c1c1c;
7
+ }}
8
+ ::-webkit-scrollbar-thumb {{
9
+ background: #282828;
10
+ }}
11
+ ::-webkit-scrollbar-thumb:hover {{
12
+ background: #333333;
13
+ }}
14
+ ::-webkit-scrollbar-corner {{
15
+ background: #232629;
16
+ }}
17
+ p {{
18
+ color: #fff;
19
+ }}
20
+ a {{
21
+ color: #b5c3cd !important;
22
+ }}
23
+ a:hover {{
24
+ color: #b8cad7 !important;
25
+ }}
26
+ .msg-user {{
27
+ background: #303030;
28
+ color: #fff;
29
+ }}
30
+ .msg-user p {{
31
+ color: #fff;
32
+ }}
33
+ .msg-bot {{
34
+ color: #fff;
35
+ }}
36
+ .msg-bot p {{
37
+ color: #fff;
38
+ }}
39
+ .cmd {{
40
+ color: #4d4d4d !important;
41
+ }}
42
+ .ts {{
43
+ color: #4d4d4d;
44
+ }}
45
+ .list {{
46
+ }}
47
+ code {{
48
+ color: {QTMATERIAL_PRIMARYLIGHTCOLOR};
49
+ }}
50
+ .code-header-wrapper {{
51
+ background-color: #303030;
52
+ }}
53
+ .code-header-action {{
54
+ color: silver !important;
55
+ }}
56
+ .code-header-action:hover {{
57
+ color: #fff;
58
+ }}
59
+ .code-header-action:hover img {{
60
+ filter: brightness(130%);
61
+ }}
62
+ .code-header-lang {{
63
+ color: #686868;
64
+ }}
65
+ .action-icons a:hover {{
66
+ filter: brightness(130%);
67
+ }}
68
+ .name-bot::before {{
69
+ background-color: {QTMATERIAL_PRIMARYLIGHTCOLOR};
70
+ }}
71
+ .name-user::before {{
72
+ background-color: silver;
73
+ }}
74
+ .tool-output .content {{
75
+ color: #4d4d4d !important;
76
+ }}
77
+
78
+ /* loader */
79
+ .lds-ring {{
80
+ color: #fff;
81
+ }}
82
+ .append_live {{
83
+ color: gray;
84
+ }}
85
+
86
+ .tips p {{
87
+ color: #5e5e5e;
88
+ }}
89
+ .msg-box .name-header.name-bot {{
90
+ color: #cfcfcf;
91
+ }}
@@ -18,9 +18,13 @@ p {{
18
18
  color: #000;
19
19
  }}
20
20
  a {{
21
- color: #3b7097 !important;
21
+ color: #2b4e67 !important;
22
+ }}
23
+ a:hover {{
24
+ color: #426f90 !important;
22
25
  }}
23
26
  .msg-user {{
27
+ background-color: #f3f3f3;
24
28
  color: #000;
25
29
  }}
26
30
  .msg-user p {{
@@ -33,7 +37,7 @@ a {{
33
37
  color: #000;
34
38
  }}
35
39
  .cmd {{
36
- color: #4d4d4d;
40
+ color: #888787 !important;
37
41
  text-decoration: none;
38
42
  }}
39
43
  .ts {{
@@ -63,10 +67,6 @@ code {{
63
67
  .code-header-lang {{
64
68
  color: #5c5c5c;
65
69
  }}
66
- .msg-user {{
67
- background-color: #f3f3f3;
68
- color: #000;
69
- }}
70
70
  .name-bot::before {{
71
71
  background-color: #6b6b6b;
72
72
  }}
@@ -76,6 +76,9 @@ code {{
76
76
  .action-icons a:hover {{
77
77
  filter: brightness(60%);
78
78
  }}
79
+ .tool-output .content {{
80
+ color: #888787 !important;
81
+ }}
79
82
 
80
83
  /* loader */
81
84
  .lds-ring {{
@@ -0,0 +1,31 @@
1
+ .layout-output-web {{
2
+ background-color: #202020 !important;
3
+ }}
4
+ QListView::item:selected,
5
+ QTreeView::item:selected {{
6
+ color: #ffffff;
7
+ selection-color: #ffffff;
8
+ }}
9
+ QComboBox::item:selected {{
10
+ color: #000;
11
+ selection-color: #000;
12
+ }}
13
+ QComboBox::item:disabled {{
14
+ color: #d1d2d2;
15
+ }}
16
+ QListView::item:selected:focus,
17
+ QComboBox::item:selected:focus,
18
+ QTreeView::item:selected:focus {{
19
+ color: #ffffff;
20
+ selection-color: #000000;
21
+ }}
22
+ QListView::item::disabled {{
23
+ color: #959595;
24
+ font-weight: bold;
25
+ }}
26
+ QMenuBar::item:selected {{
27
+ color: #000000;
28
+ }}
29
+ QMenu::item:selected {{
30
+ color: #000000;
31
+ }}
@@ -0,0 +1,10 @@
1
+ <!--?xml version="1.0" encoding="UTF-8"?-->
2
+ <resources>
3
+ <color name="primaryColor">#ffffff</color>
4
+ <color name="primaryLightColor">#ffffff</color>
5
+ <color name="secondaryColor">#1b1b1b</color>
6
+ <color name="secondaryLightColor">#202020</color>
7
+ <color name="secondaryDarkColor">#202020</color>
8
+ <color name="primaryTextColor">#ffffff</color>
9
+ <color name="secondaryTextColor">#ffffff</color>
10
+ </resources>
@@ -0,0 +1,12 @@
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: 2025.08.27 20:00:00 #
10
+ # ================================================== #
11
+
12
+ from .plugin import *
@@ -0,0 +1,256 @@
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: 2025.08.27 20:00:00 #
10
+ # ================================================== #
11
+
12
+ from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
13
+
14
+
15
+ class Config(BaseConfig):
16
+ def __init__(self, plugin: BasePlugin = None, *args, **kwargs):
17
+ super(Config, self).__init__(plugin)
18
+ self.plugin = plugin
19
+
20
+ def from_defaults(self, plugin: BasePlugin = None):
21
+ # Endpoints / HTTP
22
+ plugin.add_option(
23
+ "api_base",
24
+ type="text",
25
+ value="https://openapi.tuyaeu.com",
26
+ label="API base",
27
+ description="Tuya API base (eu/us/cn/in: https://openapi.tuyaeu.com / tuyaus / tuyacn / tuyain).",
28
+ )
29
+ plugin.add_option(
30
+ "http_timeout",
31
+ type="int",
32
+ value=30,
33
+ label="HTTP timeout (s)",
34
+ description="Requests timeout in seconds.",
35
+ )
36
+ plugin.add_option(
37
+ "lang",
38
+ type="text",
39
+ value="en",
40
+ label="Language",
41
+ description="Language header (e.g., en, pl).",
42
+ )
43
+
44
+ # Credentials
45
+ plugin.add_option(
46
+ "tuya_client_id",
47
+ type="text",
48
+ value="",
49
+ label="Tuya Client ID",
50
+ description="Client ID from Tuya IoT Platform Cloud project.",
51
+ secret=True,
52
+ )
53
+ plugin.add_option(
54
+ "tuya_client_secret",
55
+ type="text",
56
+ value="",
57
+ label="Tuya Client Secret",
58
+ description="Client secret from Tuya IoT Platform Cloud project.",
59
+ secret=True,
60
+ )
61
+ plugin.add_option(
62
+ "tuya_uid",
63
+ type="text",
64
+ value="",
65
+ label="Tuya UID (App Account)",
66
+ description="UID of linked Tuya App account (required for listing devices).",
67
+ )
68
+
69
+ # Tokens (auto)
70
+ plugin.add_option(
71
+ "tuya_access_token",
72
+ type="textarea",
73
+ value="",
74
+ label="(auto) Access token",
75
+ description="Stored Tuya access token.",
76
+ secret=True,
77
+ )
78
+ plugin.add_option(
79
+ "tuya_refresh_token",
80
+ type="textarea",
81
+ value="",
82
+ label="(auto) Refresh token",
83
+ description="Stored Tuya refresh token (not always used).",
84
+ secret=True,
85
+ )
86
+ plugin.add_option(
87
+ "tuya_token_expires_in",
88
+ type="text",
89
+ value="",
90
+ label="(auto) Expires in (s)",
91
+ description="Token lifetime seconds.",
92
+ )
93
+ plugin.add_option(
94
+ "tuya_token_expire_at",
95
+ type="text",
96
+ value="0",
97
+ label="(auto) Expire at (epoch s)",
98
+ description="Timestamp when token is considered expired.",
99
+ )
100
+
101
+ # Cache
102
+ plugin.add_option(
103
+ "tuya_cached_devices",
104
+ type="textarea",
105
+ value="[]",
106
+ label="(auto) Cached devices",
107
+ description="Cached devices for quick search.",
108
+ )
109
+
110
+ # ---------------- Commands ----------------
111
+
112
+ # Auth
113
+ plugin.add_cmd(
114
+ "tuya_set_keys",
115
+ instruction="Set Tuya Cloud credentials.",
116
+ params=[
117
+ {"name": "client_id", "type": "str", "required": True, "description": "Tuya Client ID"},
118
+ {"name": "client_secret", "type": "str", "required": True, "description": "Tuya Client Secret"},
119
+ ],
120
+ enabled=True,
121
+ description="Auth: set keys",
122
+ tab="auth",
123
+ )
124
+ plugin.add_cmd(
125
+ "tuya_set_uid",
126
+ instruction="Set Tuya App Account UID (for listing devices).",
127
+ params=[
128
+ {"name": "uid", "type": "str", "required": True, "description": "UID of linked Tuya account"},
129
+ ],
130
+ enabled=True,
131
+ description="Auth: set UID",
132
+ tab="auth",
133
+ )
134
+ plugin.add_cmd(
135
+ "tuya_token_get",
136
+ instruction="Obtain access token (grant_type=1).",
137
+ params=[],
138
+ enabled=True,
139
+ description="Auth: get token",
140
+ tab="auth",
141
+ )
142
+
143
+ # Devices
144
+ plugin.add_cmd(
145
+ "tuya_devices_list",
146
+ instruction="List devices for UID.",
147
+ params=[
148
+ {"name": "uid", "type": "str", "required": False, "description": "Override UID (optional)"},
149
+ {"name": "page_no", "type": "int", "required": False, "description": "Page number (default 1)"},
150
+ {"name": "page_size", "type": "int", "required": False, "description": "Page size (default 100)"},
151
+ ],
152
+ enabled=True,
153
+ description="Devices: list",
154
+ tab="devices",
155
+ )
156
+ plugin.add_cmd(
157
+ "tuya_device_get",
158
+ instruction="Get device info.",
159
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Device ID"}],
160
+ enabled=True,
161
+ description="Devices: get info",
162
+ tab="devices",
163
+ )
164
+ plugin.add_cmd(
165
+ "tuya_device_status",
166
+ instruction="Get device status (DP values).",
167
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Device ID"}],
168
+ enabled=True,
169
+ description="Devices: status",
170
+ tab="devices",
171
+ )
172
+ plugin.add_cmd(
173
+ "tuya_device_functions",
174
+ instruction="Get device supported functions (DP codes).",
175
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Device ID"}],
176
+ enabled=True,
177
+ description="Devices: functions",
178
+ tab="devices",
179
+ )
180
+ plugin.add_cmd(
181
+ "tuya_find_device",
182
+ instruction="Find device(s) by name (uses cached device list).",
183
+ params=[{"name": "name", "type": "str", "required": True, "description": "Substring match"}],
184
+ enabled=True,
185
+ description="Devices: find by name",
186
+ tab="devices",
187
+ )
188
+
189
+ # Control
190
+ plugin.add_cmd(
191
+ "tuya_device_set",
192
+ instruction="Set a device DP value or multiple values.",
193
+ params=[
194
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
195
+ {"name": "code", "type": "str", "required": False, "description": "DP code (if single)"},
196
+ {"name": "value", "type": "str", "required": False, "description": "Value for 'code'"},
197
+ {"name": "codes", "type": "dict", "required": False, "description": "Dict of {code: value}"},
198
+ ],
199
+ enabled=True,
200
+ description="Control: set DP(s)",
201
+ tab="control",
202
+ )
203
+ plugin.add_cmd(
204
+ "tuya_device_send",
205
+ instruction="Send raw commands list to device.",
206
+ params=[
207
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
208
+ {"name": "commands", "type": "list", "required": True, "description": "[{'code':'','value':..},...]"},
209
+ ],
210
+ enabled=True,
211
+ description="Control: send commands",
212
+ tab="control",
213
+ )
214
+ plugin.add_cmd(
215
+ "tuya_device_on",
216
+ instruction="Turn device ON (guesses switch code if not provided).",
217
+ params=[
218
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
219
+ {"name": "code", "type": "str", "required": False, "description": "Preferred switch code"},
220
+ ],
221
+ enabled=True,
222
+ description="Control: on",
223
+ tab="control",
224
+ )
225
+ plugin.add_cmd(
226
+ "tuya_device_off",
227
+ instruction="Turn device OFF (guesses switch code if not provided).",
228
+ params=[
229
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
230
+ {"name": "code", "type": "str", "required": False, "description": "Preferred switch code"},
231
+ ],
232
+ enabled=True,
233
+ description="Control: off",
234
+ tab="control",
235
+ )
236
+ plugin.add_cmd(
237
+ "tuya_device_toggle",
238
+ instruction="Toggle device state (reads current boolean DP).",
239
+ params=[
240
+ {"name": "device_id", "type": "str", "required": True, "description": "Device ID"},
241
+ {"name": "code", "type": "str", "required": False, "description": "Preferred switch code"},
242
+ ],
243
+ enabled=True,
244
+ description="Control: toggle",
245
+ tab="control",
246
+ )
247
+
248
+ # Sensors
249
+ plugin.add_cmd(
250
+ "tuya_sensors_read",
251
+ instruction="Read and normalize common sensor values.",
252
+ params=[{"name": "device_id", "type": "str", "required": True, "description": "Sensor device ID"}],
253
+ enabled=True,
254
+ description="Sensors: read",
255
+ tab="sensors",
256
+ )
@@ -0,0 +1,117 @@
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: 2025.08.27 20:00:00 #
10
+ # ================================================== #
11
+
12
+ from pygpt_net.plugin.base.plugin import BasePlugin
13
+ from pygpt_net.core.events import Event
14
+ from pygpt_net.item.ctx import CtxItem
15
+
16
+ from .config import Config
17
+
18
+
19
+ class Plugin(BasePlugin):
20
+ def __init__(self, *args, **kwargs):
21
+ super(Plugin, self).__init__(*args, **kwargs)
22
+ self.id = "tuya"
23
+ self.name = "Tuya (IoT)"
24
+ self.description = "Handle Tuya Smart Home devices via Tuya Cloud API."
25
+ self.prefix = "API"
26
+ self.order = 100
27
+ self.allowed_cmds = [
28
+ "tuya_set_keys",
29
+ "tuya_set_uid",
30
+ "tuya_token_get",
31
+ "tuya_devices_list",
32
+ "tuya_device_get",
33
+ "tuya_device_status",
34
+ "tuya_device_functions",
35
+ "tuya_find_device",
36
+ "tuya_device_set",
37
+ "tuya_device_send",
38
+ "tuya_device_on",
39
+ "tuya_device_off",
40
+ "tuya_device_toggle",
41
+ "tuya_sensors_read"
42
+ ]
43
+ self.use_locale = False
44
+ self.worker = None
45
+ self.config = Config(self)
46
+ self.init_options()
47
+
48
+ def init_options(self):
49
+ """Initialize options"""
50
+ self.config.from_defaults(self)
51
+
52
+ def handle(self, event: Event, *args, **kwargs):
53
+ """
54
+ Handle dispatched event
55
+
56
+ :param event: event object
57
+ :param args: event args
58
+ :param kwargs: event kwargs
59
+ """
60
+ name = event.name
61
+ data = event.data
62
+ ctx = event.ctx
63
+
64
+ if name == Event.CMD_SYNTAX:
65
+ self.cmd_syntax(data)
66
+
67
+ elif name == Event.CMD_EXECUTE:
68
+ self.cmd(
69
+ ctx,
70
+ data['commands'],
71
+ )
72
+
73
+ def cmd_syntax(self, data: dict):
74
+ """
75
+ Event: CMD_SYNTAX
76
+
77
+ :param data: event data dict
78
+ """
79
+ for option in self.allowed_cmds:
80
+ if self.has_cmd(option):
81
+ data['cmd'].append(self.get_cmd(option)) # append command
82
+
83
+ def cmd(self, ctx: CtxItem, cmds: list):
84
+ """
85
+ Event: CMD_EXECUTE
86
+
87
+ :param ctx: CtxItem
88
+ :param cmds: commands dict
89
+ """
90
+ from .worker import Worker
91
+
92
+ is_cmd = False
93
+ my_commands = []
94
+ for item in cmds:
95
+ if item["cmd"] in self.allowed_cmds:
96
+ my_commands.append(item)
97
+ is_cmd = True
98
+
99
+ if not is_cmd:
100
+ return
101
+
102
+ # set state: busy
103
+ self.cmd_prepare(ctx, my_commands)
104
+
105
+ try:
106
+ worker = Worker()
107
+ worker.from_defaults(self)
108
+ worker.cmds = my_commands
109
+ worker.ctx = ctx
110
+
111
+ if not self.is_async(ctx):
112
+ worker.run()
113
+ return
114
+ worker.run_async()
115
+
116
+ except Exception as e:
117
+ self.error(e)