github-agent 0.2.55__tar.gz → 0.7.1__tar.gz

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 (35) hide show
  1. {github_agent-0.2.55/github_agent.egg-info → github_agent-0.7.1}/PKG-INFO +72 -4
  2. github_agent-0.2.55/PKG-INFO → github_agent-0.7.1/README.md +66 -18
  3. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent/agent_server.py +2 -3
  4. github_agent-0.2.55/github_agent/api_wrapper.py → github_agent-0.7.1/github_agent/api_client.py +46 -44
  5. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent/auth.py +10 -10
  6. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent/github_input_models.py +33 -33
  7. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent/github_response_models.py +45 -44
  8. github_agent-0.7.1/github_agent/mcp_config.json +3 -0
  9. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent/mcp_server.py +35 -27
  10. github_agent-0.2.55/README.md → github_agent-0.7.1/github_agent.egg-info/PKG-INFO +86 -1
  11. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent.egg-info/SOURCES.txt +5 -12
  12. github_agent-0.7.1/github_agent.egg-info/requires.txt +5 -0
  13. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent.egg-info/top_level.txt +1 -0
  14. github_agent-0.7.1/pyproject.toml +52 -0
  15. github_agent-0.7.1/tests/test_github_agent_api_brute_force_coverage.py +107 -0
  16. github_agent-0.7.1/tests/test_github_agent_brute_force_coverage.py +155 -0
  17. github_agent-0.2.55/github_agent/agent_data/CRON.md +0 -12
  18. github_agent-0.2.55/github_agent/agent_data/CRON_LOG.md +0 -4
  19. github_agent-0.2.55/github_agent/agent_data/HEARTBEAT.md +0 -31
  20. github_agent-0.2.55/github_agent/agent_data/IDENTITY.md +0 -48
  21. github_agent-0.2.55/github_agent/agent_data/MEMORY.md +0 -8
  22. github_agent-0.2.55/github_agent/agent_data/NODE_AGENTS.md +0 -55
  23. github_agent-0.2.55/github_agent/agent_data/USER.md +0 -7
  24. github_agent-0.2.55/github_agent/agent_data/chats +0 -3
  25. github_agent-0.2.55/github_agent/agent_data/icon.png +0 -3
  26. github_agent-0.2.55/github_agent/agent_data/mcp_config.json +0 -18
  27. github_agent-0.2.55/github_agent.egg-info/requires.txt +0 -1
  28. github_agent-0.2.55/pyproject.toml +0 -33
  29. {github_agent-0.2.55 → github_agent-0.7.1}/LICENSE +0 -0
  30. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent/__init__.py +0 -0
  31. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent/__main__.py +0 -0
  32. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent.egg-info/dependency_links.txt +0 -0
  33. {github_agent-0.2.55 → github_agent-0.7.1}/github_agent.egg-info/entry_points.txt +0 -0
  34. {github_agent-0.2.55 → github_agent-0.7.1}/scripts/validate_a2a_agent.py +2 -2
  35. {github_agent-0.2.55 → github_agent-0.7.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-agent
3
- Version: 0.2.55
3
+ Version: 0.7.1
4
4
  Summary: GitHub Agent for MCP
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -9,10 +9,13 @@ Classifier: License :: Public Domain
9
9
  Classifier: Environment :: Console
10
10
  Classifier: Operating System :: POSIX :: Linux
11
11
  Classifier: Programming Language :: Python :: 3
12
- Requires-Python: >=3.10
12
+ Requires-Python: <3.14,>=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
- Requires-Dist: agent-utilities[agent,logfire]>=0.2.31
15
+ Requires-Dist: agent-utilities[agent,logfire]>=0.6.2
16
+ Provides-Extra: test
17
+ Requires-Dist: pytest; extra == "test"
18
+ Requires-Dist: pytest-asyncio; extra == "test"
16
19
  Dynamic: license-file
17
20
 
18
21
  # GitHub Agent - A2A | AG-UI | MCP
@@ -38,7 +41,7 @@ Dynamic: license-file
38
41
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/github-agent)
39
42
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/github-agent)
40
43
 
41
- *Version: 0.2.55*
44
+ *Version: 0.7.1*
42
45
 
43
46
  ## Overview
44
47
 
@@ -222,3 +225,68 @@ docker-compose up -d
222
225
 
