github-agent 2.4.2__tar.gz → 2.4.4__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.
- {github_agent-2.4.2 → github_agent-2.4.4}/PKG-INFO +3 -4
- {github_agent-2.4.2 → github_agent-2.4.4}/README.md +1 -1
- github_agent-2.4.4/github_agent/__init__.py +1 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/github_gql.py +15 -34
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/github_http.py +11 -7
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp_server.py +1 -1
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent.egg-info/PKG-INFO +3 -4
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent.egg-info/requires.txt +1 -2
- {github_agent-2.4.2 → github_agent-2.4.4}/pyproject.toml +2 -2
- github_agent-2.4.4/tests/test_github_gql.py +73 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_github_http.py +65 -0
- github_agent-2.4.2/github_agent/__init__.py +0 -1
- github_agent-2.4.2/tests/test_github_gql.py +0 -55
- {github_agent-2.4.2 → github_agent-2.4.4}/LICENSE +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/__main__.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/__init__.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_base.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_branches.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_comments.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_commits.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_contents.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_dependabot.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_issues.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_orgs.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_pages.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_pulls.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_releases.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_repos.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_search.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api/api_client_workflows.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/api_client.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/auth.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/connectors/__init__.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/connectors/mcp_source_presets.json +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/connectors/tool_schema_fingerprints.json +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/github_input_models.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/github_response_models.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/kg_ingest.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/__init__.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_action.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_branch.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_collaborator.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_commit.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_content.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_dependabot.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_issue.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_org.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_pull.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_release.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_repo.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp/mcp_search.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/mcp_config.json +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/ontology/__init__.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/ontology/certification.json +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/ontology/fixtures/records.json +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/ontology/github.ttl +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/ontology/mappings/source.yaml +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/ontology/migrations/manifest.json +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/ontology/shapes/connector.shacl.ttl +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/prompts/__init__.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/__init__.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-actions-ci-review/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-actions-ci-review/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-agent-operations/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-agent-operations/agents/openai.yaml +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-agent-operations/references/catalog.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-backlog-planner/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-backlog-planner/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-backlog-planner/references/addressed-heuristics.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-backlog-planner/scripts/build_plan.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-ci-failure-sweep/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-ci-failure-sweep/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-ci-failure-sweep/references/actions-tool-cheatsheet.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-ci-failure-sweep/scripts/summarize_runs.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-dependabot-review/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-dependabot-review/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-issue-tracking/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-issue-tracking/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-org-remediation-loop/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-org-remediation-loop/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-org-remediation-loop/scripts/classify_fix_risk.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pr-review-sweep/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pr-review-sweep/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pr-review-sweep/references/pulls-tool-cheatsheet.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pr-review-sweep/scripts/summarize_prs.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-project-provisioner/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-project-provisioner/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-project-provisioner/scripts/enable_pages.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-create/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-create/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-review/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-review/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-repository-management/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-repository-management/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-tools/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-tools/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-tools/code-reviewer.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-tools/scripts/fetch_comments.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-tools/scripts/inspect_pr_checks.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-triage-resolver/SKILL.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-triage-resolver/WORKFLOW.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-triage-resolver/references/resolution-rules.md +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-triage-resolver/scripts/classify_safe.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-triage-resolver/scripts/gh_write.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent.egg-info/SOURCES.txt +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent.egg-info/dependency_links.txt +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent.egg-info/entry_points.txt +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/github_agent.egg-info/top_level.txt +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/scripts/security_sanitizer.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/scripts/verify_api_integration.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/setup.cfg +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/conftest.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_action_discovery.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_api_client_endpoints.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_api_validation.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_auth_client_edge_cases.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_comment_crud.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_fleet_name.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_github_agent_api_brute_force_coverage.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_github_agent_brute_force_coverage.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_hardening.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_init_dynamics.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_kg_ingest.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_mcp_coverage.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_mcp_package_dispatch.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_model_fields.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_org_crud.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_pages.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_repo_secrets_characterization.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_backlog_build_plan.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_ci_failure_sweep_summarize_runs.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_github_tools_fetch_comments.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_github_tools_inspect_pr_checks.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_org_remediation_classify_fix_risk.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_pr_review_sweep_summarize_prs.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_triage_resolver_classify_safe.py +0 -0
- {github_agent-2.4.2 → github_agent-2.4.4}/tests/test_startup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-agent
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.4
|
|
4
4
|
Summary: GitHub Agent for MCP
|
|
5
5
|
Author-email: Project Maintainers <maintainers@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,9 +12,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: gql[requests]>=4.4.0
|
|
16
15
|
Requires-Dist: requests>=2.34.2
|
|
17
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.3.
|
|
16
|
+
Requires-Dist: agent-connector-sdk[graphql,mcp]<1.0.0,>=0.3.13
|
|
18
17
|
Provides-Extra: mcp
|
|
19
18
|
Provides-Extra: all
|
|
20
19
|
Provides-Extra: test
|
|
@@ -45,7 +44,7 @@ Dynamic: license-file
|
|
|
45
44
|

