agent-capmap 0.1.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.
- agent_capmap-0.1.0.dist-info/METADATA +295 -0
- agent_capmap-0.1.0.dist-info/RECORD +48 -0
- agent_capmap-0.1.0.dist-info/WHEEL +4 -0
- agent_capmap-0.1.0.dist-info/entry_points.txt +2 -0
- agent_capmap-0.1.0.dist-info/licenses/LICENSE +21 -0
- agentcapmap/__init__.py +3 -0
- agentcapmap/__main__.py +5 -0
- agentcapmap/baseline.py +125 -0
- agentcapmap/classify/__init__.py +221 -0
- agentcapmap/classify/cache.py +74 -0
- agentcapmap/classify/prompt.py +160 -0
- agentcapmap/classify/provider.py +122 -0
- agentcapmap/classify/reference.py +115 -0
- agentcapmap/classify/reference_labels.json +6135 -0
- agentcapmap/cli.py +392 -0
- agentcapmap/diff.py +103 -0
- agentcapmap/discovery/__init__.py +209 -0
- agentcapmap/discovery/_common.py +297 -0
- agentcapmap/discovery/claude_code.py +258 -0
- agentcapmap/discovery/claude_desktop.py +28 -0
- agentcapmap/discovery/cursor.py +33 -0
- agentcapmap/discovery/mcp_json.py +29 -0
- agentcapmap/discovery/vscode.py +65 -0
- agentcapmap/enumerate/__init__.py +278 -0
- agentcapmap/enumerate/hashing.py +37 -0
- agentcapmap/enumerate/http.py +313 -0
- agentcapmap/enumerate/netguard.py +60 -0
- agentcapmap/enumerate/stdio.py +273 -0
- agentcapmap/enumerate/transport.py +86 -0
- agentcapmap/evaluation.py +498 -0
- agentcapmap/findings.py +129 -0
- agentcapmap/graph/__init__.py +264 -0
- agentcapmap/graph/server_attrs.py +164 -0
- agentcapmap/limits.py +35 -0
- agentcapmap/models.py +186 -0
- agentcapmap/policies/default.yaml +113 -0
- agentcapmap/policy/__init__.py +24 -0
- agentcapmap/policy/engine.py +229 -0
- agentcapmap/policy/loader.py +223 -0
- agentcapmap/py.typed +0 -0
- agentcapmap/redact.py +268 -0
- agentcapmap/report/__init__.py +36 -0
- agentcapmap/report/_text.py +62 -0
- agentcapmap/report/markdown.py +152 -0
- agentcapmap/report/sarif.py +209 -0
- agentcapmap/schemas/policy.schema.json +172 -0
- agentcapmap/schemas/tool-tags.schema.json +57 -0
- agentcapmap/taxonomy.py +56 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Reviewed reference classifications that ship with the package.
|
|
2
|
+
|
|
3
|
+
For tools whose exact definition (name, description, input schema) was labeled and
|
|
4
|
+
reviewed by a person, the classifier answers from this table instead of calling an LLM,
|
|
5
|
+
so common servers can be assessed with no API key. A match is by definition hash, so
|
|
6
|
+
any change to a tool is a miss and falls through to the cache or the LLM.
|
|
7
|
+
|
|
8
|
+
The table is generated from `eval/labeled_servers/` by `scripts/build_reference_labels.py`
|
|
9
|
+
and contains only files whose labeling status is "reviewed". Draft labels never ship.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import functools
|
|
15
|
+
import json
|
|
16
|
+
from importlib import resources
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
from pydantic import BaseModel, ConfigDict, Field, ValidationError
|
|
20
|
+
|
|
21
|
+
from agentcapmap.models import (
|
|
22
|
+
ClassificationStatus,
|
|
23
|
+
SuspiciousDescription,
|
|
24
|
+
ToolClassification,
|
|
25
|
+
ToolTags,
|
|
26
|
+
)
|
|
27
|
+
from agentcapmap.redact import get_logger
|
|
28
|
+
from agentcapmap.taxonomy import TAXONOMY_VERSION
|
|
29
|
+
|
|
30
|
+
log = get_logger(__name__)
|
|
31
|
+
|
|
32
|
+
BUNDLE_FILE = "reference_labels.json"
|
|
33
|
+
REFERENCE_MODEL = "reference-labels"
|
|
34
|
+
REFERENCE_PROMPT_VERSION = "reference"
|
|
35
|
+
_MAX_BUNDLE_BYTES = 8 * 1024 * 1024
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ReferenceEntry(BaseModel):
|
|
39
|
+
model_config = ConfigDict(extra="forbid")
|
|
40
|
+
|
|
41
|
+
tags: ToolTags
|
|
42
|
+
evidence: dict[str, str] = Field(default_factory=dict)
|
|
43
|
+
suspicious: bool = False
|
|
44
|
+
server: str # label file the entry came from
|
|
45
|
+
reviewed_by: str
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ReferenceBundle(BaseModel):
|
|
49
|
+
model_config = ConfigDict(extra="forbid")
|
|
50
|
+
|
|
51
|
+
taxonomy_version: str
|
|
52
|
+
classifications: dict[str, ReferenceEntry] = Field(default_factory=dict)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ReferenceLabels:
|
|
56
|
+
"""Lookup of reviewed classifications by tool definition hash."""
|
|
57
|
+
|
|
58
|
+
def __init__(self, bundle: ReferenceBundle | None = None) -> None:
|
|
59
|
+
usable = bundle is not None and bundle.taxonomy_version == TAXONOMY_VERSION
|
|
60
|
+
if bundle is not None and not usable:
|
|
61
|
+
log.warning(
|
|
62
|
+
"ignoring reference labels for taxonomy %s (this version uses %s)",
|
|
63
|
+
bundle.taxonomy_version,
|
|
64
|
+
TAXONOMY_VERSION,
|
|
65
|
+
)
|
|
66
|
+
self._entries = bundle.classifications if bundle is not None and usable else {}
|
|
67
|
+
|
|
68
|
+
def __len__(self) -> int:
|
|
69
|
+
return len(self._entries)
|
|
70
|
+
|
|
71
|
+
def lookup(self, definition_hash: str) -> ToolClassification | None:
|
|
72
|
+
entry = self._entries.get(definition_hash)
|
|
73
|
+
if entry is None:
|
|
74
|
+
return None
|
|
75
|
+
return ToolClassification(
|
|
76
|
+
status=ClassificationStatus.CLASSIFIED,
|
|
77
|
+
tags=entry.tags,
|
|
78
|
+
confidence=1.0,
|
|
79
|
+
evidence=entry.evidence,
|
|
80
|
+
suspicious_description=SuspiciousDescription(
|
|
81
|
+
flag=entry.suspicious,
|
|
82
|
+
reason="flagged in the reviewed reference labels" if entry.suspicious else "",
|
|
83
|
+
),
|
|
84
|
+
model=REFERENCE_MODEL,
|
|
85
|
+
taxonomy_version=TAXONOMY_VERSION,
|
|
86
|
+
prompt_version=REFERENCE_PROMPT_VERSION,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def parse_bundle(text: str) -> ReferenceBundle:
|
|
91
|
+
return ReferenceBundle.model_validate_json(text)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def dump_bundle(bundle: ReferenceBundle) -> str:
|
|
95
|
+
"""Canonical text form: sorted keys, stable across runs."""
|
|
96
|
+
data: dict[str, Any] = bundle.model_dump(mode="json")
|
|
97
|
+
return json.dumps(data, indent=2, sort_keys=True, ensure_ascii=False) + "\n"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@functools.cache
|
|
101
|
+
def load_reference() -> ReferenceLabels:
|
|
102
|
+
"""The bundled table; empty (never an error) if it is missing or invalid."""
|
|
103
|
+
resource = resources.files("agentcapmap").joinpath("classify", BUNDLE_FILE)
|
|
104
|
+
try:
|
|
105
|
+
if not resource.is_file():
|
|
106
|
+
return ReferenceLabels()
|
|
107
|
+
raw = resource.read_bytes()
|
|
108
|
+
if len(raw) > _MAX_BUNDLE_BYTES:
|
|
109
|
+
raise ValueError("bundle too large")
|
|
110
|
+
return ReferenceLabels(parse_bundle(raw.decode("utf-8")))
|
|
111
|
+
except (OSError, ValueError, ValidationError) as exc:
|
|
112
|
+
log.warning(
|
|
113
|
+
"cannot load reference labels (%s); continuing without them", type(exc).__name__
|
|
114
|
+
)
|
|
115
|
+
return ReferenceLabels()
|