ultralytics-actions 0.0.96__tar.gz → 0.0.98__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. {ultralytics_actions-0.0.96/ultralytics_actions.egg-info → ultralytics_actions-0.0.98}/PKG-INFO +13 -3
  2. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/README.md +12 -2
  3. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/__init__.py +1 -1
  4. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/dispatch_actions.py +4 -3
  5. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/first_interaction.py +7 -6
  6. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/summarize_pr.py +2 -0
  7. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/summarize_release.py +2 -0
  8. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/update_file_headers.py +2 -0
  9. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/update_markdown_code_blocks.py +2 -0
  10. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/utils/common_utils.py +2 -0
  11. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/utils/github_utils.py +3 -2
  12. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/utils/openai_utils.py +13 -18
  13. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/utils/version_utils.py +3 -1
  14. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_file_headers.py +0 -2
  15. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_openai_utils.py +3 -3
  16. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_update_markdown_codeblocks.py +1 -0
  17. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_urls.py +1 -0
  18. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98/ultralytics_actions.egg-info}/PKG-INFO +13 -3
  19. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/LICENSE +0 -0
  20. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/actions/utils/__init__.py +0 -0
  21. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/pyproject.toml +0 -0
  22. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/setup.cfg +0 -0
  23. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_cli_commands.py +0 -0
  24. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_common_utils.py +0 -0
  25. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_dispatch_actions.py +0 -0
  26. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_first_interaction.py +0 -0
  27. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_github_utils.py +0 -0
  28. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_init.py +0 -0
  29. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_summarize_pr.py +0 -0
  30. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/tests/test_summarize_release.py +0 -0
  31. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/ultralytics_actions.egg-info/SOURCES.txt +0 -0
  32. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/ultralytics_actions.egg-info/dependency_links.txt +0 -0
  33. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/ultralytics_actions.egg-info/entry_points.txt +0 -0
  34. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/ultralytics_actions.egg-info/requires.txt +0 -0
  35. {ultralytics_actions-0.0.96 → ultralytics_actions-0.0.98}/ultralytics_actions.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ultralytics-actions
3
- Version: 0.0.96
3
+ Version: 0.0.98
4
4
  Summary: Ultralytics Actions for GitHub automation and PR management.
5
5
  Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>
6
6
  Maintainer-email: Ultralytics <hello@ultralytics.com>
