pygpt-net 2.6.0.post2__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 (98) hide show
  1. pygpt_net/CHANGELOG.txt +8 -0
  2. pygpt_net/__init__.py +3 -3
  3. pygpt_net/app.py +27 -9
  4. pygpt_net/controller/chat/response.py +10 -4
  5. pygpt_net/controller/chat/stream.py +40 -2
  6. pygpt_net/controller/model/editor.py +45 -4
  7. pygpt_net/controller/plugins/plugins.py +25 -0
  8. pygpt_net/controller/presets/editor.py +100 -100
  9. pygpt_net/controller/presets/experts.py +20 -1
  10. pygpt_net/controller/presets/presets.py +5 -4
  11. pygpt_net/controller/ui/mode.py +17 -66
  12. pygpt_net/core/agents/provider.py +2 -1
  13. pygpt_net/core/agents/runner.py +123 -9
  14. pygpt_net/core/agents/runners/helpers.py +3 -2
  15. pygpt_net/core/agents/runners/llama_workflow.py +176 -22
  16. pygpt_net/core/agents/runners/loop.py +22 -13
  17. pygpt_net/core/experts/experts.py +19 -25
  18. pygpt_net/core/idx/chat.py +24 -34
  19. pygpt_net/core/idx/response.py +5 -2
  20. pygpt_net/core/locale/locale.py +73 -45
  21. pygpt_net/core/render/web/body.py +152 -207
  22. pygpt_net/core/render/web/renderer.py +4 -2
  23. pygpt_net/data/config/config.json +3 -3
  24. pygpt_net/data/config/models.json +3 -3
  25. pygpt_net/data/locale/locale.de.ini +12 -8
  26. pygpt_net/data/locale/locale.en.ini +12 -8
  27. pygpt_net/data/locale/locale.es.ini +12 -8
  28. pygpt_net/data/locale/locale.fr.ini +12 -8
  29. pygpt_net/data/locale/locale.it.ini +12 -8
  30. pygpt_net/data/locale/locale.pl.ini +12 -8
  31. pygpt_net/data/locale/locale.uk.ini +12 -8
  32. pygpt_net/data/locale/locale.zh.ini +12 -8
  33. pygpt_net/item/ctx.py +2 -1
  34. pygpt_net/plugin/base/plugin.py +35 -3
  35. pygpt_net/plugin/bitbucket/__init__.py +12 -0
  36. pygpt_net/plugin/bitbucket/config.py +267 -0
  37. pygpt_net/plugin/bitbucket/plugin.py +125 -0
  38. pygpt_net/plugin/bitbucket/worker.py +569 -0
  39. pygpt_net/plugin/cmd_files/worker.py +19 -16
  40. pygpt_net/plugin/facebook/__init__.py +12 -0
  41. pygpt_net/plugin/facebook/config.py +359 -0
  42. pygpt_net/plugin/facebook/plugin.py +114 -0
  43. pygpt_net/plugin/facebook/worker.py +698 -0
  44. pygpt_net/plugin/github/__init__.py +12 -0
  45. pygpt_net/plugin/github/config.py +441 -0
  46. pygpt_net/plugin/github/plugin.py +124 -0
  47. pygpt_net/plugin/github/worker.py +674 -0
  48. pygpt_net/plugin/google/__init__.py +12 -0
  49. pygpt_net/plugin/google/config.py +367 -0
  50. pygpt_net/plugin/google/plugin.py +126 -0
  51. pygpt_net/plugin/google/worker.py +826 -0
  52. pygpt_net/plugin/slack/__init__.py +12 -0
  53. pygpt_net/plugin/slack/config.py +349 -0
  54. pygpt_net/plugin/slack/plugin.py +116 -0
  55. pygpt_net/plugin/slack/worker.py +639 -0
  56. pygpt_net/plugin/telegram/__init__.py +12 -0
  57. pygpt_net/plugin/telegram/config.py +308 -0
  58. pygpt_net/plugin/telegram/plugin.py +118 -0
  59. pygpt_net/plugin/telegram/worker.py +563 -0
  60. pygpt_net/plugin/twitter/__init__.py +12 -0
  61. pygpt_net/plugin/twitter/config.py +491 -0
  62. pygpt_net/plugin/twitter/plugin.py +126 -0
  63. pygpt_net/plugin/twitter/worker.py +837 -0
  64. pygpt_net/provider/agents/base.py +4 -1
  65. pygpt_net/provider/agents/llama_index/codeact_workflow.py +95 -0
  66. pygpt_net/provider/agents/llama_index/legacy/__init__.py +0 -0
  67. pygpt_net/provider/agents/llama_index/{openai.py → legacy/openai.py} +2 -2
  68. pygpt_net/provider/agents/llama_index/{openai_assistant.py → legacy/openai_assistant.py} +37 -5
  69. pygpt_net/provider/agents/llama_index/{planner.py → legacy/planner.py} +3 -3
  70. pygpt_net/provider/agents/llama_index/{react.py → legacy/react.py} +3 -3
  71. pygpt_net/provider/agents/llama_index/openai_workflow.py +52 -0
  72. pygpt_net/provider/agents/llama_index/planner_workflow.py +115 -0
  73. pygpt_net/provider/agents/llama_index/react_workflow.py +6 -4
  74. pygpt_net/provider/agents/llama_index/workflow/__init__.py +0 -0
  75. pygpt_net/provider/agents/llama_index/{codeact_agent_custom.py → workflow/codeact.py} +124 -8
  76. pygpt_net/provider/agents/llama_index/workflow/events.py +24 -0
  77. pygpt_net/provider/agents/llama_index/workflow/openai.py +634 -0
  78. pygpt_net/provider/agents/llama_index/workflow/planner.py +601 -0
  79. pygpt_net/provider/agents/openai/agent.py +1 -0
  80. pygpt_net/provider/agents/openai/agent_b2b.py +2 -0
  81. pygpt_net/provider/agents/openai/agent_planner.py +1 -0
  82. pygpt_net/provider/agents/openai/agent_with_experts.py +1 -0
  83. pygpt_net/provider/agents/openai/agent_with_experts_feedback.py +1 -0
  84. pygpt_net/provider/agents/openai/agent_with_feedback.py +1 -0
  85. pygpt_net/provider/agents/openai/evolve.py +1 -0
  86. pygpt_net/provider/core/preset/patch.py +11 -17
  87. pygpt_net/ui/base/config_dialog.py +4 -0
  88. pygpt_net/ui/dialog/preset.py +34 -77
  89. pygpt_net/ui/layout/toolbox/presets.py +2 -2
  90. pygpt_net/ui/main.py +3 -1
  91. pygpt_net/ui/widget/lists/experts.py +3 -2
  92. {pygpt_net-2.6.0.post2.dist-info → pygpt_net-2.6.2.dist-info}/METADATA +155 -4
  93. {pygpt_net-2.6.0.post2.dist-info → pygpt_net-2.6.2.dist-info}/RECORD +96 -62
  94. pygpt_net/data/config/presets/agent_react_workflow.json +0 -34
  95. pygpt_net/provider/agents/llama_index/code_act.py +0 -58
  96. {pygpt_net-2.6.0.post2.dist-info → pygpt_net-2.6.2.dist-info}/LICENSE +0 -0
  97. {pygpt_net-2.6.0.post2.dist-info → pygpt_net-2.6.2.dist-info}/WHEEL +0 -0
  98. {pygpt_net-2.6.0.post2.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,441 @@
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.15 00: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://api.github.com",
26
+ label="API base",
27
+ description="Base API URL (default https://api.github.com).",
28
+ )
29
+ plugin.add_option(
30
+ "web_base",
31
+ type="text",
32
+ value="https://github.com",
33
+ label="Web base",
34
+ description="GitHub website base (default https://github.com).",
35
+ )
36
+ plugin.add_option(
37
+ "api_version",
38
+ type="text",
39
+ value="2022-11-28",
40
+ label="API version header",
41
+ description="X-GitHub-Api-Version value.",
42
+ )
43
+ plugin.add_option(
44
+ "http_timeout",
45
+ type="int",
46
+ value=30,
47
+ label="HTTP timeout (s)",
48
+ description="Requests timeout in seconds.",
49
+ )
50
+
51
+ # OAuth Device Flow
52
+ plugin.add_option(
53
+ "oauth_client_id",
54
+ type="text",
55
+ value="",
56
+ label="OAuth Client ID",
57
+ description="Client ID from your GitHub OAuth App (supports Device Flow).",
58
+ secret=True,
59
+ )
60
+ plugin.add_option(
61
+ "oauth_scopes",
62
+ type="text",
63
+ value="repo read:org read:user user:email",
64
+ label="Scopes",
65
+ description="Space-separated OAuth scopes for Device Flow.",
66
+ )
67
+ plugin.add_option(
68
+ "oauth_open_browser",
69
+ type="bool",
70
+ value=True,
71
+ label="Open browser automatically",
72
+ description="Open verification URL in default browser.",
73
+ )
74
+ plugin.add_option(
75
+ "oauth_auto_begin",
76
+ type="bool",
77
+ value=True,
78
+ label="Auto-start auth when required",
79
+ description="Begin Device Flow automatically when a command needs a token.",
80
+ )
81
+ plugin.add_option(
82
+ "oauth_scope_granted",
83
+ type="text",
84
+ value="",
85
+ label="(auto) Granted scopes",
86
+ description="Set after authorization.",
87
+ )
88
+
89
+ # Tokens
90
+ plugin.add_option(
91
+ "gh_access_token",
92
+ type="textarea",
93
+ value="",
94
+ label="(auto) OAuth access token",
95
+ description="Stored OAuth access token (Device/Web).",
96
+ secret=True,
97
+ )
98
+ plugin.add_option(
99
+ "pat_token",
100
+ type="textarea",
101
+ value="",
102
+ label="PAT token (optional)",
103
+ description="Personal Access Token (classic or fine-grained).",
104
+ secret=True,
105
+ )
106
+ plugin.add_option(
107
+ "auth_scheme",
108
+ type="text",
109
+ value="Bearer",
110
+ label="Auth scheme",
111
+ description="Bearer or token (PAT usually 'token').",
112
+ )
113
+
114
+ # Convenience cache
115
+ plugin.add_option(
116
+ "user_id",
117
+ type="text",
118
+ value="",
119
+ label="(auto) User ID",
120
+ description="Cached after gh_me or auth.",
121
+ )
122
+ plugin.add_option(
123
+ "username",
124
+ type="text",
125
+ value="",
126
+ label="(auto) Username",
127
+ description="Cached after gh_me or auth.",
128
+ )
129
+
130
+ # ---------------- Commands ----------------
131
+
132
+ # Auth
133
+ plugin.add_cmd(
134
+ "gh_device_begin",
135
+ instruction="Begin OAuth Device Flow (returns user_code and verification URL).",
136
+ params=[
137
+ {"name": "scopes", "type": "str", "required": False, "description": "Override scopes (space-separated)"},
138
+ ],
139
+ enabled=True,
140
+ description="Auth: device begin",
141
+ tab="auth",
142
+ )
143
+ plugin.add_cmd(
144
+ "gh_device_poll",
145
+ instruction="Poll device code for access token.",
146
+ params=[
147
+ {"name": "device_code", "type": "str", "required": True, "description": "Device code from gh_device_begin"},
148
+ ],
149
+ enabled=True,
150
+ description="Auth: device poll",
151
+ tab="auth",
152
+ )
153
+ plugin.add_cmd(
154
+ "gh_set_pat",
155
+ instruction="Set Personal Access Token (PAT).",
156
+ params=[
157
+ {"name": "token", "type": "str", "required": True, "description": "PAT token value"},
158
+ {"name": "scheme", "type": "str", "required": False, "description": "Auth scheme: token|Bearer"},
159
+ ],
160
+ enabled=True,
161
+ description="Auth: set PAT",
162
+ tab="auth",
163
+ )
164
+
165
+ # Users
166
+ plugin.add_cmd(
167
+ "gh_me",
168
+ instruction="Get authenticated user.",
169
+ params=[],
170
+ enabled=True,
171
+ description="Users: me",
172
+ tab="users",
173
+ )
174
+ plugin.add_cmd(
175
+ "gh_user_get",
176
+ instruction="Get user by username.",
177
+ params=[{"name": "username", "type": "str", "required": True, "description": "GitHub login"}],
178
+ enabled=True,
179
+ description="Users: get",
180
+ tab="users",
181
+ )
182
+
183
+ # Repos
184
+ plugin.add_cmd(
185
+ "gh_repos_list",
186
+ instruction="List repositories.",
187
+ params=[
188
+ {"name": "username", "type": "str", "required": False, "description": "List for user (public)"},
189
+ {"name": "org", "type": "str", "required": False, "description": "List for organization"},
190
+ {"name": "type", "type": "str", "required": False, "description": "all|owner|member (for /user/repos)"},
191
+ {"name": "visibility", "type": "str", "required": False, "description": "all|public|private"},
192
+ {"name": "sort", "type": "str", "required": False, "description": "created|updated|pushed|full_name"},
193
+ {"name": "direction", "type": "str", "required": False, "description": "asc|desc"},
194
+ {"name": "per_page", "type": "int", "required": False, "description": "Items per page"},
195
+ {"name": "page", "type": "int", "required": False, "description": "Page index"},
196
+ ],
197
+ enabled=True,
198
+ description="Repos: list",
199
+ tab="repos",
200
+ )
201
+ plugin.add_cmd(
202
+ "gh_repo_get",
203
+ instruction="Get repository details.",
204
+ params=[
205
+ {"name": "owner", "type": "str", "required": True, "description": "Owner login"},
206
+ {"name": "repo", "type": "str", "required": True, "description": "Repo name"},
207
+ ],
208
+ enabled=True,
209
+ description="Repos: get",
210
+ tab="repos",
211
+ )
212
+ plugin.add_cmd(
213
+ "gh_repo_create",
214
+ instruction="Create repository for user or org.",
215
+ params=[
216
+ {"name": "name", "type": "str", "required": True, "description": "Repository name"},
217
+ {"name": "description", "type": "str", "required": False, "description": "Description"},
218
+ {"name": "private", "type": "bool", "required": False, "description": "Default False"},
219
+ {"name": "auto_init", "type": "bool", "required": False, "description": "Default True"},
220
+ {"name": "org", "type": "str", "required": False, "description": "Organization (if creating in org)"},
221
+ ],
222
+ enabled=True,
223
+ description="Repos: create",
224
+ tab="repos",
225
+ )
226
+ plugin.add_cmd(
227
+ "gh_repo_delete",
228
+ instruction="Delete repository (dangerous).",
229
+ params=[
230
+ {"name": "owner", "type": "str", "required": True, "description": "Owner login"},
231
+ {"name": "repo", "type": "str", "required": True, "description": "Repo name"},
232
+ {"name": "confirm", "type": "bool", "required": False, "description": "Must be true"},
233
+ ],
234
+ enabled=False,
235
+ description="Repos: delete",
236
+ tab="repos",
237
+ )
238
+
239
+ # Contents
240
+ plugin.add_cmd(
241
+ "gh_contents_get",
242
+ instruction="Get file or list directory contents.",
243
+ params=[
244
+ {"name": "owner", "type": "str", "required": True, "description": "Owner login"},
245
+ {"name": "repo", "type": "str", "required": True, "description": "Repo name"},
246
+ {"name": "path", "type": "str", "required": False, "description": "Path inside repo (optional)"},
247
+ {"name": "ref", "type": "str", "required": False, "description": "Branch/tag/commit SHA"},
248
+ ],
249
+ enabled=True,
250
+ description="Contents: get",
251
+ tab="contents",
252
+ )
253
+ plugin.add_cmd(
254
+ "gh_file_put",
255
+ instruction="Create or update a file via Contents API.",
256
+ params=[
257
+ {"name": "owner", "type": "str", "required": True, "description": "Owner login"},
258
+ {"name": "repo", "type": "str", "required": True, "description": "Repo name"},
259
+ {"name": "path", "type": "str", "required": True, "description": "Path inside repo"},
260
+ {"name": "message", "type": "str", "required": False, "description": "Commit message"},
261
+ {"name": "content", "type": "str", "required": False, "description": "Raw text content"},
262
+ {"name": "local_path", "type": "str", "required": False, "description": "Local file to upload"},
263
+ {"name": "branch", "type": "str", "required": False, "description": "Branch name"},
264
+ {"name": "sha", "type": "str", "required": False, "description": "Existing blob sha for update"},
265
+ {"name": "committer", "type": "dict", "required": False, "description": '{"name":"","email":""}'},
266
+ {"name": "author", "type": "dict", "required": False, "description": '{"name":"","email":""}'},
267
+ {"name": "resolve_sha", "type": "bool", "required": False, "description": "Auto-detect sha if missing"},
268
+ ],
269
+ enabled=True,
270
+ description="Contents: put file",
271
+ tab="contents",
272
+ )
273
+ plugin.add_cmd(
274
+ "gh_file_delete",
275
+ instruction="Delete a file via Contents API.",
276
+ params=[
277
+ {"name": "owner", "type": "str", "required": True, "description": "Owner login"},
278
+ {"name": "repo", "type": "str", "required": True, "description": "Repo name"},
279
+ {"name": "path", "type": "str", "required": True, "description": "Path inside repo"},
280
+ {"name": "message", "type": "str", "required": True, "description": "Commit message"},
281
+ {"name": "sha", "type": "str", "required": True, "description": "Blob sha"},
282
+ {"name": "branch", "type": "str", "required": False, "description": "Branch name"},
283
+ ],
284
+ enabled=True,
285
+ description="Contents: delete file",
286
+ tab="contents",
287
+ )
288
+
289
+ # Issues
290
+ plugin.add_cmd(
291
+ "gh_issues_list",
292
+ instruction="List repository issues.",
293
+ params=[
294
+ {"name": "owner", "type": "str", "required": True, "description": "Owner"},
295
+ {"name": "repo", "type": "str", "required": True, "description": "Repo"},
296
+ {"name": "state", "type": "str", "required": False, "description": "open|closed|all"},
297
+ {"name": "labels", "type": "str", "required": False, "description": "Comma labels"},
298
+ {"name": "creator", "type": "str", "required": False, "description": "Creator login"},
299
+ {"name": "mentioned", "type": "str", "required": False, "description": "Mentioned login"},
300
+ {"name": "assignee", "type": "str", "required": False, "description": "Assignee login"},
301
+ {"name": "since", "type": "str", "required": False, "description": "ISO8601"},
302
+ {"name": "per_page", "type": "int", "required": False, "description": "Items per page"},
303
+ {"name": "page", "type": "int", "required": False, "description": "Page"},
304
+ ],
305
+ enabled=True,
306
+ description="Issues: list",
307
+ tab="issues",
308
+ )
309
+ plugin.add_cmd(
310
+ "gh_issue_create",
311
+ instruction="Create an issue.",
312
+ params=[
313
+ {"name": "owner", "type": "str", "required": True, "description": "Owner"},
314
+ {"name": "repo", "type": "str", "required": True, "description": "Repo"},
315
+ {"name": "title", "type": "str", "required": True, "description": "Issue title"},
316
+ {"name": "body", "type": "str", "required": False, "description": "Issue body"},
317
+ {"name": "assignees", "type": "list", "required": False, "description": "List of logins"},
318
+ {"name": "labels", "type": "list", "required": False, "description": "List of labels"},
319
+ ],
320
+ enabled=True,
321
+ description="Issues: create",
322
+ tab="issues",
323
+ )
324
+ plugin.add_cmd(
325
+ "gh_issue_comment",
326
+ instruction="Comment on an issue.",
327
+ params=[
328
+ {"name": "owner", "type": "str", "required": True, "description": "Owner"},
329
+ {"name": "repo", "type": "str", "required": True, "description": "Repo"},
330
+ {"name": "number", "type": "int", "required": True, "description": "Issue number"},
331
+ {"name": "body", "type": "str", "required": True, "description": "Comment body"},
332
+ ],
333
+ enabled=True,
334
+ description="Issues: comment",
335
+ tab="issues",
336
+ )
337
+ plugin.add_cmd(
338
+ "gh_issue_close",
339
+ instruction="Close an issue.",
340
+ params=[
341
+ {"name": "owner", "type": "str", "required": True, "description": "Owner"},
342
+ {"name": "repo", "type": "str", "required": True, "description": "Repo"},
343
+ {"name": "number", "type": "int", "required": True, "description": "Issue number"},
344
+ ],
345
+ enabled=True,
346
+ description="Issues: close",
347
+ tab="issues",
348
+ )
349
+
350
+ # Pull Requests
351
+ plugin.add_cmd(
352
+ "gh_pulls_list",
353
+ instruction="List pull requests.",
354
+ params=[
355
+ {"name": "owner", "type": "str", "required": True, "description": "Owner"},
356
+ {"name": "repo", "type": "str", "required": True, "description": "Repo"},
357
+ {"name": "state", "type": "str", "required": False, "description": "open|closed|all"},
358
+ {"name": "head", "type": "str", "required": False, "description": "user:branch"},
359
+ {"name": "base", "type": "str", "required": False, "description": "Base branch"},
360
+ {"name": "sort", "type": "str", "required": False, "description": "created|updated|popularity|long-running"},
361
+ {"name": "direction", "type": "str", "required": False, "description": "asc|desc"},
362
+ {"name": "per_page", "type": "int", "required": False, "description": "Items per page"},
363
+ {"name": "page", "type": "int", "required": False, "description": "Page"},
364
+ ],
365
+ enabled=True,
366
+ description="PR: list",
367
+ tab="pulls",
368
+ )
369
+ plugin.add_cmd(
370
+ "gh_pull_create",
371
+ instruction="Create a pull request.",
372
+ params=[
373
+ {"name": "owner", "type": "str", "required": True, "description": "Owner"},
374
+ {"name": "repo", "type": "str", "required": True, "description": "Repo"},
375
+ {"name": "title", "type": "str", "required": True, "description": "PR title"},
376
+ {"name": "head", "type": "str", "required": True, "description": "Source branch (user:branch)"},
377
+ {"name": "base", "type": "str", "required": True, "description": "Target branch"},
378
+ {"name": "body", "type": "str", "required": False, "description": "PR body"},
379
+ {"name": "draft", "type": "bool", "required": False, "description": "Draft PR"},
380
+ ],
381
+ enabled=True,
382
+ description="PR: create",
383
+ tab="pulls",
384
+ )
385
+ plugin.add_cmd(
386
+ "gh_pull_merge",
387
+ instruction="Merge a pull request.",
388
+ params=[
389
+ {"name": "owner", "type": "str", "required": True, "description": "Owner"},
390
+ {"name": "repo", "type": "str", "required": True, "description": "Repo"},
391
+ {"name": "number", "type": "int", "required": True, "description": "PR number"},
392
+ {"name": "commit_title", "type": "str", "required": False, "description": "Commit title"},
393
+ {"name": "commit_message", "type": "str", "required": False, "description": "Commit message"},
394
+ {"name": "merge_method", "type": "str", "required": False, "description": "merge|squash|rebase"},
395
+ ],
396
+ enabled=True,
397
+ description="PR: merge",
398
+ tab="pulls",
399
+ )
400
+
401
+ # Search
402
+ plugin.add_cmd(
403
+ "gh_search_repos",
404
+ instruction="Search repositories.",
405
+ params=[
406
+ {"name": "q", "type": "str", "required": True, "description": "Query string"},
407
+ {"name": "sort", "type": "str", "required": False, "description": "stars|forks|help-wanted-issues|updated"},
408
+ {"name": "order", "type": "str", "required": False, "description": "desc|asc"},
409
+ {"name": "per_page", "type": "int", "required": False, "description": "Items per page"},
410
+ {"name": "page", "type": "int", "required": False, "description": "Page"},
411
+ ],
412
+ enabled=True,
413
+ description="Search: repositories",
414
+ tab="search",
415
+ )
416
+ plugin.add_cmd(
417
+ "gh_search_issues",
418
+ instruction="Search issues and pull requests.",
419
+ params=[
420
+ {"name": "q", "type": "str", "required": True, "description": "Query string"},
421
+ {"name": "sort", "type": "str", "required": False, "description": "comments|reactions|created|updated"},
422
+ {"name": "order", "type": "str", "required": False, "description": "desc|asc"},
423
+ {"name": "per_page", "type": "int", "required": False, "description": "Items per page"},
424
+ {"name": "page", "type": "int", "required": False, "description": "Page"},
425
+ ],
426
+ enabled=True,
427
+ description="Search: issues",
428
+ tab="search",
429
+ )
430
+ plugin.add_cmd(
431
+ "gh_search_code",
432
+ instruction="Search code.",
433
+ params=[
434
+ {"name": "q", "type": "str", "required": True, "description": "Query string (use qualifiers)"},
435
+ {"name": "per_page", "type": "int", "required": False, "description": "Items per page"},
436
+ {"name": "page", "type": "int", "required": False, "description": "Page"},
437
+ ],
438
+ enabled=True,
439
+ description="Search: code",
440
+ tab="search",
441
+ )
@@ -0,0 +1,124 @@
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.15 00: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
+ from .worker import Worker
18
+
19
+
20
+ class Plugin(BasePlugin):
21
+ def __init__(self, *args, **kwargs):
22
+ super(Plugin, self).__init__(*args, **kwargs)
23
+ self.id = "github"
24
+ self.name = "GitHub"
25
+ self.description = "Access GitHub API to manage repositories, issues, and pull requests."
26
+ self.prefix = "API"
27
+ self.order = 100
28
+ self.allowed_cmds = [
29
+ "gh_device_begin",
30
+ "gh_device_poll",
31
+ "gh_set_pat",
32
+ "gh_me",
33
+ "gh_user_get",
34
+ "gh_repos_list",
35
+ "gh_repo_get",
36
+ "gh_repo_create",
37
+ "gh_repo_delete",
38
+ "gh_contents_get",
39
+ "gh_file_put",
40
+ "gh_file_delete",
41
+ "gh_issues_list",
42
+ "gh_issue_create",
43
+ "gh_issue_comment",
44
+ "gh_issue_close",
45
+ "gh_pulls_list",
46
+ "gh_pull_create",
47
+ "gh_pull_merge",
48
+ "gh_search_repos",
49
+ "gh_search_issues",
50
+ "gh_search_code"
51
+ ]
52
+ self.use_locale = False
53
+ self.worker = None
54
+ self.config = Config(self)
55
+ self.init_options()
56
+
57
+ def init_options(self):
58
+ """Initialize options"""
59
+ self.config.from_defaults(self)
60
+
61
+ def handle(self, event: Event, *args, **kwargs):
62
+ """
63
+ Handle dispatched event
64
+
65
+ :param event: event object
66
+ :param args: event args
67
+ :param kwargs: event kwargs
68
+ """
69
+ name = event.name
70
+ data = event.data
71
+ ctx = event.ctx
72
+
73
+ if name == Event.CMD_SYNTAX:
74
+ self.cmd_syntax(data)
75
+
76
+ elif name == Event.CMD_EXECUTE:
77
+ self.cmd(
78
+ ctx,
79
+ data['commands'],
80
+ )
81
+
82
+ def cmd_syntax(self, data: dict):
83
+ """
84
+ Event: CMD_SYNTAX
85
+
86
+ :param data: event data dict
87
+ """
88
+ for option in self.allowed_cmds:
89
+ if self.has_cmd(option):
90
+ data['cmd'].append(self.get_cmd(option)) # append command
91
+
92
+ def cmd(self, ctx: CtxItem, cmds: list):
93
+ """
94
+ Event: CMD_EXECUTE
95
+
96
+ :param ctx: CtxItem
97
+ :param cmds: commands dict
98
+ """
99
+ is_cmd = False
100
+ my_commands = []
101
+ for item in cmds:
102
+ if item["cmd"] in self.allowed_cmds:
103
+ my_commands.append(item)
104
+ is_cmd = True
105
+
106
+ if not is_cmd:
107
+ return
108
+
109
+ # set state: busy
110
+ self.cmd_prepare(ctx, my_commands)
111
+
112
+ try:
113
+ worker = Worker()
114
+ worker.from_defaults(self)
115
+ worker.cmds = my_commands
116
+ worker.ctx = ctx
117
+
118
+ if not self.is_async(ctx):
119
+ worker.run()
120
+ return
121
+ worker.run_async()
122
+
123
+ except Exception as e:
124
+ self.error(e)