pygpt-net 2.6.1__py3-none-any.whl → 2.6.2__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 (61) hide show
  1. pygpt_net/CHANGELOG.txt +4 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +15 -1
  4. pygpt_net/controller/chat/response.py +5 -3
  5. pygpt_net/controller/chat/stream.py +40 -2
  6. pygpt_net/controller/plugins/plugins.py +25 -0
  7. pygpt_net/controller/presets/editor.py +33 -88
  8. pygpt_net/controller/presets/experts.py +20 -1
  9. pygpt_net/controller/presets/presets.py +2 -2
  10. pygpt_net/controller/ui/mode.py +17 -66
  11. pygpt_net/core/agents/runner.py +15 -7
  12. pygpt_net/core/experts/experts.py +3 -3
  13. pygpt_net/data/config/config.json +3 -3
  14. pygpt_net/data/config/models.json +3 -3
  15. pygpt_net/data/locale/locale.de.ini +2 -0
  16. pygpt_net/data/locale/locale.en.ini +2 -0
  17. pygpt_net/data/locale/locale.es.ini +2 -0
  18. pygpt_net/data/locale/locale.fr.ini +2 -0
  19. pygpt_net/data/locale/locale.it.ini +2 -0
  20. pygpt_net/data/locale/locale.pl.ini +3 -1
  21. pygpt_net/data/locale/locale.uk.ini +2 -0
  22. pygpt_net/data/locale/locale.zh.ini +2 -0
  23. pygpt_net/plugin/base/plugin.py +35 -3
  24. pygpt_net/plugin/bitbucket/__init__.py +12 -0
  25. pygpt_net/plugin/bitbucket/config.py +267 -0
  26. pygpt_net/plugin/bitbucket/plugin.py +125 -0
  27. pygpt_net/plugin/bitbucket/worker.py +569 -0
  28. pygpt_net/plugin/facebook/__init__.py +12 -0
  29. pygpt_net/plugin/facebook/config.py +359 -0
  30. pygpt_net/plugin/facebook/plugin.py +114 -0
  31. pygpt_net/plugin/facebook/worker.py +698 -0
  32. pygpt_net/plugin/github/__init__.py +12 -0
  33. pygpt_net/plugin/github/config.py +441 -0
  34. pygpt_net/plugin/github/plugin.py +124 -0
  35. pygpt_net/plugin/github/worker.py +674 -0
  36. pygpt_net/plugin/google/__init__.py +12 -0
  37. pygpt_net/plugin/google/config.py +367 -0
  38. pygpt_net/plugin/google/plugin.py +126 -0
  39. pygpt_net/plugin/google/worker.py +826 -0
  40. pygpt_net/plugin/slack/__init__.py +12 -0
  41. pygpt_net/plugin/slack/config.py +349 -0
  42. pygpt_net/plugin/slack/plugin.py +116 -0
  43. pygpt_net/plugin/slack/worker.py +639 -0
  44. pygpt_net/plugin/telegram/__init__.py +12 -0
  45. pygpt_net/plugin/telegram/config.py +308 -0
  46. pygpt_net/plugin/telegram/plugin.py +118 -0
  47. pygpt_net/plugin/telegram/worker.py +563 -0
  48. pygpt_net/plugin/twitter/__init__.py +12 -0
  49. pygpt_net/plugin/twitter/config.py +491 -0
  50. pygpt_net/plugin/twitter/plugin.py +126 -0
  51. pygpt_net/plugin/twitter/worker.py +837 -0
  52. pygpt_net/provider/agents/llama_index/legacy/openai_assistant.py +35 -3
  53. pygpt_net/ui/base/config_dialog.py +4 -0
  54. pygpt_net/ui/dialog/preset.py +34 -77
  55. pygpt_net/ui/layout/toolbox/presets.py +2 -2
  56. pygpt_net/ui/main.py +3 -1
  57. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/METADATA +145 -2
  58. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/RECORD +61 -33
  59. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/LICENSE +0 -0
  60. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/WHEEL +0 -0
  61. {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/entry_points.txt +0 -0
@@ -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.06.30 02:00:00 #
10
+ # ================================================== #
11
+
12
+ from .plugin import *
@@ -0,0 +1,349 @@
1
+ # config.py
2
+ #!/usr/bin/env python3
3
+ # -*- coding: utf-8 -*-
4
+ # ================================================== #
5
+ # This file is a part of PYGPT package #
6
+ # Website: https://pygpt.net #
7
+ # GitHub: https://github.com/szczyglis-dev/py-gpt #
8
+ # MIT License #
9
+ # Created By : Marcin Szczygliński #
10
+ # Updated Date: 2025.08.14 00:00:00 #
11
+ # ================================================== #
12
+
13
+ from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
14
+
15
+
16
+ class Config(BaseConfig):
17
+ def __init__(self, plugin: BasePlugin = None, *args, **kwargs):
18
+ super(Config, self).__init__(plugin)
19
+ self.plugin = plugin
20
+
21
+ def from_defaults(self, plugin: BasePlugin = None):
22
+ # Endpoints / HTTP
23
+ plugin.add_option(
24
+ "api_base",
25
+ type="text",
26
+ value="https://slack.com/api",
27
+ label="API base",
28
+ description="Base Slack Web API URL.",
29
+ )
30
+ plugin.add_option(
31
+ "oauth_base",
32
+ type="text",
33
+ value="https://slack.com",
34
+ label="OAuth base",
35
+ description="Base for OAuth authorize (default https://slack.com).",
36
+ )
37
+ plugin.add_option(
38
+ "http_timeout",
39
+ type="int",
40
+ value=30,
41
+ label="HTTP timeout (s)",
42
+ description="Requests timeout in seconds.",
43
+ )
44
+
45
+ # OAuth2 (Slack)
46
+ plugin.add_option(
47
+ "oauth2_client_id",
48
+ type="text",
49
+ value="",
50
+ label="OAuth2 Client ID",
51
+ description="Client ID from Slack App.",
52
+ secret=True,
53
+ )
54
+ plugin.add_option(
55
+ "oauth2_client_secret",
56
+ type="text",
57
+ value="",
58
+ label="OAuth2 Client Secret",
59
+ description="Client Secret from Slack App.",
60
+ secret=True,
61
+ )
62
+ plugin.add_option(
63
+ "oauth2_redirect_uri",
64
+ type="text",
65
+ value="http://127.0.0.1:8733/callback",
66
+ label="Redirect URI",
67
+ description="Must match one of the redirect URLs in your Slack App.",
68
+ )
69
+ plugin.add_option(
70
+ "bot_scopes",
71
+ type="text",
72
+ value="chat:write,users:read,users:read.email,channels:read,groups:read,im:read,mpim:read,channels:history,groups:history,im:history,mpim:history,files:write",
73
+ label="Bot scopes (comma-separated)",
74
+ description="Scopes for bot token.",
75
+ )
76
+ plugin.add_option(
77
+ "user_scopes",
78
+ type="text",
79
+ value="",
80
+ label="User scopes (comma-separated)",
81
+ description="Optional user scopes (if you need a user token).",
82
+ )
83
+
84
+ # Tokens/cache
85
+ plugin.add_option(
86
+ "bot_token",
87
+ type="textarea",
88
+ value="",
89
+ label="(auto/manual) Bot token",
90
+ description="xoxb-... You can paste manually or obtain via OAuth.",
91
+ secret=True,
92
+ )
93
+ plugin.add_option(
94
+ "user_token",
95
+ type="textarea",
96
+ value="",
97
+ label="(auto) User token (optional)",
98
+ description="xoxp-... from OAuth (if user scopes requested).",
99
+ secret=True,
100
+ )
101
+ plugin.add_option(
102
+ "oauth2_refresh_token",
103
+ type="textarea",
104
+ value="",
105
+ label="(auto) Refresh token (if rotation enabled)",
106
+ description="Stored refresh token (bot or user).",
107
+ secret=True,
108
+ )
109
+ plugin.add_option(
110
+ "oauth2_expires_at",
111
+ type="text",
112
+ value="0",
113
+ label="(auto) Expires at (unix)",
114
+ description="Auto-calculated expiry time.",
115
+ )
116
+ plugin.add_option(
117
+ "team_id",
118
+ type="text",
119
+ value="",
120
+ label="(auto) Team ID",
121
+ description="Cached after auth.test or OAuth.",
122
+ )
123
+ plugin.add_option(
124
+ "bot_user_id",
125
+ type="text",
126
+ value="",
127
+ label="(auto) Bot user ID",
128
+ description="Cached after OAuth exchange.",
129
+ )
130
+ plugin.add_option(
131
+ "authed_user_id",
132
+ type="text",
133
+ value="",
134
+ label="(auto) Authed user ID",
135
+ description="Cached after auth.test/OAuth.",
136
+ )
137
+
138
+ plugin.add_option(
139
+ "oauth_auto_begin",
140
+ type="bool",
141
+ value=True,
142
+ label="Auto-start OAuth when required",
143
+ description="If a command needs token, begin OAuth flow automatically.",
144
+ )
145
+ plugin.add_option(
146
+ "oauth_open_browser",
147
+ type="bool",
148
+ value=True,
149
+ label="Open browser automatically",
150
+ description="Open authorize URL in default browser.",
151
+ )
152
+ plugin.add_option(
153
+ "oauth_local_server",
154
+ type="bool",
155
+ value=True,
156
+ label="Use local server for OAuth",
157
+ description="Start local HTTP server to capture redirect (requires local redirect).",
158
+ )
159
+ plugin.add_option(
160
+ "oauth_local_timeout",
161
+ type="int",
162
+ value=180,
163
+ label="OAuth local timeout (s)",
164
+ description="How long to wait for redirect with code.",
165
+ )
166
+ plugin.add_option(
167
+ "oauth_success_html",
168
+ type="textarea",
169
+ value="<html><body><h3>Authorization complete. You can close this window.</h3></body></html>",
170
+ label="Success HTML",
171
+ description="HTML shown on local callback success.",
172
+ )
173
+ plugin.add_option(
174
+ "oauth_fail_html",
175
+ type="textarea",
176
+ value="<html><body><h3>Authorization failed.</h3></body></html>",
177
+ label="Fail HTML",
178
+ description="HTML shown on local callback error.",
179
+ )
180
+ plugin.add_option(
181
+ "oauth_local_port",
182
+ type="int",
183
+ value=8733,
184
+ label="OAuth local port (0=auto)",
185
+ description="Local HTTP port for callback; use >1024. Must be registered in Slack App.",
186
+ )
187
+ plugin.add_option(
188
+ "oauth_allow_port_fallback",
189
+ type="bool",
190
+ value=True,
191
+ label="Allow fallback port if busy",
192
+ description="If preferred port is busy/forbidden, pick a free local port.",
193
+ )
194
+
195
+ # ---------------- Commands ----------------
196
+
197
+ # Auth
198
+ plugin.add_cmd(
199
+ "slack_oauth_begin",
200
+ instruction="Begin OAuth2 flow (returns authorize URL).",
201
+ params=[],
202
+ enabled=True,
203
+ description="Auth: begin OAuth2",
204
+ tab="auth",
205
+ )
206
+ plugin.add_cmd(
207
+ "slack_oauth_exchange",
208
+ instruction="Exchange authorization code for tokens.",
209
+ params=[
210
+ {"name": "code", "type": "str", "required": True, "description": "Authorization code"},
211
+ {"name": "state", "type": "str", "required": False, "description": "State (if used)"},
212
+ ],
213
+ enabled=True,
214
+ description="Auth: exchange code",
215
+ tab="auth",
216
+ )
217
+ plugin.add_cmd(
218
+ "slack_oauth_refresh",
219
+ instruction="Refresh token (if rotation enabled).",
220
+ params=[],
221
+ enabled=True,
222
+ description="Auth: refresh token",
223
+ tab="auth",
224
+ )
225
+ plugin.add_cmd(
226
+ "slack_auth_test",
227
+ instruction="Test authentication and get ids.",
228
+ params=[],
229
+ enabled=True,
230
+ description="Auth: test",
231
+ tab="auth",
232
+ )
233
+
234
+ # Users
235
+ plugin.add_cmd(
236
+ "slack_users_list",
237
+ instruction="List workspace users (contacts).",
238
+ params=[
239
+ {"name": "limit", "type": "int", "required": False, "description": "Default Slack pagination"},
240
+ {"name": "cursor", "type": "str", "required": False, "description": "Cursor for next page"},
241
+ {"name": "include_locale", "type": "bool", "required": False, "description": "Include locale"},
242
+ ],
243
+ enabled=True,
244
+ description="Users: list",
245
+ tab="users",
246
+ )
247
+
248
+ # Conversations
249
+ plugin.add_cmd(
250
+ "slack_conversations_list",
251
+ instruction="List channels/DMs visible to the token.",
252
+ params=[
253
+ {"name": "types", "type": "str", "required": False, "description": "public_channel,private_channel,im,mpim"},
254
+ {"name": "exclude_archived", "type": "bool", "required": False, "description": "Default true"},
255
+ {"name": "limit", "type": "int", "required": False, "description": "Default Slack pagination"},
256
+ {"name": "cursor", "type": "str", "required": False, "description": "Cursor for next page"},
257
+ ],
258
+ enabled=True,
259
+ description="Conversations: list",
260
+ tab="conversations",
261
+ )
262
+ plugin.add_cmd(
263
+ "slack_conversations_history",
264
+ instruction="Fetch channel/DM history.",
265
+ params=[
266
+ {"name": "channel", "type": "str", "required": True, "description": "Conversation ID"},
267
+ {"name": "limit", "type": "int", "required": False, "description": "Default Slack pagination"},
268
+ {"name": "cursor", "type": "str", "required": False, "description": "Cursor for next page"},
269
+ {"name": "oldest", "type": "str", "required": False, "description": "TS lower bound"},
270
+ {"name": "latest", "type": "str", "required": False, "description": "TS upper bound"},
271
+ {"name": "inclusive", "type": "bool", "required": False, "description": "Include bounds"},
272
+ ],
273
+ enabled=True,
274
+ description="Conversations: history",
275
+ tab="conversations",
276
+ )
277
+ plugin.add_cmd(
278
+ "slack_conversations_replies",
279
+ instruction="Fetch a thread by root ts.",
280
+ params=[
281
+ {"name": "channel", "type": "str", "required": True, "description": "Conversation ID"},
282
+ {"name": "ts", "type": "str", "required": True, "description": "Root thread ts"},
283
+ {"name": "limit", "type": "int", "required": False, "description": "Default Slack pagination"},
284
+ {"name": "cursor", "type": "str", "required": False, "description": "Cursor for next page"},
285
+ ],
286
+ enabled=True,
287
+ description="Conversations: replies",
288
+ tab="conversations",
289
+ )
290
+ plugin.add_cmd(
291
+ "slack_conversations_open",
292
+ instruction="Open/resume DM or MPDM.",
293
+ params=[
294
+ {"name": "users", "type": "list|str", "required": False, "description": "User IDs (1..8)."},
295
+ {"name": "channel", "type": "str", "required": False, "description": "Existing IM/MPIM id to resume"},
296
+ {"name": "return_im", "type": "bool", "required": False, "description": "Return full obj (default true)"},
297
+ ],
298
+ enabled=True,
299
+ description="Conversations: open",
300
+ tab="conversations",
301
+ )
302
+
303
+ # Chat
304
+ plugin.add_cmd(
305
+ "slack_chat_post_message",
306
+ instruction="Post message to channel/DM.",
307
+ params=[
308
+ {"name": "channel", "type": "str", "required": True, "description": "Channel/DM ID"},
309
+ {"name": "text", "type": "str", "required": False, "description": "Message text"},
310
+ {"name": "thread_ts", "type": "str", "required": False, "description": "Reply to thread"},
311
+ {"name": "blocks", "type": "list|dict", "required": False, "description": "Block Kit"},
312
+ {"name": "attachments", "type": "list", "required": False, "description": "Legacy attachments"},
313
+ {"name": "mrkdwn", "type": "bool", "required": False, "description": "Enable markdown"},
314
+ {"name": "unfurl_links", "type": "bool", "required": False, "description": "Unfurl links"},
315
+ {"name": "unfurl_media", "type": "bool", "required": False, "description": "Unfurl media"},
316
+ {"name": "reply_broadcast", "type": "bool", "required": False, "description": "Broadcast reply"},
317
+ ],
318
+ enabled=True,
319
+ description="Chat: post message",
320
+ tab="chat",
321
+ )
322
+ plugin.add_cmd(
323
+ "slack_chat_delete",
324
+ instruction="Delete a message.",
325
+ params=[
326
+ {"name": "channel", "type": "str", "required": True, "description": "Channel/DM ID"},
327
+ {"name": "ts", "type": "str", "required": True, "description": "Message ts"},
328
+ ],
329
+ enabled=True,
330
+ description="Chat: delete",
331
+ tab="chat",
332
+ )
333
+
334
+ # Files (new upload flow)
335
+ plugin.add_cmd(
336
+ "slack_files_upload",
337
+ instruction="Upload file (External flow) and share.",
338
+ params=[
339
+ {"name": "path", "type": "str", "required": True, "description": "Local file path"},
340
+ {"name": "channel", "type": "str", "required": False, "description": "Share to channel id"},
341
+ {"name": "title", "type": "str", "required": False, "description": "Title"},
342
+ {"name": "initial_comment", "type": "str", "required": False, "description": "Comment with file"},
343
+ {"name": "thread_ts", "type": "str", "required": False, "description": "Share in thread"},
344
+ {"name": "alt_text", "type": "str", "required": False, "description": "Alt text (images)"},
345
+ ],
346
+ enabled=True,
347
+ description="Files: upload (getUploadURLExternal + completeUploadExternal)",
348
+ tab="files",
349
+ )
@@ -0,0 +1,116 @@
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.07.14 00:00:00 #
10
+ # ================================================== #
11
+
12
+ import os
13
+
14
+ from pygpt_net.plugin.base.plugin import BasePlugin
15
+ from pygpt_net.core.events import Event
16
+ from pygpt_net.item.ctx import CtxItem
17
+
18
+ from .config import Config
19
+ from .worker import Worker
20
+
21
+
22
+ class Plugin(BasePlugin):
23
+ def __init__(self, *args, **kwargs):
24
+ super(Plugin, self).__init__(*args, **kwargs)
25
+ self.id = "slack"
26
+ self.name = "Slack"
27
+ self.description = "Handle users, conversations, messages, and files on Slack."
28
+ self.prefix = "API"
29
+ self.order = 100
30
+ self.allowed_cmds = [
31
+ "slack_oauth_begin",
32
+ "slack_oauth_exchange",
33
+ "slack_oauth_refresh",
34
+ "slack_auth_test",
35
+ "slack_users_list",
36
+ "slack_conversations_list",
37
+ "slack_conversations_history",
38
+ "slack_conversations_replies",
39
+ "slack_conversations_open",
40
+ "slack_chat_post_message",
41
+ "slack_chat_delete",
42
+ "slack_files_upload"
43
+ ]
44
+ self.use_locale = False
45
+ self.worker = None
46
+ self.config = Config(self)
47
+ self.init_options()
48
+
49
+ def init_options(self):
50
+ """Initialize options"""
51
+ self.config.from_defaults(self)
52
+
53
+ def handle(self, event: Event, *args, **kwargs):
54
+ """
55
+ Handle dispatched event
56
+
57
+ :param event: event object
58
+ :param args: event args
59
+ :param kwargs: event kwargs
60
+ """
61
+ name = event.name
62
+ data = event.data
63
+ ctx = event.ctx
64
+
65
+ if name == Event.CMD_SYNTAX:
66
+ self.cmd_syntax(data)
67
+
68
+ elif name == Event.CMD_EXECUTE:
69
+ self.cmd(
70
+ ctx,
71
+ data['commands'],
72
+ )
73
+
74
+ def cmd_syntax(self, data: dict):
75
+ """
76
+ Event: CMD_SYNTAX
77
+
78
+ :param data: event data dict
79
+ """
80
+ for option in self.allowed_cmds:
81
+ if self.has_cmd(option):
82
+ data['cmd'].append(self.get_cmd(option)) # append command
83
+
84
+ def cmd(self, ctx: CtxItem, cmds: list):
85
+ """
86
+ Event: CMD_EXECUTE
87
+
88
+ :param ctx: CtxItem
89
+ :param cmds: commands dict
90
+ """
91
+ is_cmd = False
92
+ my_commands = []
93
+ for item in cmds:
94
+ if item["cmd"] in self.allowed_cmds:
95
+ my_commands.append(item)
96
+ is_cmd = True
97
+
98
+ if not is_cmd:
99
+ return
100
+
101
+ # set state: busy
102
+ self.cmd_prepare(ctx, my_commands)
103
+
104
+ try:
105
+ worker = Worker()
106
+ worker.from_defaults(self)
107
+ worker.cmds = my_commands
108
+ worker.ctx = ctx
109
+
110
+ if not self.is_async(ctx):
111
+ worker.run()
112
+ return
113
+ worker.run_async()
114
+
115
+ except Exception as e:
116
+ self.error(e)