@@ -47,8 +47,6 @@ Welcome to the [Ultralytics Actions](https://github.com/ultralytics/actions) rep
47
47
  [![Actions CI](https://github.com/ultralytics/actions/actions/workflows/ci.yml/badge.svg)](https://github.com/ultralytics/actions/actions/workflows/ci.yml)
48
48
  [![Ultralytics Actions](https://github.com/ultralytics/actions/actions/workflows/format.yml/badge.svg)](https://github.com/ultralytics/actions/actions/workflows/format.yml)
49
49
  [![codecov](https://codecov.io/github/ultralytics/actions/graph/badge.svg?token=DoizJ1WS6j)](https://codecov.io/github/ultralytics/actions)
50
- [![PyPI version](https://badge.fury.io/py/ultralytics-actions.svg)](https://badge.fury.io/py/ultralytics-actions)
51
- [![Downloads](https://static.pepy.tech/badge/ultralytics-actions)](https://clickpy.clickhouse.com/dashboard/ultralytics-actions)
52
50
 
53
51
  [![Ultralytics Discord](https://img.shields.io/discord/1089800235347353640?logo=discord&logoColor=white&label=Discord&color=blue)](https://discord.com/invite/ultralytics)
54
52
  [![Ultralytics Forums](https://img.shields.io/discourse/users?server=https%3A%2F%2Fcommunity.ultralytics.com&logo=discourse&label=Forums&color=blue)](https://community.ultralytics.com/)
@@ -130,6 +128,18 @@ To integrate this action into your Ultralytics repository:
130
128
 
131
129
  3. **Customize:** Adjust the `runs-on` runner and the boolean flags (`labels`, `python`, `prettier`, `swift`, `spelling`, `links`, `summary`) based on your project's needs. Remember to add your `OPENAI_API_KEY` as a secret in your repository settings if you enable `labels` or `summary`.
132
130
 
131
+ ## Python Package
132
+
133
+ Install the `ultralytics-actions` Python package directly with Pip:
134
+
135
+ [![PyPI - Version](https://img.shields.io/pypi/v/ultralytics-actions?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics-actions/)
136
+ [![Ultralytics Downloads](https://static.pepy.tech/badge/ultralytics-actions)](https://clickpy.clickhouse.com/dashboard/ultralytics-actions)
137
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics-actions?logo=python&logoColor=gold)](https://pypi.org/project/ultralytics-actions/)
138
+
139
+ ```sh
140
+ pip install ultralytics-actions
141
+ ```
142
+
133
143
  ## 💡 Contribute
134
144
 
135
145
  Ultralytics thrives on community collaboration, and we deeply value your contributions! Please see our [Contributing Guide](https://docs.ultralytics.com/help/contributing/) for details on how you can get involved. We also encourage you to share your feedback through our [Survey](https://www.ultralytics.com/survey?utm_source=github&utm_medium=social&utm_campaign=Survey). A huge thank you 🙏 to all our contributors!
@@ -9,8 +9,6 @@ Welcome to the [Ultralytics Actions](https://github.com/ultralytics/actions) rep
9
9
  [![Actions CI](https://github.com/ultralytics/actions/actions/workflows/ci.yml/badge.svg)](https://github.com/ultralytics/actions/actions/workflows/ci.yml)
10
10
  [![Ultralytics Actions](https://github.com/ultralytics/actions/actions/workflows/format.yml/badge.svg)](https://github.com/ultralytics/actions/actions/workflows/format.yml)
11
11
  [![codecov](https://codecov.io/github/ultralytics/actions/graph/badge.svg?token=DoizJ1WS6j)](https://codecov.io/github/ultralytics/actions)
12
- [![PyPI version](https://badge.fury.io/py/ultralytics-actions.svg)](https://badge.fury.io/py/ultralytics-actions)
13
- [![Downloads](https://static.pepy.tech/badge/ultralytics-actions)](https://clickpy.clickhouse.com/dashboard/ultralytics-actions)
14
12
 
15
13
  [![Ultralytics Discord](https://img.shields.io/discord/1089800235347353640?logo=discord&logoColor=white&label=Discord&color=blue)](https://discord.com/invite/ultralytics)
16
14
  [![Ultralytics Forums](https://img.shields.io/discourse/users?server=https%3A%2F%2Fcommunity.ultralytics.com&logo=discourse&label=Forums&color=blue)](https://community.ultralytics.com/)
@@ -92,6 +90,18 @@ To integrate this action into your Ultralytics repository:
92
90
 
93
91
  3. **Customize:** Adjust the `runs-on` runner and the boolean flags (`labels`, `python`, `prettier`, `swift`, `spelling`, `links`, `summary`) based on your project's needs. Remember to add your `OPENAI_API_KEY` as a secret in your repository settings if you enable `labels` or `summary`.
94
92
 
93
+ ## Python Package
94
+
95
+ Install the `ultralytics-actions` Python package directly with Pip:
96
+
97
+ [![PyPI - Version](https://img.shields.io/pypi/v/ultralytics-actions?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics-actions/)
98
+ [![Ultralytics Downloads](https://static.pepy.tech/badge/ultralytics-actions)](https://clickpy.clickhouse.com/dashboard/ultralytics-actions)
99
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics-actions?logo=python&logoColor=gold)](https://pypi.org/project/ultralytics-actions/)
100
+
101
+ ```sh
102
+ pip install ultralytics-actions
103
+ ```
104
+
95
105
  ## 💡 Contribute
96
106
 
97
107
  Ultralytics thrives on community collaboration, and we deeply value your contributions! Please see our [Contributing Guide](https://docs.ultralytics.com/help/contributing/) for details on how you can get involved. We also encourage you to share your feedback through our [Survey](https://www.ultralytics.com/survey?utm_source=github&utm_medium=social&utm_campaign=Survey). A huge thank you 🙏 to all our contributors!
@@ -22,4 +22,4 @@
22
22
  # ├── test_summarize_pr.py
23
23
  # └── ...
24
24
 
25
- __version__ = "0.0.96"
25
+ __version__ = "0.0.98"
@@ -1,8 +1,9 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import time
4
6
  from datetime import datetime
5
- from typing import Dict, List
6
7
 
7
8
  from .utils import GITHUB_API_URL, Action
8
9
 
@@ -18,7 +19,7 @@ def get_pr_branch(event) -> str:
18
19
  return pr_data.get("head", {}).get("ref", "main")
19
20
 
20
21
 
21
- def trigger_and_get_workflow_info(event, branch: str) -> List[Dict]:
22
+ def trigger_and_get_workflow_info(event, branch: str) -> list[dict]:
22
23
  """Triggers workflows and returns their information."""
23
24
  repo = event.repository
24
25
  results = []
@@ -56,7 +57,7 @@ def trigger_and_get_workflow_info(event, branch: str) -> List[Dict]:
56
57
  return results
57
58
 
58
59
 
59
- def update_comment(event, comment_body: str, triggered_actions: List[Dict], branch: str) -> bool:
60
+ def update_comment(event, comment_body: str, triggered_actions: list[dict], branch: str) -> bool:
60
61
  """Updates the comment with workflow information."""
61
62
  if not triggered_actions:
62
63
  return False
@@ -1,7 +1,8 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import os
4
- from typing import Dict, List, Tuple
5
6
 
6
7
  from .utils import GITHUB_API_URL, Action, get_completion, remove_html_comments
7
8
 
@@ -9,7 +10,7 @@ from .utils import GITHUB_API_URL, Action, get_completion, remove_html_comments
9
10
  BLOCK_USER = os.getenv("BLOCK_USER", "false").lower() == "true"
10
11
 
11
12
 
12
- def get_event_content(event) -> Tuple[int, str, str, str, str, str, str]:
13
+ def get_event_content(event) -> tuple[int, str, str, str, str, str, str]:
13
14
  """Extracts key information from GitHub event data for issues, pull requests, or discussions."""
14
15
  data = event.event_data
15
16
  name = event.event_name
@@ -108,8 +109,8 @@ def block_user(event, username: str):
108
109
 
109
110
 
110
111
  def get_relevant_labels(
111
- issue_type: str, title: str, body: str, available_labels: Dict, current_labels: List
112
- ) -> List[str]:
112
+ issue_type: str, title: str, body: str, available_labels: dict, current_labels: list
113
+ ) -> list[str]:
113
114
  """Determines relevant labels for GitHub issues/PRs using OpenAI, considering title, body, and existing labels."""
114
115
  # Remove mutually exclusive labels like both 'bug' and 'question' or inappropriate labels like 'help wanted'
115
116
  for label in {
@@ -178,7 +179,7 @@ YOUR RESPONSE (label names only):
178
179
  ]
179
180
 
180
181
 
181
- def get_label_ids(event, labels: List[str]) -> List[str]:
182
+ def get_label_ids(event, labels: list[str]) -> list[str]:
182
183
  """Retrieves GitHub label IDs for a list of label names using the GraphQL API."""
183
184
  query = """
184
185
  query($owner: String!, $name: String!) {
@@ -202,7 +203,7 @@ query($owner: String!, $name: String!) {
202
203
  return []
203
204
 
204
205
 
205
- def apply_labels(event, number: int, node_id: str, labels: List[str], issue_type: str):
206
+ def apply_labels(event, number: int, node_id: str, labels: list[str], issue_type: str):
206
207
  """Applies specified labels to a GitHub issue, pull request, or discussion using the appropriate API."""
207
208
  if "Alert" in labels:
208
209
  create_alert_label(event)
@@ -1,5 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import time
4
6
 
5
7
  from .utils import GITHUB_API_URL, GITHUB_GRAPHQL_URL, Action, get_completion
@@ -1,5 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import os
4
6
  import re
5
7
  import subprocess
@@ -1,5 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import os
4
6
  from pathlib import Path
5
7
 
@@ -1,5 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import hashlib
4
6
  import re
5
7
  import shutil
@@ -1,5 +1,7 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import os
4
6
  import re
5
7
  import time
@@ -1,9 +1,10 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import json
4
6
  import os
5
7
  from pathlib import Path
6
- from typing import Union
7
8
 
8
9
  import requests
9
10
 
@@ -96,7 +97,7 @@ class Action:
96
97
  """Checks if the repository is public using event data or GitHub API if needed."""
97
98
  return self.event_data.get("repository", {}).get("private")
98
99
 
99
- def get_username(self) -> Union[str, None]:
100
+ def get_username(self) -> str | None:
100
101
  """Gets username associated with the GitHub token."""
101
102
  response = self.post(GITHUB_GRAPHQL_URL, json={"query": "query { viewer { login } }"})
102
103
  if response.status_code == 200:
@@ -1,17 +1,17 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+ from __future__ import annotations
4
+
3
5
  import os
4
- import time
5
- from typing import Dict, List
6
6
 
7
7
  import requests
8
8
 
9
9
  from actions.utils.common_utils import check_links_in_string
10
10
 
11
11
  OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
12
- OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-5-2025-08-07")
12
+ OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-5-codex")
13
13
  SYSTEM_PROMPT_ADDITION = """Guidance:
14
- - Ultralytics Branding: Use YOLO11, YOLO12, etc., not YOLOv11, YOLOv12 (only older versions like YOLOv10 have a v). Always capitalize "HUB" in "Ultralytics HUB"; use "Ultralytics HUB", not "The Ultralytics HUB".
14
+ - Ultralytics Branding: Use YOLO11, YOLO26, etc., not YOLOv11, YOLOv26 (only older versions like YOLOv10 have a v). Always capitalize "HUB" in "Ultralytics HUB"; use "Ultralytics HUB", not "The Ultralytics HUB".
15
15
  - Avoid Equations: Do not include equations or mathematical notations.
16
16
  - Markdown: Reply in Markdown format.
17
17
  - Links: Use descriptive anchor text for all URLs.
@@ -34,15 +34,15 @@ def remove_outer_codeblocks(string):
34
34
 
35
35
 
36
36
  def get_completion(
37
- messages: List[Dict[str, str]],
37
+ messages: list[dict[str, str]],
38
38
  check_links: bool = True,
39
- remove: List[str] = (" @giscus[bot]",), # strings to remove from response
39
+ remove: list[str] = (" @giscus[bot]",), # strings to remove from response
40
40
  temperature: float = 1.0, # note GPT-5 requires temperature=1.0
41
41
  reasoning_effort: str = None, # reasoning effort for GPT-5 models: minimal, low, medium, high
42
42
  ) -> str:
43
- """Generates a completion using OpenAI's API based on input messages."""
43
+ """Generates a completion using OpenAI's Responses API based on input messages."""
44
44
  assert OPENAI_API_KEY, "OpenAI API key is required."
45
- url = "https://api.openai.com/v1/chat/completions"
45
+ url = "https://api.openai.com/v1/responses"
46
46
  headers = {"Authorization": f"Bearer {OPENAI_API_KEY}", "Content-Type": "application/json"}
47
47
  if messages and messages[0].get("role") == "system":
48
48
  messages[0]["content"] += "\n\n" + SYSTEM_PROMPT_ADDITION
@@ -50,20 +50,15 @@ def get_completion(
50
50
  content = ""
51
51
  max_retries = 2
52
52
  for attempt in range(max_retries + 2): # attempt = [0, 1, 2, 3], 2 random retries before asking for no links
53
- data = {
54
- "model": OPENAI_MODEL,
55
- "messages": messages,
56
- "seed": int(time.time() * 1000),
57
- "temperature": temperature,
58
- }
59
-
60
- # Add reasoning_effort for GPT-5 models
53
+ data = {"model": OPENAI_MODEL, "input": messages, "store": False, "temperature": temperature}
54
+
55
+ # Add reasoning for GPT-5 models
61
56
  if "gpt-5" in OPENAI_MODEL:
62
- data["reasoning_effort"] = reasoning_effort or "low" # Default to low for GPT-5
57
+ data["reasoning"] = {"effort": reasoning_effort or "low"} # Default to low for GPT-5
63
58
 
64
59
  r = requests.post(url, json=data, headers=headers)
65
60
  r.raise_for_status()
66
- content = r.json()["choices"][0]["message"]["content"].strip()
61
+ content = r.json()["output_text"].strip()
67
62
  content = remove_outer_codeblocks(content)
68
63
  for x in remove:
69
64
  content = content.replace(x, "")
@@ -3,6 +3,8 @@
3
3
  # from actions.utils.version_utils import check_pypi_version
4
4
  # check_pypi_version()
5
5
 
6
+ from __future__ import annotations
7
+
6
8
  import re
7
9
  from pathlib import Path
8
10
 
@@ -13,7 +15,7 @@ def should_publish(local_version, remote_version):
13
15
  """Determine if version should be published based on semver rules."""
14
16
  if remote_version:
15
17
  local_ver, remote_ver = [tuple(map(int, v.split("."))) for v in [local_version, remote_version]]
16
- major_diff, minor_diff, patch_diff = [l - r for l, r in zip(local_ver, remote_ver)]
18
+ major_diff, minor_diff, patch_diff = [local - remote for local, remote in zip(local_ver, remote_ver)]
17
19
  return (
18
20
  (major_diff == 0 and minor_diff == 0 and 0 < patch_diff <= 2) # patch diff <=2
19
21
  or (major_diff == 0 and minor_diff == 1 and local_ver[2] == 0) # new minor version
@@ -1,6 +1,4 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
-
3
- # tests/test_update_file_headers.py
4
2
  """Tests for the file headers update functionality."""
5
3
 
6
4
  from pathlib import Path
@@ -24,11 +24,11 @@ def test_remove_outer_codeblocks():
24
24
 
25
25
  @patch("requests.post")
26
26
  def test_get_completion(mock_post):
27
- """Test OpenAI API completion function with mocked response."""
27
+ """Test OpenAI Responses API completion function with mocked response."""
28
28
  # Setup mock response
29
29
  mock_response = MagicMock()
30
30
  mock_response.status_code = 200
31
- mock_response.json.return_value = {"choices": [{"message": {"content": "Test response from OpenAI"}}]}
31
+ mock_response.json.return_value = {"output_text": "Test response from OpenAI"}
32
32
  mock_post.return_value = mock_response
33
33
 
34
34
  # Test with basic messages
@@ -50,7 +50,7 @@ def test_get_completion_with_link_check(mock_check_links, mock_post):
50
50
  # Setup mocks
51
51
  mock_response = MagicMock()
52
52
  mock_response.status_code = 200
53
- mock_response.json.return_value = {"choices": [{"message": {"content": "Response with https://example.com link"}}]}
53
+ mock_response.json.return_value = {"output_text": "Response with https://example.com link"}
54
54
  mock_post.return_value = mock_response
55
55
  mock_check_links.return_value = True
56
56
 
@@ -1,5 +1,6 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
+
3
4
  from pathlib import Path
4
5
  from unittest.mock import mock_open, patch
5
6
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  # Continuous Integration (CI) GitHub Actions tests
4
4
 
5
+
5
6
  import pytest
6
7
 
7
8
  from actions.utils.common_utils import check_links_in_string, is_url
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ultralytics-actions
3
- Version: 0.0.96
3
+ Version: 0.0.98
4
4
  Summary: Ultralytics Actions for GitHub automation and PR management.
5
5
  Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>
6
6
  Maintainer-email: Ultralytics <hello@ultralytics.com>
@@ -47,8 +47,6 @@ Welcome to the [Ultralytics Actions](https://github.com/ultralytics/actions) rep
47
47
  [![Actions CI](https://github.com/ultralytics/actions/actions/workflows/ci.yml/badge.svg)](https://github.com/ultralytics/actions/actions/workflows/ci.yml)
48
48
  [![Ultralytics Actions](https://github.com/ultralytics/actions/actions/workflows/format.yml/badge.svg)](https://github.com/ultralytics/actions/actions/workflows/format.yml)
49
49
  [![codecov](https://codecov.io/github/ultralytics/actions/graph/badge.svg?token=DoizJ1WS6j)](https://codecov.io/github/ultralytics/actions)
50
- [![PyPI version](https://badge.fury.io/py/ultralytics-actions.svg)](https://badge.fury.io/py/ultralytics-actions)
51
- [![Downloads](https://static.pepy.tech/badge/ultralytics-actions)](https://clickpy.clickhouse.com/dashboard/ultralytics-actions)
52
50
 
53
51
  [![Ultralytics Discord](https://img.shields.io/discord/1089800235347353640?logo=discord&logoColor=white&label=Discord&color=blue)](https://discord.com/invite/ultralytics)
54
52
  [![Ultralytics Forums](https://img.shields.io/discourse/users?server=https%3A%2F%2Fcommunity.ultralytics.com&logo=discourse&label=Forums&color=blue)](https://community.ultralytics.com/)
@@ -130,6 +128,18 @@ To integrate this action into your Ultralytics repository:
130
128
 
131
129
  3. **Customize:** Adjust the `runs-on` runner and the boolean flags (`labels`, `python`, `prettier`, `swift`, `spelling`, `links`, `summary`) based on your project's needs. Remember to add your `OPENAI_API_KEY` as a secret in your repository settings if you enable `labels` or `summary`.
132
130
 
131
+ ## Python Package
132
+
133
+ Install the `ultralytics-actions` Python package directly with Pip:
134
+
135
+ [![PyPI - Version](https://img.shields.io/pypi/v/ultralytics-actions?logo=pypi&logoColor=white)](https://pypi.org/project/ultralytics-actions/)
136
+ [![Ultralytics Downloads](https://static.pepy.tech/badge/ultralytics-actions)](https://clickpy.clickhouse.com/dashboard/ultralytics-actions)
137
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ultralytics-actions?logo=python&logoColor=gold)](https://pypi.org/project/ultralytics-actions/)
138
+
139
+ ```sh
140
+ pip install ultralytics-actions
141
+ ```
142
+
133
143
  ## 💡 Contribute
134
144
 
135
145
  Ultralytics thrives on community collaboration, and we deeply value your contributions! Please see our [Contributing Guide](https://docs.ultralytics.com/help/contributing/) for details on how you can get involved. We also encourage you to share your feedback through our [Survey](https://www.ultralytics.com/survey?utm_source=github&utm_medium=social&utm_campaign=Survey). A huge thank you 🙏 to all our contributors!