223
226
  ![GitHub followers](https://img.shields.io/github/followers/Knucklessg1)
224
227
  ![GitHub User's stars](https://img.shields.io/github/stars/Knucklessg1)
228
+
229
+
230
+ ## MCP Configuration Examples
231
+
232
+ ### 1. Standard IO (stdio) Deployment
233
+
234
+ ```json
235
+ {
236
+ "mcpServers": {
237
+ "github-agent": {
238
+ "command": "uv",
239
+ "args": [
240
+ "run",
241
+ "github-mcp"
242
+ ],
243
+ "env": {
244
+ "AGENT_DESCRIPTION": "<YOUR_AGENT_DESCRIPTION>",
245
+ "AGENT_SYSTEM_PROMPT": "<YOUR_AGENT_SYSTEM_PROMPT>",
246
+ "CONTENTSTOOL": "True",
247
+ "DEFAULT_AGENT_NAME": "<YOUR_DEFAULT_AGENT_NAME>",
248
+ "GITHUB_TOKEN": "<YOUR_GITHUB_TOKEN>",
249
+ "GITHUB_URL": "<YOUR_GITHUB_URL>",
250
+ "GITHUB_VERIFY": "<YOUR_GITHUB_VERIFY>",
251
+ "ISSUETOOL": "True",
252
+ "PULLSTOOL": "True",
253
+ "REPOSTOOL": "True"
254
+ }
255
+ }
256
+ }
257
+ }
258
+ ```
259
+
260
+ ### 2. Streamable HTTP (SSE) Deployment
261
+
262
+ ```json
263
+ {
264
+ "mcpServers": {
265
+ "github-agent": {
266
+ "command": "uv",
267
+ "args": [
268
+ "run",
269
+ "github-mcp",
270
+ "--transport",
271
+ "http",
272
+ "--host",
273
+ "0.0.0.0",
274
+ "--port",
275
+ "8000"
276
+ ],
277
+ "env": {
278
+ "AGENT_DESCRIPTION": "<YOUR_AGENT_DESCRIPTION>",
279
+ "AGENT_SYSTEM_PROMPT": "<YOUR_AGENT_SYSTEM_PROMPT>",
280
+ "CONTENTSTOOL": "True",
281
+ "DEFAULT_AGENT_NAME": "<YOUR_DEFAULT_AGENT_NAME>",
282
+ "GITHUB_TOKEN": "<YOUR_GITHUB_TOKEN>",
283
+ "GITHUB_URL": "<YOUR_GITHUB_URL>",
284
+ "GITHUB_VERIFY": "<YOUR_GITHUB_VERIFY>",
285
+ "ISSUETOOL": "True",
286
+ "PULLSTOOL": "True",
287
+ "REPOSTOOL": "True"
288
+ }
289
+ }
290
+ }
291
+ }
292
+ ```
@@ -1,20 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: github-agent
3
- Version: 0.2.55
4
- Summary: GitHub Agent for MCP
5
- Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
- License: MIT
7
- Classifier: Development Status :: 5 - Production/Stable
8
- Classifier: License :: Public Domain
9
- Classifier: Environment :: Console
10
- Classifier: Operating System :: POSIX :: Linux
11
- Classifier: Programming Language :: Python :: 3
12
- Requires-Python: >=3.10
13
- Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Requires-Dist: agent-utilities[agent,logfire]>=0.2.31
16
- Dynamic: license-file
17
-
18
1
  # GitHub Agent - A2A | AG-UI | MCP
19
2
 
20
3
  ![PyPI - Version](https://img.shields.io/pypi/v/github-agent)
@@ -38,7 +21,7 @@ Dynamic: license-file
38
21
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/github-agent)
39
22
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/github-agent)
40
23
 
41
- *Version: 0.2.55*
24
+ *Version: 0.7.1*
42
25
 
43
26
  ## Overview
44
27
 
@@ -222,3 +205,68 @@ docker-compose up -d
222
205
 
223
206
  ![GitHub followers](https://img.shields.io/github/followers/Knucklessg1)
224
207
  ![GitHub User's stars](https://img.shields.io/github/stars/Knucklessg1)
208
+
209
+
210
+ ## MCP Configuration Examples
211
+
212
+ ### 1. Standard IO (stdio) Deployment
213
+
214
+ ```json
215
+ {
216
+ "mcpServers": {
217
+ "github-agent": {
218
+ "command": "uv",
219
+ "args": [
220
+ "run",
221
+ "github-mcp"
222
+ ],
223
+ "env": {
224
+ "AGENT_DESCRIPTION": "<YOUR_AGENT_DESCRIPTION>",
225
+ "AGENT_SYSTEM_PROMPT": "<YOUR_AGENT_SYSTEM_PROMPT>",
226
+ "CONTENTSTOOL": "True",
227
+ "DEFAULT_AGENT_NAME": "<YOUR_DEFAULT_AGENT_NAME>",
228
+ "GITHUB_TOKEN": "<YOUR_GITHUB_TOKEN>",
229
+ "GITHUB_URL": "<YOUR_GITHUB_URL>",
230
+ "GITHUB_VERIFY": "<YOUR_GITHUB_VERIFY>",
231
+ "ISSUETOOL": "True",
232
+ "PULLSTOOL": "True",
233
+ "REPOSTOOL": "True"
234
+ }
235
+ }
236
+ }
237
+ }
238
+ ```
239
+
240
+ ### 2. Streamable HTTP (SSE) Deployment
241
+
242
+ ```json
243
+ {
244
+ "mcpServers": {
245
+ "github-agent": {
246
+ "command": "uv",
247
+ "args": [
248
+ "run",
249
+ "github-mcp",
250
+ "--transport",
251
+ "http",
252
+ "--host",
253
+ "0.0.0.0",
254
+ "--port",
255
+ "8000"
256
+ ],
257
+ "env": {
258
+ "AGENT_DESCRIPTION": "<YOUR_AGENT_DESCRIPTION>",
259
+ "AGENT_SYSTEM_PROMPT": "<YOUR_AGENT_SYSTEM_PROMPT>",
260
+ "CONTENTSTOOL": "True",
261
+ "DEFAULT_AGENT_NAME": "<YOUR_DEFAULT_AGENT_NAME>",
262
+ "GITHUB_TOKEN": "<YOUR_GITHUB_TOKEN>",
263
+ "GITHUB_URL": "<YOUR_GITHUB_URL>",
264
+ "GITHUB_VERIFY": "<YOUR_GITHUB_VERIFY>",
265
+ "ISSUETOOL": "True",
266
+ "PULLSTOOL": "True",
267
+ "REPOSTOOL": "True"
268
+ }
269
+ }
270
+ }
271
+ }
272
+ ```
@@ -1,8 +1,7 @@
1
1
  #!/usr/bin/python
2
- # coding: utf-8
2
+ import logging
3
3
  import os
4
4
  import sys
5
- import logging
6
5
  import warnings
7
6
 
8
7
  from agent_utilities import (
@@ -13,7 +12,7 @@ from agent_utilities import (
13
12
  load_identity,
14
13
  )
15
14
 
16
- __version__ = "0.2.55"
15
+ __version__ = "0.7.1"
17
16
 
18
17
  logging.basicConfig(
19
18
  level=logging.INFO,
@@ -1,51 +1,52 @@
1
1
  #!/usr/bin/python
2
2
 
3
+ import logging
3
4
  import re
5
+ from concurrent.futures import ThreadPoolExecutor, as_completed
6
+ from typing import TypeVar
7
+
4
8
  import requests
5
9
  import urllib3
6
- import logging
7
- from typing import List, TypeVar, Tuple
8
- from pydantic import ValidationError
9
- from concurrent.futures import ThreadPoolExecutor, as_completed
10
10
  from agent_utilities.base_utilities import get_logger
11
+ from pydantic import BaseModel, ValidationError
11
12
 
12
13
  logger = get_logger(__name__)
13
14
 
15
+ from agent_utilities.core.decorators import require_auth
16
+ from agent_utilities.core.exceptions import (
17
+ AuthError,
18
+ MissingParameterError,
19
+ ParameterError,
20
+ UnauthorizedError,
21
+ )
22
+
14
23
  from github_agent.github_input_models import (
15
- RepoModel,
16
- IssueModel,
17
- PullRequestModel,
18
- ContentModel,
19
24
  BranchModel,
20
25
  CommitModel,
26
+ ContentModel,
27
+ IssueModel,
28
+ PullRequestModel,
29
+ RepoModel,
21
30
  )
22
31
  from github_agent.github_response_models import (
23
- Repository,
24
- Issue,
25
- PullRequest,
26
- Content,
27
32
  Branch,
28
33
  Commit,
34
+ Content,
35
+ Issue,
36
+ PullRequest,
37
+ Repository,
29
38
  Response,
30
39
  )
31
- from agent_utilities.decorators import require_auth
32
- from agent_utilities.exceptions import (
33
- AuthError,
34
- UnauthorizedError,
35
- ParameterError,
36
- MissingParameterError,
37
- )
38
-
39
- T = TypeVar("T")
40
40
 
41
+ T = TypeVar("T", bound=BaseModel)
41
42
 
42
- class Api(object):
43
43
 
44
+ class Api:
44
45
  def __init__(
45
46
  self,
46
47
  url: str = "https://api.github.com",
47
- token: str = None,
48
- proxies: dict = None,
48
+ token: str | None = None,
49
+ proxies: dict | None = None,
49
50
  verify: bool = True,
50
51
  debug: bool = False,
51
52
  ):
@@ -73,7 +74,6 @@ class Api(object):
73
74
  if token:
74
75
  self.headers["Authorization"] = f"Bearer {token}"
75
76
  else:
76
-
77
77
  logger.warning("No token provided for GitHub API")
78
78
 
79
79
  try:
@@ -84,20 +84,20 @@ class Api(object):
84
84
  proxies=self.proxies,
85
85
  )
86
86
  if response.status_code in (401, 403):
87
- logger.error(f"Authentication Error: {response.content}")
87
+ logger.error(f"Authentication Error: {response.text}")
88
88
  raise AuthError if response.status_code == 401 else UnauthorizedError
89
89
  except requests.exceptions.RequestException as e:
90
90
  logger.error(f"Connection Error: {str(e)}")
91
91
 
92
92
  def _fetch_next_page(
93
93
  self, endpoint: str, model: T, header: dict, page: int
94
- ) -> List[dict]:
94
+ ) -> list[dict]:
95
95
  """Fetch a single page of data from the specified endpoint"""
96
- model.page = page
96
+ model.page = page # type: ignore[attr-defined]
97
97
  model.model_post_init(None)
98
98
  response = self._session.get(
99
99
  url=f"{self.url}{endpoint}" if endpoint.startswith("/") else endpoint,
100
- params=model.api_parameters,
100
+ params=model.api_parameters, # type: ignore[attr-defined]
101
101
  headers=header,
102
102
  verify=self.verify,
103
103
  proxies=self.proxies,
@@ -119,7 +119,7 @@ class Api(object):
119
119
 
120
120
  def _fetch_all_pages(
121
121
  self, endpoint: str, model: T
122
- ) -> Tuple[requests.Response, List[dict]]:
122
+ ) -> tuple[requests.Response, list[dict]]:
123
123
  """Generic method to fetch all pages with parallelization if possible"""
124
124
  all_data = []
125
125
 
@@ -127,7 +127,7 @@ class Api(object):
127
127
 
128
128
  response = self._session.get(
129
129
  url=initial_url,
130
- params=model.api_parameters,
130
+ params=model.api_parameters, # type: ignore[attr-defined]
131
131
  headers=self.headers,
132
132
  verify=self.verify,
133
133
  proxies=self.proxies,
@@ -142,14 +142,15 @@ class Api(object):
142
142
 
143
143
  total_pages = self._get_total_pages(response)
144
144
 
145
- if not model.max_pages or model.max_pages == 0 or model.max_pages > total_pages:
146
- model.max_pages = total_pages
147
-
148
- if model.max_pages > 1:
145
+ max_pages = getattr(model, "max_pages", total_pages)
146
+ if not max_pages or max_pages == 0 or max_pages > total_pages:
147
+ max_pages = total_pages
148
+ model.max_pages = total_pages # type: ignore[attr-defined]
149
149
 
150
+ if max_pages > 1:
150
151
  with ThreadPoolExecutor(max_workers=5) as executor:
151
152
  futures = []
152
- for page in range(2, model.max_pages + 1):
153
+ for page in range(2, max_pages + 1):
153
154
  futures.append(
154
155
  executor.submit(
155
156
  self._fetch_next_page,
@@ -177,7 +178,7 @@ class Api(object):
177
178
  parsed_data = [Repository(**item) for item in data]
178
179
  return Response(response=response, data=parsed_data)
179
180
  except ValidationError as e:
180
- raise ParameterError(f"Invalid parameters: {e.errors()}")
181
+ raise ParameterError(f"Invalid parameters: {e.errors()}") from e
181
182
 
182
183
  @require_auth
183
184
  def get_repository(self, owner: str, repo: str) -> Response:
@@ -194,8 +195,8 @@ class Api(object):
194
195
  return Response(response=response, data=parsed_data)
195
196
  except requests.exceptions.HTTPError as e:
196
197
  if e.response.status_code == 404:
197
- raise ParameterError(f"Repository {owner}/{repo} not found")
198
- raise e
198
+ raise ParameterError(f"Repository {owner}/{repo} not found") from e
199
+ raise
199
200
 
200
201
  @require_auth
201
202
  def get_issues(self, **kwargs) -> Response:
@@ -210,7 +211,7 @@ class Api(object):
210
211
  parsed_data = [Issue(**item) for item in data]
211
212
  return Response(response=response, data=parsed_data)
212
213
  except ValidationError as e:
213
- raise ParameterError(f"Invalid parameters: {e.errors()}")
214
+ raise ParameterError(f"Invalid parameters: {e.errors()}") from e
214
215
 
215
216
  @require_auth
216
217
  def get_pull_requests(self, **kwargs) -> Response:
@@ -225,7 +226,7 @@ class Api(object):
225
226
  parsed_data = [PullRequest(**item) for item in data]
226
227
  return Response(response=response, data=parsed_data)
227
228
  except ValidationError as e:
228
- raise ParameterError(f"Invalid parameters: {e.errors()}")
229
+ raise ParameterError(f"Invalid parameters: {e.errors()}") from e
229
230
 
230
231
  @require_auth
231
232
  def get_contents(self, **kwargs) -> Response:
@@ -241,13 +242,14 @@ class Api(object):
241
242
  )
242
243
  response.raise_for_status()
243
244
  data = response.json()
245
+ parsed_data: list[Content] | Content
244
246
  if isinstance(data, list):
245
247
  parsed_data = [Content(**item) for item in data]
246
248
  else:
247
249
  parsed_data = Content(**data)
248
250
  return Response(response=response, data=parsed_data)
249
251
  except ValidationError as e:
250
- raise ParameterError(f"Invalid parameters: {e.errors()}")
252
+ raise ParameterError(f"Invalid parameters: {e.errors()}") from e
251
253
 
252
254
  @require_auth
253
255
  def get_branches(self, **kwargs) -> Response:
@@ -260,7 +262,7 @@ class Api(object):
260
262
  parsed_data = [Branch(**item) for item in data]
261
263
  return Response(response=response, data=parsed_data)
262
264
  except ValidationError as e:
263
- raise ParameterError(f"Invalid parameters: {e.errors()}")
265
+ raise ParameterError(f"Invalid parameters: {e.errors()}") from e
264
266
 
265
267
  @require_auth
266
268
  def get_commits(self, **kwargs) -> Response:
@@ -273,4 +275,4 @@ class Api(object):
273
275
  parsed_data = [Commit(**item) for item in data]
274
276
  return Response(response=response, data=parsed_data)
275
277
  except ValidationError as e:
276
- raise ParameterError(f"Invalid parameters: {e.errors()}")
278
+ raise ParameterError(f"Invalid parameters: {e.errors()}") from e
@@ -2,12 +2,12 @@
2
2
 
3
3
  import os
4
4
  import threading
5
- from typing import Optional
6
5
 
7
6
  import requests
8
- from agent_utilities.base_utilities import to_boolean, get_logger
9
- from github_agent.api_wrapper import Api
10
- from agent_utilities.exceptions import AuthError, UnauthorizedError
7
+ from agent_utilities.base_utilities import get_logger, to_boolean
8
+ from agent_utilities.core.exceptions import AuthError, UnauthorizedError
9
+
10
+ from github_agent.api_client import Api
11
11
 
12
12
  local = threading.local()
13
13
  logger = get_logger(__name__)
@@ -15,9 +15,9 @@ logger = get_logger(__name__)
15
15
 
16
16
  def get_client(
17
17
  instance: str = os.getenv("GITHUB_URL", "https://api.github.com"),
18
- token: Optional[str] = os.getenv("GITHUB_TOKEN", None),
18
+ token: str | None = os.getenv("GITHUB_TOKEN", None),
19
19
  verify: bool = to_boolean(string=os.getenv("GITHUB_VERIFY", "True")),
20
- config: Optional[dict] = None,
20
+ config: dict | None = None,
21
21
  ) -> Api:
22
22
  """
23
23
  Factory function to create the GitHub Api client.
@@ -45,22 +45,22 @@ def get_client(
45
45
  exchange_data = {
46
46
  "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
47
47
  "subject_token": user_token,
48
- "subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
49
- "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
48
+ "subject_token_type": "urn:ietf:params:oauth:token-type:access_token", # nosec B105
49
+ "requested_token_type": "urn:ietf:params:oauth:token-type:access_token", # nosec B105
50
50
  "audience": config["audience"],
51
51
  "scope": config["delegated_scopes"],
52
52
  }
53
53
  auth = (config["oidc_client_id"], config["oidc_client_secret"])
54
54
  try:
55
55
  response = requests.post(
56
- config["token_endpoint"], data=exchange_data, auth=auth
56
+ config["token_endpoint"], data=exchange_data, auth=auth, timeout=30
57
57
  )
58
58
  response.raise_for_status()
59
59
  new_token = response.json()["access_token"]
60
60
  logger.info("Token exchange successful")
61
61
  except Exception as e:
62
62
  logger.error(f"Token exchange failed: {str(e)}")
63
- raise RuntimeError(f"Token exchange failed: {str(e)}")
63
+ raise RuntimeError(f"Token exchange failed: {str(e)}") from e
64
64
 
65
65
  try:
66
66
  return Api(
@@ -1,6 +1,6 @@
1
- #!/usr/bin/python
1
+ from typing import Any
2
2
 
3
- from typing import Union, List, Dict, Optional
3
+ #!/usr/bin/python
4
4
  from pydantic import (
5
5
  BaseModel,
6
6
  Field,
@@ -12,12 +12,14 @@ class BaseModelWrapper(BaseModel):
12
12
  Base Model wrapping common functionalities.
13
13
  """
14
14
 
15
- max_pages: Optional[int] = Field(
15
+ max_pages: int | None = Field(
16
16
  description="Max amount of pages to retrieve", default=None
17
17
  )
18
- page: Optional[int] = Field(description="Pagination page", default=1)
19
- per_page: Optional[int] = Field(description="Results per page", default=100)
20
- api_parameters: Optional[Dict] = Field(description="API Parameters", default=None)
18
+ page: int | None = Field(description="Pagination page", default=1)
19
+ per_page: int | None = Field(description="Results per page", default=100)
20
+ api_parameters: dict[str, Any] = Field(
21
+ description="API Parameters", default_factory=dict
22
+ )
21
23
 
22
24
  def model_post_init(self, __context):
23
25
  self.api_parameters = {}
@@ -32,15 +34,13 @@ class RepoModel(BaseModelWrapper):
32
34
  Pydantic model for Repository requests.
33
35
  """
34
36
 
35
- owner: Optional[str] = Field(
36
- None, description="The account owner of the repository."
37
- )
38
- repo: Optional[str] = Field(None, description="The name of the repository.")
39
- visibility: Optional[str] = Field(
37
+ owner: str | None = Field(None, description="The account owner of the repository.")
38
+ repo: str | None = Field(None, description="The name of the repository.")
39
+ visibility: str | None = Field(
40
40
  None, description="Can be one of all, public, or private."
41
41
  )
42
- affiliation: Optional[str] = Field(None, description="Affiliation filter.")
43
- type: Optional[str] = Field(
42
+ affiliation: str | None = Field(None, description="Affiliation filter.")
43
+ type: str | None = Field(
44
44
  None, description="Can be one of all, owner, public, private, member."
45
45
  )
46
46
 
@@ -61,25 +61,25 @@ class IssueModel(BaseModelWrapper):
61
61
 
62
62
  owner: str = Field(..., description="The account owner of the repository.")
63
63
  repo: str = Field(..., description="The name of the repository.")
64
- issue_number: Optional[int] = Field(
64
+ issue_number: int | None = Field(
65
65
  None, description="The number that identifies the issue."
66
66
  )
67
- state: Optional[str] = Field(
67
+ state: str | None = Field(
68
68
  None,
69
69
  description="Indicates the state of the issues to return. Can be either open, closed, or all.",
70
70
  )
71
- labels: Optional[Union[str, List[str]]] = Field(
71
+ labels: str | list[str] | None = Field(
72
72
  None, description="A list of comma separated label names."
73
73
  )
74
- assignee: Optional[str] = Field(
74
+ assignee: str | None = Field(
75
75
  None,
76
76
  description="Can be the name of a user. Use none for issues with no assigned user, and * for assigned issues to any user.",
77
77
  )
78
- creator: Optional[str] = Field(None, description="The user that created the issue.")
79
- mentioned: Optional[str] = Field(
78
+ creator: str | None = Field(None, description="The user that created the issue.")
79
+ mentioned: str | None = Field(
80
80
  None, description="A user that is mentioned in the issue."
81
81
  )
82
- since: Optional[str] = Field(
82
+ since: str | None = Field(
83
83
  None, description="Only show notifications updated after the given time."
84
84
  )
85
85
 
@@ -105,22 +105,22 @@ class PullRequestModel(BaseModelWrapper):
105
105
 
106
106
  owner: str = Field(..., description="The account owner of the repository.")
107
107
  repo: str = Field(..., description="The name of the repository.")
108
- pull_number: Optional[int] = Field(
108
+ pull_number: int | None = Field(
109
109
  None, description="The number that identifies the pull request."
110
110
  )
111
- state: Optional[str] = Field(
111
+ state: str | None = Field(
112
112
  None, description="State of the PR. (open, closed, or all)"
113
113
  )
114
- head: Optional[str] = Field(
114
+ head: str | None = Field(
115
115
  None,
116
116
  description="Filter pulls by head user or head organization and branch name in the format of user:ref-name or organization:ref-name.",
117
117
  )
118
- base: Optional[str] = Field(None, description="Filter pulls by base branch name.")
119
- sort: Optional[str] = Field(
118
+ base: str | None = Field(None, description="Filter pulls by base branch name.")
119
+ sort: str | None = Field(
120
120
  None,
121
121
  description="What to sort results by. Can be created, updated, popularity, long-running.",
122
122
  )
123
- direction: Optional[str] = Field(
123
+ direction: str | None = Field(
124
124
  None, description="The direction of the sort. Can be asc or desc."
125
125
  )
126
126
 
@@ -146,7 +146,7 @@ class ContentModel(BaseModelWrapper):
146
146
  owner: str = Field(..., description="The account owner of the repository.")
147
147
  repo: str = Field(..., description="The name of the repository.")
148
148
  path: str = Field(..., description="The content path.")
149
- ref: Optional[str] = Field(
149
+ ref: str | None = Field(
150
150
  None,
151
151
  description="The name of the commit/branch/tag. Default: the repository's default branch.",
152
152
  )
@@ -164,7 +164,7 @@ class BranchModel(BaseModelWrapper):
164
164
 
165
165
  owner: str = Field(..., description="The account owner of the repository.")
166
166
  repo: str = Field(..., description="The name of the repository.")
167
- branch: Optional[str] = Field(None, description="The name of the branch.")
167
+ branch: str | None = Field(None, description="The name of the branch.")
168
168
 
169
169
  def model_post_init(self, __context):
170
170
  super().model_post_init(__context)
@@ -177,19 +177,19 @@ class CommitModel(BaseModelWrapper):
177
177
 
178
178
  owner: str = Field(..., description="The account owner of the repository.")
179
179
  repo: str = Field(..., description="The name of the repository.")
180
- sha: Optional[str] = Field(
180
+ sha: str | None = Field(
181
181
  None, description="SHA or branch to start listing commits from."
182
182
  )
183
- path: Optional[str] = Field(
183
+ path: str | None = Field(
184
184
  None, description="Only commits containing this file path will be returned."
185
185
  )
186
- author: Optional[str] = Field(
186
+ author: str | None = Field(
187
187
  None, description="GitHub username or email address to filter by commit author."
188
188
  )
189
- since: Optional[str] = Field(
189
+ since: str | None = Field(
190
190
  None, description="Only show notifications updated after the given time."
191
191
  )
192
- until: Optional[str] = Field(
192
+ until: str | None = Field(
193
193
  None, description="Only show notifications updated before the given time."
194
194
  )
195
195