|
|
46
45
|

|
|
47
46
|
|
|
48
|
-
*Version: 2.4.
|
|
47
|
+
*Version: 2.4.4*
|
|
49
48
|
|
|
50
49
|
> **Documentation** — Installation, deployment, and usage across the MCP, API, and
|
|
51
50
|
> [official documentation](https://knuckles-team.github.io/github-agent/).
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|

|
|
21
21
|

|
|
22
22
|
|
|
23
|
-
*Version: 2.4.
|
|
23
|
+
*Version: 2.4.4*
|
|
24
24
|
|
|
25
25
|
> **Documentation** — Installation, deployment, and usage across the MCP, API, and
|
|
26
26
|
> [official documentation](https://knuckles-team.github.io/github-agent/).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.4.4"
|
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
import logging
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from agent_connector_sdk.exceptions import MissingParameterError
|
|
7
|
+
from agent_connector_sdk.exceptions import MissingParameterError
|
|
8
8
|
from agent_connector_sdk.tls.profile import ResolvedTLSProfile
|
|
9
9
|
from agent_connector_sdk.tls.resolve import resolve_tls_profile
|
|
10
|
-
from
|
|
11
|
-
from gql.transport.requests import RequestsHTTPTransport
|
|
10
|
+
from agent_connector_sdk.transports.graphql import GraphQLAuth, GraphQLClient
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class GraphQL:
|
|
@@ -44,29 +43,21 @@ class GraphQL:
|
|
|
44
43
|
# GitHub GraphQL authenticates with a bearer token (classic PAT,
|
|
45
44
|
# fine-grained PAT, or OAuth/GitHub-App installation token).
|
|
46
45
|
self.headers = {"Authorization": f"Bearer {token}"}
|
|
47
|
-
self.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
self.client = Client(
|
|
53
|
-
transport=self.transport, fetch_schema_from_transport=False
|
|
46
|
+
self._gql = GraphQLClient(
|
|
47
|
+
self.url,
|
|
48
|
+
auth=GraphQLAuth.bearer(token),
|
|
49
|
+
tls_profile=self.tls_profile,
|
|
50
|
+
tls_service="github",
|
|
54
51
|
)
|
|
55
52
|
|
|
53
|
+
@property
|
|
54
|
+
def client(self) -> Any:
|
|
55
|
+
"""The underlying protocol client, built on first use."""
|
|
56
|
+
return self._gql.client
|
|
57
|
+
|
|
56
58
|
def close(self) -> None:
|
|
57
|
-
"""Release GraphQL transport state and runtime-only TLS material.
|
|
58
|
-
|
|
59
|
-
``Client.close_sync()`` unconditionally asserts ``self.session`` is a
|
|
60
|
-
``SyncClientSession`` — but under gql 4.0 that attribute is only ever
|
|
61
|
-
set by ``connect_sync()`` (called implicitly by ``execute_gql`` /
|
|
62
|
-
``client.execute``). If this ``GraphQL`` was constructed but never
|
|
63
|
-
used to run a query, the underlying ``Client`` has no ``session``
|
|
64
|
-
attribute yet and ``close_sync()`` raises ``AttributeError`` instead
|
|
65
|
-
of being a no-op. Only close a session that was actually opened.
|
|
66
|
-
"""
|
|
67
|
-
if hasattr(self.client, "session"):
|
|
68
|
-
self.client.close_sync()
|
|
69
|
-
self.tls_profile.cleanup()
|
|
59
|
+
"""Release GraphQL transport state and runtime-only TLS material."""
|
|
60
|
+
self._gql.close()
|
|
70
61
|
|
|
71
62
|
@staticmethod
|
|
72
63
|
def _graphql_endpoint(url: str) -> str:
|
|
@@ -91,17 +82,7 @@ class GraphQL:
|
|
|
91
82
|
Raises:
|
|
92
83
|
ParameterError: If the query fails or the response carries errors.
|
|
93
84
|
"""
|
|
94
|
-
|
|
95
|
-
query = gql(query_str)
|
|
96
|
-
result = self.client.execute(
|
|
97
|
-
query, variable_values=variables, operation_name=operation_name
|
|
98
|
-
)
|
|
99
|
-
if "errors" in result:
|
|
100
|
-
raise ParameterError(f"GraphQL errors: {result['errors']}")
|
|
101
|
-
return result
|
|
102
|
-
except Exception as e:
|
|
103
|
-
logging.error("GraphQL execution failed: error_type=%s", type(e).__name__)
|
|
104
|
-
raise ParameterError(f"Query execution failed: {type(e).__name__}") from e
|
|
85
|
+
return self._gql.execute(query_str, variables, operation_name)
|
|
105
86
|
|
|
106
87
|
def enable_pull_request_auto_merge(
|
|
107
88
|
self, pull_request_id: str, merge_method: str = "MERGE"
|
|
@@ -4,21 +4,23 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import http.client
|
|
6
6
|
import json
|
|
7
|
-
import os
|
|
8
7
|
import ssl
|
|
9
8
|
from typing import Any
|
|
10
9
|
|
|
10
|
+
from agent_connector_sdk.tls.errors import TransportSecurityError
|
|
11
|
+
from agent_connector_sdk.tls.profile import ResolvedTLSProfile
|
|
12
|
+
from agent_connector_sdk.tls.resolve import resolve_tls_profile
|
|
13
|
+
|
|
11
14
|
GITHUB_API_HOST = "api.github.com"
|
|
12
15
|
MAX_REQUEST_BYTES = 1 * 1024 * 1024
|
|
13
16
|
MAX_RESPONSE_BYTES = 8 * 1024 * 1024
|
|
14
17
|
|
|
15
18
|
|
|
16
|
-
def
|
|
17
|
-
|
|
18
|
-
capath = os.environ.get("SSL_CERT_DIR")
|
|
19
|
+
def _tls_profile() -> ResolvedTLSProfile:
|
|
20
|
+
"""Resolve the GitHub TLS profile from the SDK (SDK-CONNECTOR-CONTROL-R017)."""
|
|
19
21
|
try:
|
|
20
|
-
return
|
|
21
|
-
except
|
|
22
|
+
return resolve_tls_profile("github")
|
|
23
|
+
except TransportSecurityError:
|
|
22
24
|
raise RuntimeError("runtime TLS trust configuration is invalid") from None
|
|
23
25
|
|
|
24
26
|
|
|
@@ -103,11 +105,12 @@ def github_json_request(
|
|
|
103
105
|
_validate_token_shape(token)
|
|
104
106
|
body = _encode_request_body(payload)
|
|
105
107
|
headers = _request_headers(token)
|
|
108
|
+
profile = _tls_profile()
|
|
106
109
|
connection = http.client.HTTPSConnection(
|
|
107
110
|
GITHUB_API_HOST,
|
|
108
111
|
443,
|
|
109
112
|
timeout=30,
|
|
110
|
-
context=
|
|
113
|
+
context=profile.ssl_context,
|
|
111
114
|
)
|
|
112
115
|
try:
|
|
113
116
|
connection.request(method, path, body=body, headers=headers)
|
|
@@ -118,3 +121,4 @@ def github_json_request(
|
|
|
118
121
|
raise RuntimeError("GitHub service is unavailable") from None
|
|
119
122
|
finally:
|
|
120
123
|
connection.close()
|
|
124
|
+
profile.cleanup()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-agent
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.4
|
|
4
4
|
Summary: GitHub Agent for MCP
|
|
5
5
|
Author-email: Project Maintainers <maintainers@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,9 +12,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: gql[requests]>=4.4.0
|
|
16
15
|
Requires-Dist: requests>=2.34.2
|
|
17
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.3.
|
|
16
|
+
Requires-Dist: agent-connector-sdk[graphql,mcp]<1.0.0,>=0.3.13
|
|
18
17
|
Provides-Extra: mcp
|
|
19
18
|
Provides-Extra: all
|
|
20
19
|
Provides-Extra: test
|
|
@@ -45,7 +44,7 @@ Dynamic: license-file
|
|
|
45
44
|

|
|
46
45
|

|
|
47
46
|
|
|
48
|
-
*Version: 2.4.
|
|
47
|
+
*Version: 2.4.4*
|
|
49
48
|
|
|
50
49
|
> **Documentation** — Installation, deployment, and usage across the MCP, API, and
|
|
51
50
|
> [official documentation](https://knuckles-team.github.io/github-agent/).
|
|
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "github-agent"
|
|
7
|
-
version = "2.4.
|
|
7
|
+
version = "2.4.4"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
description = "GitHub Agent for MCP"
|
|
10
10
|
requires-python = ">=3.12"
|
|
11
11
|
classifiers = [ "Development Status :: 5 - Production/Stable", "License :: Public Domain", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
|
|
12
|
-
dependencies = [ "
|
|
12
|
+
dependencies = [ "requests>=2.34.2", "agent-connector-sdk[mcp,graphql]>=0.3.13,<1.0.0",]
|
|
13
13
|
[[project.authors]]
|
|
14
14
|
name = "Project Maintainers"
|
|
15
15
|
email = "maintainers@users.noreply.github.com"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""GitHub GraphQL client — endpoint derivation + construction (no network)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from agent_connector_sdk.exceptions import MissingParameterError
|
|
7
|
+
|
|
8
|
+
from github_agent.github_gql import GraphQL
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_endpoint_github_com():
|
|
12
|
+
assert GraphQL._graphql_endpoint("https://api.github.com") == (
|
|
13
|
+
"https://api.github.com/graphql"
|
|
14
|
+
)
|
|
15
|
+
assert GraphQL._graphql_endpoint("https://api.github.com/") == (
|
|
16
|
+
"https://api.github.com/graphql"
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_endpoint_enterprise():
|
|
21
|
+
assert GraphQL._graphql_endpoint("https://github.example/api/v3") == (
|
|
22
|
+
"https://github.example/api/graphql"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_requires_url_and_token():
|
|
27
|
+
with pytest.raises(MissingParameterError):
|
|
28
|
+
GraphQL(url=None, token="x")
|
|
29
|
+
with pytest.raises(MissingParameterError):
|
|
30
|
+
GraphQL(url="https://api.github.com", token=None)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_construction_sets_bearer_header():
|
|
34
|
+
g = GraphQL(url="https://api.github.com", token="tok123")
|
|
35
|
+
assert g.headers["Authorization"] == "Bearer tok123"
|
|
36
|
+
assert g.url.endswith("/graphql")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_close_without_session_does_not_raise():
|
|
40
|
+
"""close() on a never-used client is a safe no-op."""
|
|
41
|
+
GraphQL(url="https://api.github.com", token="tok123").close()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@pytest.mark.spec("CONN-GITHUB-AGENT-CONNECTOR-IDENTITY-R002")
|
|
45
|
+
def test_wrapper_delegates_to_shared_graphql_client():
|
|
46
|
+
from unittest.mock import patch
|
|
47
|
+
|
|
48
|
+
from agent_connector_sdk.tls.resolve import resolve_tls_profile
|
|
49
|
+
from agent_connector_sdk.transports.graphql import GraphQLClient
|
|
50
|
+
|
|
51
|
+
profile = resolve_tls_profile("github")
|
|
52
|
+
g = GraphQL(url="https://github.example/api/v3", token="tok123", tls_profile=profile)
|
|
53
|
+
assert isinstance(g._gql, GraphQLClient)
|
|
54
|
+
assert g._gql.endpoint == "https://github.example/api/graphql"
|
|
55
|
+
assert g._gql.headers["Authorization"] == "Bearer tok123"
|
|
56
|
+
assert g._gql.tls_profile is profile
|
|
57
|
+
with patch.object(GraphQLClient, "execute", return_value={"viewer": {}}) as ex:
|
|
58
|
+
assert g.execute_gql("query { viewer { login } }", {"a": 1}, "Op") == {
|
|
59
|
+
"viewer": {}
|
|
60
|
+
}
|
|
61
|
+
ex.assert_called_once_with("query { viewer { login } }", {"a": 1}, "Op")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_execute_failure_message_is_redacted_class_name():
|
|
65
|
+
from unittest.mock import patch
|
|
66
|
+
|
|
67
|
+
from agent_connector_sdk.exceptions import ParameterError
|
|
68
|
+
from agent_connector_sdk.transports.graphql import GraphQLClient
|
|
69
|
+
|
|
70
|
+
g = GraphQL(url="https://api.github.com", token="tok123")
|
|
71
|
+
with patch.object(GraphQLClient, "_attempt", side_effect=ValueError("boom")):
|
|
72
|
+
with pytest.raises(ParameterError, match="Query execution failed: ValueError"):
|
|
73
|
+
g.execute_gql("query { viewer { login } }")
|
|
@@ -163,3 +163,68 @@ def test_github_json_request_encodes_payload_as_compact_json():
|
|
|
163
163
|
assert value == {"created": True}
|
|
164
164
|
sent_kwargs = connection.request.call_args.kwargs
|
|
165
165
|
assert sent_kwargs["body"] == json.dumps({"title": "hi"}, separators=(",", ":")).encode()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@pytest.mark.spec("CONN-GITHUB-AGENT-TRANSPORT-TLS-R001")
|
|
169
|
+
def test_request_uses_sdk_tls_profile_context():
|
|
170
|
+
"""CONN-GITHUB-AGENT-TRANSPORT-TLS-R001: the connection uses the profile's context."""
|
|
171
|
+
connection, _ = _mock_connection()
|
|
172
|
+
profile = MagicMock()
|
|
173
|
+
with (
|
|
174
|
+
patch("github_agent.github_http.resolve_tls_profile", return_value=profile) as resolve,
|
|
175
|
+
patch("github_agent.github_http.http.client.HTTPSConnection", return_value=connection) as conn_cls,
|
|
176
|
+
):
|
|
177
|
+
github_json_request("GET", "/repos/x/y", "tok")
|
|
178
|
+
resolve.assert_called_once_with("github")
|
|
179
|
+
assert conn_cls.call_args.kwargs["context"] is profile.ssl_context
|
|
180
|
+
profile.cleanup.assert_called_once()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@pytest.mark.spec("CONN-GITHUB-AGENT-TRANSPORT-TLS-R001")
|
|
184
|
+
def test_private_ca_is_carried_through_the_profile(tmp_path, monkeypatch):
|
|
185
|
+
"""CONN-GITHUB-AGENT-TRANSPORT-TLS-R001: a configured CA bundle reaches the profile."""
|
|
186
|
+
from cryptography import x509
|
|
187
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
|
188
|
+
from cryptography.hazmat.primitives.asymmetric import ec
|
|
189
|
+
import datetime
|
|
190
|
+
|
|
191
|
+
from github_agent.github_http import _tls_profile
|
|
192
|
+
|
|
193
|
+
key = ec.generate_private_key(ec.SECP256R1())
|
|
194
|
+
name = x509.Name([x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, "test-ca")])
|
|
195
|
+
now = datetime.datetime.now(datetime.timezone.utc)
|
|
196
|
+
cert = (
|
|
197
|
+
x509.CertificateBuilder()
|
|
198
|
+
.subject_name(name)
|
|
199
|
+
.issuer_name(name)
|
|
200
|
+
.public_key(key.public_key())
|
|
201
|
+
.serial_number(1)
|
|
202
|
+
.not_valid_before(now)
|
|
203
|
+
.not_valid_after(now + datetime.timedelta(days=1))
|
|
204
|
+
.add_extension(x509.BasicConstraints(ca=True, path_length=None), critical=True)
|
|
205
|
+
.sign(key, hashes.SHA256())
|
|
206
|
+
)
|
|
207
|
+
ca = tmp_path / "ca.pem"
|
|
208
|
+
ca.write_bytes(cert.public_bytes(serialization.Encoding.PEM))
|
|
209
|
+
monkeypatch.setenv("GITHUB_CA_BUNDLE", str(ca))
|
|
210
|
+
profile = _tls_profile()
|
|
211
|
+
try:
|
|
212
|
+
assert profile.ca_bundle_path == ca
|
|
213
|
+
assert profile.verify_enabled
|
|
214
|
+
finally:
|
|
215
|
+
profile.cleanup()
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
@pytest.mark.spec("CONN-GITHUB-AGENT-TRANSPORT-TLS-R001")
|
|
219
|
+
def test_no_hand_built_ssl_context_remains():
|
|
220
|
+
"""CONN-GITHUB-AGENT-TRANSPORT-TLS-R001: no package code builds its own context."""
|
|
221
|
+
from pathlib import Path
|
|
222
|
+
|
|
223
|
+
import github_agent
|
|
224
|
+
|
|
225
|
+
root = Path(github_agent.__file__).parent
|
|
226
|
+
for path in root.rglob("*.py"):
|
|
227
|
+
text = path.read_text(encoding="utf-8")
|
|
228
|
+
assert "create_default_context" not in text, path
|
|
229
|
+
assert "verify=False" not in text, path
|
|
230
|
+
assert "disable_warnings" not in text, path
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.4.2"
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"""GitHub GraphQL client — endpoint derivation + construction (no network)."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import pytest
|
|
6
|
-
from agent_connector_sdk.exceptions import MissingParameterError
|
|
7
|
-
|
|
8
|
-
from github_agent.github_gql import GraphQL
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def test_endpoint_github_com():
|
|
12
|
-
assert GraphQL._graphql_endpoint("https://api.github.com") == (
|
|
13
|
-
"https://api.github.com/graphql"
|
|
14
|
-
)
|
|
15
|
-
assert GraphQL._graphql_endpoint("https://api.github.com/") == (
|
|
16
|
-
"https://api.github.com/graphql"
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def test_endpoint_enterprise():
|
|
21
|
-
assert GraphQL._graphql_endpoint("https://github.example/api/v3") == (
|
|
22
|
-
"https://github.example/api/graphql"
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def test_requires_url_and_token():
|
|
27
|
-
with pytest.raises(MissingParameterError):
|
|
28
|
-
GraphQL(url=None, token="x")
|
|
29
|
-
with pytest.raises(MissingParameterError):
|
|
30
|
-
GraphQL(url="https://api.github.com", token=None)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def test_construction_sets_bearer_header():
|
|
34
|
-
g = GraphQL(url="https://api.github.com", token="tok123")
|
|
35
|
-
assert g.headers["Authorization"] == "Bearer tok123"
|
|
36
|
-
assert g.url.endswith("/graphql")
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def test_close_without_session_does_not_raise():
|
|
40
|
-
"""Regression guard: under gql 4.0, Client.close_sync() unconditionally
|
|
41
|
-
asserts ``self.session`` — an attribute only ever set by connect_sync()
|
|
42
|
-
(called implicitly the first time a query executes). A GraphQL client
|
|
43
|
-
that was constructed but never used to run a query has no such session
|
|
44
|
-
yet, so close() must be a safe no-op rather than raising AttributeError.
|
|
45
|
-
"""
|
|
46
|
-
g = GraphQL(url="https://api.github.com", token="tok123")
|
|
47
|
-
g.close()
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_close_after_session_opened_closes_cleanly():
|
|
51
|
-
"""Once a sync session has actually been opened, close() still closes it."""
|
|
52
|
-
g = GraphQL(url="https://api.github.com", token="tok123")
|
|
53
|
-
g.client.connect_sync()
|
|
54
|
-
assert hasattr(g.client, "session")
|
|
55
|
-
g.close()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/connectors/tool_schema_fingerprints.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-actions-ci-review/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-actions-ci-review/WORKFLOW.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-agent-operations/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-backlog-planner/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-backlog-planner/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-ci-failure-sweep/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-ci-failure-sweep/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-dependabot-review/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-dependabot-review/WORKFLOW.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-issue-tracking/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-issue-tracking/WORKFLOW.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-org-remediation-loop/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pr-review-sweep/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pr-review-sweep/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-project-provisioner/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-project-provisioner/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-create/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-create/WORKFLOW.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-review/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-pull-request-review/WORKFLOW.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-repository-management/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-tools/scripts/fetch_comments.py
RENAMED
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-triage-resolver/SKILL.md
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/github_agent/skills/github-triage-resolver/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/tests/test_github_agent_api_brute_force_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_ci_failure_sweep_summarize_runs.py
RENAMED
|
File without changes
|
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_github_tools_inspect_pr_checks.py
RENAMED
|
File without changes
|
{github_agent-2.4.2 → github_agent-2.4.4}/tests/test_skill_org_remediation_classify_fix_risk.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|