github-haystack 1.1.0__py3-none-any.whl → 1.2.0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-haystack
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Haystack components for interacting with GitHub repositories
5
5
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/github
6
6
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/github/README.md
@@ -27,19 +27,10 @@ Description-Content-Type: text/markdown
27
27
  [![PyPI - Version](https://img.shields.io/pypi/v/github-haystack.svg)](https://pypi.org/project/github-haystack)
28
28
  [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/github-haystack.svg)](https://pypi.org/project/github-haystack)
29
29
 
30
- -----
30
+ - [Integration page](https://haystack.deepset.ai/integrations/github)
31
+ - [Changelog](https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/github/CHANGELOG.md)
32
+
33
+ ---
34
+ ## Contributing
31
35
 
32
- ## Table of Contents
33
-
34
- - [Installation](#installation)
35
- - [License](#license)
36
-
37
- ## Installation
38
-
39
- ```console
40
- pip install github-haystack
41
- ```
42
-
43
- ## License
44
-
45
- `github-haystack` is distributed under the terms of the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license.
36
+ Refer to the general [Contribution Guidelines](https://github.com/deepset-ai/haystack-core-integrations/blob/main/CONTRIBUTING.md).
@@ -1,29 +1,31 @@
1
1
  haystack_integrations/components/connectors/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  haystack_integrations/components/connectors/github/__init__.py,sha256=aRIkCcJ_ogsyt67cwjZQu8rqP7yIQu8jRzK6TAYRGx4,557
3
- haystack_integrations/components/connectors/github/file_editor.py,sha256=DbW57Ztm9kv8mCYSJGhUY7xp9wXOvRdhomOosNbBFnQ,11738
3
+ haystack_integrations/components/connectors/github/file_editor.py,sha256=9WnQuhy8A5hnkoAzm6pCJzD773eQrcmDhLCxnyyQt84,11732
4
4
  haystack_integrations/components/connectors/github/issue_commenter.py,sha256=S8VhaPaIQJ29TJNMsnfPns4lNBNAnC0QUxuktKTrnfE,5618
5
5
  haystack_integrations/components/connectors/github/issue_viewer.py,sha256=Xionw1Y8jGxMCo2AXDUjqWk_yaJTW0d9xhvSr8bOGcM,7368
6
6
  haystack_integrations/components/connectors/github/pr_creator.py,sha256=KEWgXVQlLjaSJiwqn-5vIxOCG1PHH8OKEJtNphI3o_g,11428
7
- haystack_integrations/components/connectors/github/repo_forker.py,sha256=C52zONah1E5BNsNzOILohDKl2QBXZcJn3t1fm7AedQs,11538
7
+ haystack_integrations/components/connectors/github/repo_forker.py,sha256=7OYtBgumMlE1HIb9Q0svEoahcdf3S7NJv0Jha6HjoOM,11522
8
8
  haystack_integrations/components/connectors/github/repo_viewer.py,sha256=tECbnxaBxqX3zAZQ2MzCrqvKfY-Ml9MGMhgtLKrsmKw,9199
9
9
  haystack_integrations/prompts/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- haystack_integrations/prompts/github/__init__.py,sha256=jjkSZGJ76S0EX-ZTv4qrhpxGrwVpBb_TCyqMJFhl2ec,759
10
+ haystack_integrations/prompts/github/__init__.py,sha256=cs_w-7RycC2C9q35pN0jY-McAHWbTIM-j_O2S-AIM7Q,882
11
11
  haystack_integrations/prompts/github/context_prompt.py,sha256=RSzISqtaBHaC7v6rcyyxt2vxmbBVp5OHsWR6Z2wp5pk,8783
12
12
  haystack_integrations/prompts/github/file_editor_prompt.py,sha256=_ro-I3MbVIpYpVFJbSpj4TuzbKLX7wTGn55Q95q8jFE,3301
13
13
  haystack_integrations/prompts/github/issue_commenter_prompt.py,sha256=EPynR1z6joRMowsse5hHjkDmpQljYeEBK4fCCxeBCvY,904
14
14
  haystack_integrations/prompts/github/issue_viewer_prompt.py,sha256=QlEjfrnoTRiZYlbySMbGu2EP2jfi62c3qfEPNuV_bUc,930
15
15
  haystack_integrations/prompts/github/pr_creator_prompt.py,sha256=tNC9BdzIowZ42o8bmnrJ46aonIzMfVHRrZopwryiABI,3944
16
+ haystack_integrations/prompts/github/repo_forker_prompt.py,sha256=VU-80JpGFP5R7haEHQEiKYAnHzU1iSKCD4qUThCpudA,2654
16
17
  haystack_integrations/prompts/github/repo_viewer_prompt.py,sha256=JkU2ODn06Vs_YQozF1H0vYym7jzczSdN1kAOXSD5IkA,3257
17
18
  haystack_integrations/prompts/github/system_prompt.py,sha256=xiOEAbENJiLHL8M1qrgSdUxrfguAphI_6B0kqelxDok,4209
18
19
  haystack_integrations/tools/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- haystack_integrations/tools/github/__init__.py,sha256=FyNJ5F0IO2Xied-wP6utoMB13lPLK1Y0fAu7YlKhWu0,532
20
+ haystack_integrations/tools/github/__init__.py,sha256=ZJKLyVZRXcg5mU-AdH_Xk1rNLeiItlPqgmY6eTqFSTA,611
20
21
  haystack_integrations/tools/github/file_editor_tool.py,sha256=ETvDnSqjaXgzHyo8nNtqhxgZf0RiM4Z7k82TDyOLPTo,5178
21
22
  haystack_integrations/tools/github/issue_commenter_tool.py,sha256=AVlto9NxLLJcnmW-U2PZhOoeagICh7STQR5_paXfY2Y,5125
22
23
  haystack_integrations/tools/github/issue_viewer_tool.py,sha256=mEiDxyx9xuttOR3LEq29eETt4UYF8zBd8uAtWE3TuiI,5065
23
24
  haystack_integrations/tools/github/pr_creator_tool.py,sha256=Bfqn1gSsnfkzJg69Dk4DuICnjkviHYIw7vTX9zsaQa4,4824
25
+ haystack_integrations/tools/github/repo_forker_tool.py,sha256=gd50C3Scfl-KZyJySWMrBq_d-HeAU38rMIQZCBHHI84,4834
24
26
  haystack_integrations/tools/github/repo_viewer_tool.py,sha256=QWnbpQS3XrmxJ3qbBIjTUR9eOXfHR_MfQgd1ClDS5qE,5883
25
27
  haystack_integrations/tools/github/utils.py,sha256=iSIEFulC3KqZvAY1QcrE2rTZJSkCp49SSqC62BTpcs8,3312
26
- github_haystack-1.1.0.dist-info/METADATA,sha256=Ks5JPUEfFqMCy7N0JCE3leQnQ7VAUqfaGefteHSx94k,1709
27
- github_haystack-1.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
28
- github_haystack-1.1.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
29
- github_haystack-1.1.0.dist-info/RECORD,,
28
+ github_haystack-1.2.0.dist-info/METADATA,sha256=UJCimOUWJoKgdjVreeQ5uLJoD5RR8cls-WvDLaxxuxs,1771
29
+ github_haystack-1.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
30
+ github_haystack-1.2.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
31
+ github_haystack-1.2.0.dist-info/RECORD,,
@@ -225,7 +225,7 @@ class GitHubFileEditor:
225
225
  def _delete_file(self, owner: str, repo: str, payload: Dict[str, str], branch: str) -> str:
226
226
  """Handle file deletion."""
227
227
  try:
228
- content, sha = self._get_file_content(owner, repo, payload["path"], branch)
228
+ _, sha = self._get_file_content(owner, repo, payload["path"], branch)
229
229
  url = f"https://api.github.com/repos/{owner}/{repo}/contents/{payload['path']}"
230
230
 
231
231
  data = {"message": payload["message"], "sha": sha, "branch": branch}
@@ -60,9 +60,9 @@ class GitHubRepoForker:
60
60
  :param auto_sync: If True, syncs fork with original repository if it already exists
61
61
  :param create_branch: If True, creates a fix branch based on the issue number
62
62
  """
63
- error_message = "github_token must be a Secret"
64
63
  if not isinstance(github_token, Secret):
65
- raise TypeError(error_message)
64
+ msg = "github_token must be a Secret"
65
+ raise TypeError(msg)
66
66
 
67
67
  self.github_token = github_token
68
68
  self.raise_on_failure = raise_on_failure
@@ -5,6 +5,7 @@ from .context_prompt import CONTEXT_PROMPT
5
5
  from .file_editor_prompt import FILE_EDITOR_PROMPT, FILE_EDITOR_SCHEMA
6
6
  from .issue_commenter_prompt import ISSUE_COMMENTER_PROMPT, ISSUE_COMMENTER_SCHEMA
7
7
  from .pr_creator_prompt import PR_CREATOR_PROMPT, PR_CREATOR_SCHEMA
8
+ from .repo_forker_prompt import REPO_FORKER_PROMPT, REPO_FORKER_SCHEMA
8
9
  from .repo_viewer_prompt import REPO_VIEWER_PROMPT, REPO_VIEWER_SCHEMA
9
10
  from .system_prompt import SYSTEM_PROMPT
10
11
 
@@ -16,6 +17,8 @@ __all__ = [
16
17
  "ISSUE_COMMENTER_SCHEMA",
17
18
  "PR_CREATOR_PROMPT",
18
19
  "PR_CREATOR_SCHEMA",
20
+ "REPO_FORKER_PROMPT",
21
+ "REPO_FORKER_SCHEMA",
19
22
  "REPO_VIEWER_PROMPT",
20
23
  "REPO_VIEWER_SCHEMA",
21
24
  "SYSTEM_PROMPT",
@@ -0,0 +1,61 @@
1
+ # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ REPO_FORKER_PROMPT = """Haystack-Agent uses this tool to fork GitHub repositories in order to contribute to issues.
5
+ Haystack-Agent initiates a fork so it can freely make changes for contributions.
6
+ A fork is required to open a pull request to the upstream repository.
7
+ Haystack-Agent works by forking the repository associated with a given issue.
8
+
9
+ <usage>
10
+ Pass a `url` string for the GitHub issue you want to work on in a fork.
11
+ It is REQUIRED to pass `url` to use this tool.
12
+ The structure must be "https://github.com/<repo-owner>/<repo-name>/issues/<issue-number>".
13
+
14
+ Examples:
15
+
16
+ - {"url": "https://github.com/deepset-ai/haystack/issues/9343"}
17
+ - will fork the "deepset-ai/haystack" repository to work on issue 9343
18
+ - {"url": "https://github.com/deepset-ai/haystack-core-integrations/issues/1685"}
19
+ - will fork the "deepset-ai/haystack-core-integrations" repository to work on issue 1685
20
+ </usage>
21
+
22
+ Haystack-Agent uses the `repo_forker` tool to create a copy (fork) of the target repository into its own account.
23
+ Haystack-Agent ensures the issue URL is valid and points to a real GitHub issue.
24
+ It parses the URL to identify the correct repository.
25
+
26
+ <thinking>
27
+ - Does this issue belong to the repository I need to work on?
28
+ - Can I extract the owner and repository name from the URL?
29
+ - Why am I forking this repository? (e.g., to implement a fix, to add a feature)
30
+ - Is there anything special about the branch or base state I should be aware of?
31
+ </thinking>
32
+
33
+ Haystack-Agent reflects on the results after forking:
34
+ <thinking>
35
+ - Did the fork succeed? Is the fork visible in my account?
36
+ - Can I access, clone, and push to my fork?
37
+ - Are there any permissions or fork-specific settings to configure before proceeding?
38
+ - Which branch will I be working on in the fork?
39
+ </thinking>
40
+
41
+ IMPORTANT
42
+ Haystack-Agent ONLY forks the repository mentioned in the given issue URL.
43
+ Haystack-Agent does NOT attempt to fork organizations, user profiles, or non-issue URLs.
44
+ Haystack-Agent knows that forking is a prerequisite to contributing changes and creating pull requests.
45
+
46
+ Haystack-Agent takes notes after the fork:
47
+ <scratchpad>
48
+ - Record the URL of the forked repository
49
+ - Note the original issue being worked on
50
+ - Document any post-fork steps (e.g., git cloning, installing dependencies)
51
+ - Make note of any errors or special setup requirements
52
+ </scratchpad>
53
+ """
54
+
55
+ REPO_FORKER_SCHEMA = {
56
+ "properties": {
57
+ "url": {"type": "string", "description": "URL of the GitHub issue to work on in the fork."},
58
+ },
59
+ "required": ["url"],
60
+ "type": "object",
61
+ }
@@ -5,6 +5,7 @@ from .file_editor_tool import GitHubFileEditorTool
5
5
  from .issue_commenter_tool import GitHubIssueCommenterTool
6
6
  from .issue_viewer_tool import GitHubIssueViewerTool
7
7
  from .pr_creator_tool import GitHubPRCreatorTool
8
+ from .repo_forker_tool import GitHubRepoForkerTool
8
9
  from .repo_viewer_tool import GitHubRepoViewerTool
9
10
 
10
11
  __all__ = [
@@ -12,5 +13,6 @@ __all__ = [
12
13
  "GitHubIssueCommenterTool",
13
14
  "GitHubIssueViewerTool",
14
15
  "GitHubPRCreatorTool",
16
+ "GitHubRepoForkerTool",
15
17
  "GitHubRepoViewerTool",
16
18
  ]
@@ -0,0 +1,116 @@
1
+ # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ from typing import Any, Callable, Dict, Optional, Union
5
+
6
+ from haystack.core.serialization import generate_qualified_class_name
7
+ from haystack.tools import ComponentTool
8
+ from haystack.utils import Secret, deserialize_secrets_inplace
9
+
10
+ from haystack_integrations.components.connectors.github.repo_forker import GitHubRepoForker
11
+ from haystack_integrations.prompts.github.repo_forker_prompt import REPO_FORKER_PROMPT, REPO_FORKER_SCHEMA
12
+ from haystack_integrations.tools.github.utils import deserialize_handlers, serialize_handlers
13
+
14
+
15
+ class GitHubRepoForkerTool(ComponentTool):
16
+ """
17
+ A tool for forking Github repository.
18
+ """
19
+
20
+ def __init__(
21
+ self,
22
+ *,
23
+ name: Optional[str] = "repo_forker",
24
+ description: Optional[str] = REPO_FORKER_PROMPT,
25
+ parameters: Optional[Dict[str, Any]] = REPO_FORKER_SCHEMA,
26
+ github_token: Secret = Secret.from_env_var("GITHUB_TOKEN"),
27
+ raise_on_failure: bool = True,
28
+ outputs_to_string: Optional[Dict[str, Union[str, Callable[[Any], str]]]] = None,
29
+ inputs_from_state: Optional[Dict[str, str]] = None,
30
+ outputs_to_state: Optional[Dict[str, Dict[str, Union[str, Callable]]]] = None,
31
+ ):
32
+ """
33
+ Initialize the GitHub Repo Forker tool.
34
+
35
+ :param name: Optional name for the tool.
36
+ :param description: Optional description.
37
+ :param parameters: Optional JSON schema defining the parameters expected by the Tool.
38
+ :param github_token: GitHub personal access token for API authentication
39
+ :param raise_on_failure: If True, raises exceptions on API errors
40
+ :param outputs_to_string:
41
+ Optional dictionary defining how a tool outputs should be converted into a string.
42
+ If the source is provided only the specified output key is sent to the handler.
43
+ If the source is omitted the whole tool result is sent to the handler.
44
+ Example: {
45
+ "source": "docs", "handler": format_documents
46
+ }
47
+ :param inputs_from_state:
48
+ Optional dictionary mapping state keys to tool parameter names.
49
+ Example: {"repository": "repo"} maps state's "repository" to tool's "repo" parameter.
50
+ :param outputs_to_state:
51
+ Optional dictionary defining how tool outputs map to keys within state as well as optional handlers.
52
+ If the source is provided only the specified output key is sent to the handler.
53
+ Example: {
54
+ "documents": {"source": "docs", "handler": custom_handler}
55
+ }
56
+ If the source is omitted the whole tool result is sent to the handler.
57
+ Example: {
58
+ "documents": {"handler": custom_handler}
59
+ }
60
+ """
61
+ self.github_token = github_token
62
+ self.raise_on_failure = raise_on_failure
63
+ self.outputs_to_string = outputs_to_string
64
+ self.inputs_from_state = inputs_from_state
65
+ self.outputs_to_state = outputs_to_state
66
+
67
+ repo_forker = GitHubRepoForker(
68
+ github_token=github_token,
69
+ raise_on_failure=raise_on_failure,
70
+ )
71
+
72
+ super().__init__(
73
+ component=repo_forker,
74
+ name=name,
75
+ description=description,
76
+ parameters=parameters,
77
+ outputs_to_string=self.outputs_to_string,
78
+ inputs_from_state=self.inputs_from_state,
79
+ outputs_to_state=self.outputs_to_state,
80
+ )
81
+
82
+ def to_dict(self) -> Dict[str, Any]:
83
+ """
84
+ Serializes the tool to a dictionary.
85
+
86
+ Returns:
87
+ Dictionary with serialized data.
88
+ """
89
+ serialized = {
90
+ "name": self.name,
91
+ "description": self.description,
92
+ "parameters": self.parameters,
93
+ "github_token": self.github_token.to_dict() if self.github_token else None,
94
+ "raise_on_failure": self.raise_on_failure,
95
+ "outputs_to_string": self.outputs_to_string,
96
+ "inputs_from_state": self.inputs_from_state,
97
+ "outputs_to_state": self.outputs_to_state,
98
+ }
99
+
100
+ serialize_handlers(serialized, self.outputs_to_state, self.outputs_to_string)
101
+ return {"type": generate_qualified_class_name(type(self)), "data": serialized}
102
+
103
+ @classmethod
104
+ def from_dict(cls, data: Dict[str, Any]) -> "GitHubRepoForkerTool":
105
+ """
106
+ Deserializes the tool from a dictionary.
107
+
108
+ :param data:
109
+ Dictionary to deserialize from.
110
+ :returns:
111
+ Deserialized tool.
112
+ """
113
+ inner_data = data["data"]
114
+ deserialize_secrets_inplace(inner_data, keys=["github_token"])
115
+ deserialize_handlers(inner_data)
116
+ return cls(**inner_data)