github-agent 2.4.5__py3-none-any.whl → 2.4.7__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.
- github_agent/__init__.py +1 -1
- github_agent/mcp_server.py +1 -1
- github_agent/ontology/github.ttl +3 -0
- github_agent/ontology/ingest_sources.json +24 -0
- {github_agent-2.4.5.dist-info → github_agent-2.4.7.dist-info}/METADATA +2 -2
- {github_agent-2.4.5.dist-info → github_agent-2.4.7.dist-info}/RECORD +12 -9
- tests/test_ingest_sources.py +34 -0
- tests/test_ontology_parent_link.py +114 -0
- {github_agent-2.4.5.dist-info → github_agent-2.4.7.dist-info}/WHEEL +0 -0
- {github_agent-2.4.5.dist-info → github_agent-2.4.7.dist-info}/entry_points.txt +0 -0
- {github_agent-2.4.5.dist-info → github_agent-2.4.7.dist-info}/licenses/LICENSE +0 -0
- {github_agent-2.4.5.dist-info → github_agent-2.4.7.dist-info}/top_level.txt +0 -0
github_agent/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "2.4.
|
|
1
|
+
__version__ = "2.4.7"
|
github_agent/mcp_server.py
CHANGED
github_agent/ontology/github.ttl
CHANGED
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
rdfs:comment "A GitHub organization that owns repositories and members (github_orgs)." .
|
|
19
19
|
|
|
20
20
|
:Repository a owl:Class ;
|
|
21
|
+
rdfs:subClassOf :SoftwareProject ;
|
|
21
22
|
rdfs:label "Repository" ;
|
|
22
23
|
rdfs:comment "A GitHub repository / codebase (github_repos)." .
|
|
23
24
|
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
rdfs:comment "A proposed change under review, from a head to a base branch (github_pulls)." .
|
|
27
28
|
|
|
28
29
|
:Issue a owl:Class ;
|
|
30
|
+
rdfs:subClassOf :WorkItem ;
|
|
29
31
|
rdfs:label "Issue" ;
|
|
30
32
|
rdfs:comment "A tracked work item, bug, or discussion in a repository (github_issues)." .
|
|
31
33
|
|
|
@@ -46,6 +48,7 @@
|
|
|
46
48
|
rdfs:comment "A GitHub Actions CI/CD workflow definition (github_actions)." .
|
|
47
49
|
|
|
48
50
|
:WorkflowRun a owl:Class ;
|
|
51
|
+
rdfs:subClassOf :PipelineRun ;
|
|
49
52
|
rdfs:label "Workflow Run" ;
|
|
50
53
|
rdfs:comment "A single execution of a GitHub Actions workflow for a ref/commit (github_actions)." .
|
|
51
54
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"connector": "github-mcp",
|
|
3
|
+
"sources": [
|
|
4
|
+
{
|
|
5
|
+
"source_id": "issues",
|
|
6
|
+
"record_type": "Issue",
|
|
7
|
+
"tools": [
|
|
8
|
+
"github_search_issues"
|
|
9
|
+
],
|
|
10
|
+
"records_path": "data.items",
|
|
11
|
+
"id_field": "id",
|
|
12
|
+
"title_field": "title",
|
|
13
|
+
"text_field": "body",
|
|
14
|
+
"cursor_field": "updated_at",
|
|
15
|
+
"incremental": false,
|
|
16
|
+
"arguments": {
|
|
17
|
+
"q": "is:issue is:open involves:@me",
|
|
18
|
+
"per_page": 50,
|
|
19
|
+
"max_pages": 1
|
|
20
|
+
},
|
|
21
|
+
"description": "Open GitHub issues involving the authenticated user (first 50)."
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-agent
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.7
|
|
4
4
|
Summary: GitHub Agent for MCP
|
|
5
5
|
Author-email: Project Maintainers <maintainers@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -44,7 +44,7 @@ Dynamic: license-file
|
|
|
44
44
|

|
|
45
45
|

|
|
46
46
|
|
|
47
|
-
*Version: 2.4.
|
|
47
|
+
*Version: 2.4.7*
|
|
48
48
|
|
|
49
49
|
> **Documentation** — Installation, deployment, and usage across the MCP, API, and
|
|
50
50
|
> [official documentation](https://knuckles-team.github.io/github-agent/).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
github_agent/__init__.py,sha256=
|
|
1
|
+
github_agent/__init__.py,sha256=6Ls7f3ZJxdJNWxciT1KkTqmIR_gddzXVDXxBtiav_WI,22
|
|
2
2
|
github_agent/__main__.py,sha256=O4Xg__fMvKfUsA6m61pLV56jlYY6EORiLhgDLlp0vJ8,92
|
|
3
3
|
github_agent/api_client.py,sha256=O69YfkXBKyVd59EC8szaMlw3_ZxwEEvsLSvhWlfYnvk,1581
|
|
4
4
|
github_agent/auth.py,sha256=isNd6DYbl_syB_wIbC399d_-157jqH1jqJfDmBn8h-0,4671
|
|
@@ -8,7 +8,7 @@ github_agent/github_input_models.py,sha256=yqqPGHb206th736MZvbnxq9F1JRsBUBODNeNV
|
|
|
8
8
|
github_agent/github_response_models.py,sha256=mllSt0frBgzklUtfuHywJ2Ald3m99So948Xikt3H2Tc,8859
|
|
9
9
|
github_agent/kg_ingest.py,sha256=iH_NKpd8a6GtNxfZTp8Oah8VZkcXjI74KDf8P9NbtjA,17978
|
|
10
10
|
github_agent/mcp_config.json,sha256=2OOXrwO1sDLyHQqpZwhvDHizPIe3by6YmK4KFE333gI,23
|
|
11
|
-
github_agent/mcp_server.py,sha256=
|
|
11
|
+
github_agent/mcp_server.py,sha256=6Pd--MgYMT6g8nvzOpcXNToNHZr0SPdY6dfeCydkmf0,126620
|
|
12
12
|
github_agent/api/__init__.py,sha256=ntaEPqk-dsAV3HyyDLc2hYpc9nTTyG5CKI-SVDDjc24,27
|
|
13
13
|
github_agent/api/api_client_base.py,sha256=tMXKrZIXg6aQ6OK4kNKBDcNc8BrM0Vml_66SwA5ZgEw,7485
|
|
14
14
|
github_agent/api/api_client_branches.py,sha256=bCmqGUWQ27GFTGxcFkQ7D-ZEltKp6APVsk_Fw9wzdjY,3940
|
|
@@ -42,7 +42,8 @@ github_agent/mcp/mcp_repo.py,sha256=ny5GdawCFZxlbjpOc3ttnn-NIs9QDQLAxRdAWEWLUdc,
|
|
|
42
42
|
github_agent/mcp/mcp_search.py,sha256=3ZBGNKkVu5oBXgN9MBWd-ve4NDCzcwP9sY22bp4hqKs,2963
|
|
43
43
|
github_agent/ontology/__init__.py,sha256=-qc7ZPSgdaCLrD1AH_7TFXWikEpSH9rVmBciCC9gtCY,552
|
|
44
44
|
github_agent/ontology/certification.json,sha256=nUT_C-AtTjtb4bDAs3cDT2vlk7kK_8RPFfbyIWXCMw0,1664
|
|
45
|
-
github_agent/ontology/github.ttl,sha256=
|
|
45
|
+
github_agent/ontology/github.ttl,sha256=U2jeFMGCqhsyu9G4AzTXaw1xmSWrqLlbSXTWduWxccw,9260
|
|
46
|
+
github_agent/ontology/ingest_sources.json,sha256=70glHq2q8MEQCxD22r2VPyz_7mubibf1iygCf-sSdMs,572
|
|
46
47
|
github_agent/ontology/fixtures/records.json,sha256=EvW1Swrph3DyefmeE2eI0GM0AEKp1v9LrAwiqIbS3Hs,543
|
|
47
48
|
github_agent/ontology/mappings/source.yaml,sha256=f_ejdVD4JaYf5tD5UpIG9O_icnQx4yuKuVo5oyvc7UM,533
|
|
48
49
|
github_agent/ontology/migrations/manifest.json,sha256=rfFgIlAt0DHdMDpSq656Bnfs4RNeHgXCHbokya5Rk1w,118
|
|
@@ -92,7 +93,7 @@ github_agent/skills/github-triage-resolver/WORKFLOW.md,sha256=orvcRmaV-qb_JKoGSw
|
|
|
92
93
|
github_agent/skills/github-triage-resolver/references/resolution-rules.md,sha256=lGPvfLCSHpNIeh2rKWcH2k_2lla3ovgBxzwvtMmyQ-0,4133
|
|
93
94
|
github_agent/skills/github-triage-resolver/scripts/classify_safe.py,sha256=8BhcDF9Q8rjJIEVOmdyO-dO-eHBjW7T-bzaYC16uY5I,9556
|
|
94
95
|
github_agent/skills/github-triage-resolver/scripts/gh_write.py,sha256=SL5oA1A3lFRLepNri4CzEcuEsg9D5WKJ1000fCRKBEM,4125
|
|
95
|
-
github_agent-2.4.
|
|
96
|
+
github_agent-2.4.7.dist-info/licenses/LICENSE,sha256=5ALbh4fIALWVsUhO7q1nFT1bQb-CL9sWKf7p3GgLEG8,1070
|
|
96
97
|
scripts/security_sanitizer.py,sha256=gE65xtYMGx43oYUnK0kozBm73Hx97mCdrQUM7GGzIbk,9449
|
|
97
98
|
scripts/verify_api_integration.py,sha256=3AK8HKW52o1yxCDaEUtXngnh7CjYw6NiG9Eb3EIoXNE,10256
|
|
98
99
|
tests/conftest.py,sha256=kgpOLUp_q8IZaI6Xd7F1tbFuio81-_l5Gd4jaGiMrnY,3636
|
|
@@ -108,11 +109,13 @@ tests/test_github_agent_brute_force_coverage.py,sha256=Z_voXtChOYRqaNEmNzMfzvwQM
|
|
|
108
109
|
tests/test_github_gql.py,sha256=M55X5V2orZ1kVek16s1zaMJIUb6FhlfbC8k0cKkD07Y,2709
|
|
109
110
|
tests/test_github_http.py,sha256=uuSMrot71Kj8WQf-QyazO4rWzpWSucRTQ1tt5wRvC_E,9563
|
|
110
111
|
tests/test_hardening.py,sha256=sdlKmtk7B5yncc-r1LuFgoJfro6wNlCqY0xI73IVC4M,3710
|
|
112
|
+
tests/test_ingest_sources.py,sha256=hzY7vDW5Q1P-Qc_X6PAFAnXik_0BIP1DrNLVPhe_9DQ,1391
|
|
111
113
|
tests/test_init_dynamics.py,sha256=fPE_4M-bONKiqvtWLn12A0q18CUlzQhdx1UoXYkbbPk,1839
|
|
112
114
|
tests/test_kg_ingest.py,sha256=TeHjWz74LiuSxpI7N6HHrdj0H1mRsJHceQDNYvre4To,9462
|
|
113
115
|
tests/test_mcp_coverage.py,sha256=W_7fbCWoFd4mDwKvah2DmQRcy0fD7tI4ykFTne69tNM,43550
|
|
114
116
|
tests/test_mcp_package_dispatch.py,sha256=mzrC-jGl3DlrQx9z5uIxy1m0x9qsxfMo6eJImx844WY,22993
|
|
115
117
|
tests/test_model_fields.py,sha256=GvVFFedjdL0KBl328-NZ0SM6olv7muiglsMh0Vd59As,3388
|
|
118
|
+
tests/test_ontology_parent_link.py,sha256=gMdFdrsjYVnKii3f93hBufvfMES4we3ffH1xsH2Rnok,4352
|
|
116
119
|
tests/test_org_crud.py,sha256=7WMb8eCWSsl_rCILBmsJ4OFnmwtb_GXmebf51O8xsxI,19938
|
|
117
120
|
tests/test_pages.py,sha256=CGlxgPVrhvPnnXuFZwzF4VqsV4ygBDY8w8Cqr6KqJmI,18726
|
|
118
121
|
tests/test_repo_secrets_characterization.py,sha256=-9NkJlROsKIYKcNEZpVYy7tkJg-lB0_8We1RvOW1EaY,6043
|
|
@@ -124,8 +127,8 @@ tests/test_skill_org_remediation_classify_fix_risk.py,sha256=0Y8289lhxtJ3pxYUHzO
|
|
|
124
127
|
tests/test_skill_pr_review_sweep_summarize_prs.py,sha256=NrNaucQvM7K-k1WBcOBKtTGjxJbW16VgTHbC7dSsjm4,3821
|
|
125
128
|
tests/test_skill_triage_resolver_classify_safe.py,sha256=B-aDeVmsKTsxYO8TwMEx-cmpVSmZdlKXw5993Da2ubc,9489
|
|
126
129
|
tests/test_startup.py,sha256=Ix_g69k0tsZbY0-Vkeh8ADWojUdbYwTwwmnM4_hVuCc,1245
|
|
127
|
-
github_agent-2.4.
|
|
128
|
-
github_agent-2.4.
|
|
129
|
-
github_agent-2.4.
|
|
130
|
-
github_agent-2.4.
|
|
131
|
-
github_agent-2.4.
|
|
130
|
+
github_agent-2.4.7.dist-info/METADATA,sha256=q_4bTKAdIUsfu9TcD7RDkkKSLb8cnvhoyRryLf-VhmI,34508
|
|
131
|
+
github_agent-2.4.7.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
132
|
+
github_agent-2.4.7.dist-info/entry_points.txt,sha256=Wi6GhziOqmJl-22qTYkjfVuIHEHKRrBvyyloc7NqV80,367
|
|
133
|
+
github_agent-2.4.7.dist-info/top_level.txt,sha256=53Ecr8n7o_EMIqZClc11PBU07uQIggYZOk5WnvBbeOQ,50
|
|
134
|
+
github_agent-2.4.7.dist-info/RECORD,,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""The packaged ingestible-source declaration (CONN-GITHUB-AGENT-CONNECTOR-CONTENT-R003)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
import yaml
|
|
9
|
+
from agent_connector_sdk.ingest.sources import load_ingest_sources
|
|
10
|
+
from agent_connector_sdk.mcp.method_tools import operation_annotations, operation_verb
|
|
11
|
+
from agent_connector_sdk.mcp.tool_surface import operation_prefix
|
|
12
|
+
|
|
13
|
+
import github_agent
|
|
14
|
+
from github_agent.api_client import Api
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.mark.spec("CONN-GITHUB-AGENT-CONNECTOR-CONTENT-R003")
|
|
18
|
+
def test_declares_ingestible_sources() -> None:
|
|
19
|
+
package_root = Path(github_agent.__file__).parent
|
|
20
|
+
declaration = load_ingest_sources(package_root)
|
|
21
|
+
assert declaration is not None
|
|
22
|
+
assert declaration.connector == "github-mcp"
|
|
23
|
+
source = declaration.source("issues")
|
|
24
|
+
assert source is not None and source.record_type == "Issue"
|
|
25
|
+
prefix = operation_prefix("github-agent")
|
|
26
|
+
assert source.tools == (f"{prefix}_search_issues",)
|
|
27
|
+
# The engine admits a record only under the pack mapping of its type.
|
|
28
|
+
manifest = yaml.safe_load(
|
|
29
|
+
(package_root.parent / "connector_manifest.yml").read_text("utf-8")
|
|
30
|
+
)
|
|
31
|
+
assert source.record_type in manifest["schema_mappings"]
|
|
32
|
+
method = getattr(Api, "search_issues")
|
|
33
|
+
annotations = operation_annotations("search_issues", operation_verb(method))
|
|
34
|
+
assert annotations.read_only_hint is True
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Every class of the packaged ontology reaches an epistemic-graph parent class (CONN-GITHUB-AGENT-CONNECTOR-CONTENT-R002)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
pytestmark = pytest.mark.spec("CONN-GITHUB-AGENT-CONNECTOR-CONTENT-R002")
|
|
11
|
+
|
|
12
|
+
PARENT_IRI = "http://knuckles.team/kg"
|
|
13
|
+
ONTOLOGIES = sorted(
|
|
14
|
+
(Path(__file__).resolve().parents[1] / "github_agent" / "ontology").glob("*.ttl")
|
|
15
|
+
)
|
|
16
|
+
OWL = "http://www.w3.org/2002/07/owl#"
|
|
17
|
+
RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
|
|
18
|
+
SUBCLASS = "http://www.w3.org/2000/01/rdf-schema#subClassOf"
|
|
19
|
+
# Parent classes of the epistemic-graph ontology that this connector links to or redeclares.
|
|
20
|
+
PARENT_CLASSES = frozenset(
|
|
21
|
+
(
|
|
22
|
+
"http://knuckles.team/kg#Commit",
|
|
23
|
+
"http://knuckles.team/kg#Document",
|
|
24
|
+
"http://knuckles.team/kg#Organization",
|
|
25
|
+
"http://knuckles.team/kg#Person",
|
|
26
|
+
"http://knuckles.team/kg#PipelineRun",
|
|
27
|
+
"http://knuckles.team/kg#PullRequest",
|
|
28
|
+
"http://knuckles.team/kg#SoftwareProject",
|
|
29
|
+
"http://knuckles.team/kg#WorkItem",
|
|
30
|
+
"http://knuckles.team/kg#Workflow",
|
|
31
|
+
)
|
|
32
|
+
)
|
|
33
|
+
# Classes for which the parent ontology has no fitting class yet. Each is a candidate for a new
|
|
34
|
+
# parent class (see the orphan mapping report); a class leaves this set when it gains a parent.
|
|
35
|
+
PENDING_NEW_PARENT: frozenset[str] = frozenset(
|
|
36
|
+
(
|
|
37
|
+
"http://knuckles.team/kg#Branch",
|
|
38
|
+
"http://knuckles.team/kg#CheckRun",
|
|
39
|
+
"http://knuckles.team/kg#Release",
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
_STRING = re.compile(r'"""(?:.|\n)*?"""|"(?:[^"\\\n]|\\.)*"')
|
|
44
|
+
_IRI = re.compile(r"<([^<>\s]*)>")
|
|
45
|
+
_PREFIX = re.compile(r"(?im)^\s*@?prefix\s+([A-Za-z][\w.-]*)?:\s+\x00(\d+)\s*\.?")
|
|
46
|
+
_END = re.compile(r"\s\.(?=\s|$)|(?<=[\]>)\w\"'])\.(?=\s|$)")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _triples(text: str) -> list[tuple[str, str, str]]:
|
|
50
|
+
"""Subject, predicate and object of a Turtle file; names are expanded, literals dropped."""
|
|
51
|
+
iris: list[str] = []
|
|
52
|
+
|
|
53
|
+
def keep(match: re.Match[str]) -> str:
|
|
54
|
+
iris.append(match.group(1))
|
|
55
|
+
return f" \x00{len(iris)} "
|
|
56
|
+
|
|
57
|
+
body = re.sub(r"(?m)#[^\n]*$", "", _IRI.sub(keep, _STRING.sub(' "" ', text)))
|
|
58
|
+
prefixes = {
|
|
59
|
+
m.group(1) or "": iris[int(m.group(2)) - 1] for m in _PREFIX.finditer(body)
|
|
60
|
+
}
|
|
61
|
+
body = re.sub(r"\[[^\[\]]*\]", " _:b ", _PREFIX.sub("", body))
|
|
62
|
+
|
|
63
|
+
def expand(token: str) -> str:
|
|
64
|
+
if token.startswith("\x00"):
|
|
65
|
+
return iris[int(token[1:]) - 1]
|
|
66
|
+
prefix, sep, local = token.partition(":")
|
|
67
|
+
return (
|
|
68
|
+
prefixes[prefix] + local
|
|
69
|
+
if sep and prefix in prefixes
|
|
70
|
+
else RDF_TYPE
|
|
71
|
+
if token == "a"
|
|
72
|
+
else token
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
triples: list[tuple[str, str, str]] = []
|
|
76
|
+
for statement in _END.split(body):
|
|
77
|
+
tokens = statement.replace(";", " ; ").replace(",", " , ").split()
|
|
78
|
+
subject, predicate, fresh = "", "", True
|
|
79
|
+
for index, token in enumerate(tokens):
|
|
80
|
+
if index == 0:
|
|
81
|
+
subject = expand(token)
|
|
82
|
+
elif token == ";":
|
|
83
|
+
fresh = True
|
|
84
|
+
elif token != ",":
|
|
85
|
+
if fresh:
|
|
86
|
+
predicate, fresh = expand(token), False
|
|
87
|
+
else:
|
|
88
|
+
triples.append((subject, predicate, expand(token)))
|
|
89
|
+
return triples
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _orphans(triples: list[tuple[str, str, str]]) -> set[str]:
|
|
93
|
+
declared = {s for s, p, o in triples if p == RDF_TYPE and o == OWL + "Class"}
|
|
94
|
+
linked: set[str] = set()
|
|
95
|
+
changed = True
|
|
96
|
+
while changed:
|
|
97
|
+
changed = False
|
|
98
|
+
for cls in declared - linked - PARENT_CLASSES:
|
|
99
|
+
ups = {o for s, p, o in triples if s == cls and p == SUBCLASS}
|
|
100
|
+
if ups & (PARENT_CLASSES | linked):
|
|
101
|
+
linked.add(cls)
|
|
102
|
+
changed = True
|
|
103
|
+
return declared - linked - PARENT_CLASSES
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@pytest.mark.parametrize("path", ONTOLOGIES, ids=lambda p: p.name)
|
|
107
|
+
def test_ontology_joins_the_parent_graph(path: Path) -> None:
|
|
108
|
+
triples = _triples(path.read_text(encoding="utf-8"))
|
|
109
|
+
declared = {s for s, p, o in triples if p == RDF_TYPE and o == OWL + "Class"}
|
|
110
|
+
if not declared:
|
|
111
|
+
pytest.skip("declares no classes")
|
|
112
|
+
imports = {o for s, p, o in triples if p == OWL + "imports"}
|
|
113
|
+
assert any(i == PARENT_IRI or i.startswith(PARENT_IRI + "/") for i in imports)
|
|
114
|
+
assert _orphans(triples) == PENDING_NEW_PARENT & declared
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|