agent_os_kernel 3.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_control_plane/__init__.py +662 -0
- agent_control_plane/a2a_adapter.py +543 -0
- agent_control_plane/adapter.py +417 -0
- agent_control_plane/agent_hibernation.py +394 -0
- agent_control_plane/agent_kernel.py +470 -0
- agent_control_plane/compliance.py +720 -0
- agent_control_plane/constraint_graphs.py +478 -0
- agent_control_plane/control_plane.py +854 -0
- agent_control_plane/example_executors.py +195 -0
- agent_control_plane/execution_engine.py +231 -0
- agent_control_plane/flight_recorder.py +846 -0
- agent_control_plane/governance_layer.py +435 -0
- agent_control_plane/hf_utils.py +563 -0
- agent_control_plane/interfaces/__init__.py +55 -0
- agent_control_plane/interfaces/kernel_interface.py +361 -0
- agent_control_plane/interfaces/plugin_interface.py +497 -0
- agent_control_plane/interfaces/protocol_interfaces.py +387 -0
- agent_control_plane/kernel_space.py +1009 -0
- agent_control_plane/langchain_adapter.py +424 -0
- agent_control_plane/lifecycle.py +3113 -0
- agent_control_plane/mcp_adapter.py +653 -0
- agent_control_plane/ml_safety.py +563 -0
- agent_control_plane/multimodal.py +727 -0
- agent_control_plane/mute_agent.py +422 -0
- agent_control_plane/observability.py +787 -0
- agent_control_plane/orchestrator.py +482 -0
- agent_control_plane/plugin_registry.py +750 -0
- agent_control_plane/policy_engine.py +954 -0
- agent_control_plane/process_isolation.py +777 -0
- agent_control_plane/shadow_mode.py +310 -0
- agent_control_plane/signals.py +493 -0
- agent_control_plane/supervisor_agents.py +430 -0
- agent_control_plane/time_travel_debugger.py +557 -0
- agent_control_plane/tool_registry.py +452 -0
- agent_control_plane/vfs.py +697 -0
- agent_kernel/__init__.py +69 -0
- agent_kernel/analyzer.py +435 -0
- agent_kernel/auditor.py +36 -0
- agent_kernel/completeness_auditor.py +237 -0
- agent_kernel/detector.py +203 -0
- agent_kernel/kernel.py +744 -0
- agent_kernel/memory_manager.py +85 -0
- agent_kernel/models.py +374 -0
- agent_kernel/nudge_mechanism.py +263 -0
- agent_kernel/outcome_analyzer.py +338 -0
- agent_kernel/patcher.py +582 -0
- agent_kernel/semantic_analyzer.py +316 -0
- agent_kernel/semantic_purge.py +349 -0
- agent_kernel/simulator.py +449 -0
- agent_kernel/teacher.py +85 -0
- agent_kernel/triage.py +152 -0
- agent_os/__init__.py +409 -0
- agent_os/_adversarial_impl.py +200 -0
- agent_os/_circuit_breaker_impl.py +232 -0
- agent_os/_mcp_metrics.py +193 -0
- agent_os/adversarial.py +20 -0
- agent_os/agents_compat.py +490 -0
- agent_os/audit_logger.py +135 -0
- agent_os/base_agent.py +651 -0
- agent_os/circuit_breaker.py +34 -0
- agent_os/cli/__init__.py +659 -0
- agent_os/cli/cmd_audit.py +128 -0
- agent_os/cli/cmd_init.py +152 -0
- agent_os/cli/cmd_policy.py +41 -0
- agent_os/cli/cmd_policy_gen.py +180 -0
- agent_os/cli/cmd_validate.py +258 -0
- agent_os/cli/mcp_scan.py +265 -0
- agent_os/cli/output.py +192 -0
- agent_os/cli/policy_checker.py +330 -0
- agent_os/compat.py +74 -0
- agent_os/constraint_graph.py +234 -0
- agent_os/content_governance.py +140 -0
- agent_os/context_budget.py +305 -0
- agent_os/credential_redactor.py +224 -0
- agent_os/diff_policy.py +89 -0
- agent_os/egress_policy.py +159 -0
- agent_os/escalation.py +276 -0
- agent_os/event_bus.py +124 -0
- agent_os/exceptions.py +180 -0
- agent_os/execution_context_policy.py +141 -0
- agent_os/github_enterprise.py +96 -0
- agent_os/health.py +20 -0
- agent_os/integrations/__init__.py +279 -0
- agent_os/integrations/a2a_adapter.py +279 -0
- agent_os/integrations/agent_lightning/__init__.py +30 -0
- agent_os/integrations/anthropic_adapter.py +420 -0
- agent_os/integrations/autogen_adapter.py +620 -0
- agent_os/integrations/base.py +1137 -0
- agent_os/integrations/compat.py +229 -0
- agent_os/integrations/config.py +98 -0
- agent_os/integrations/conversation_guardian.py +957 -0
- agent_os/integrations/crewai_adapter.py +467 -0
- agent_os/integrations/drift_detector.py +425 -0
- agent_os/integrations/dry_run.py +124 -0
- agent_os/integrations/escalation.py +582 -0
- agent_os/integrations/gemini_adapter.py +364 -0
- agent_os/integrations/google_adk_adapter.py +633 -0
- agent_os/integrations/guardrails_adapter.py +394 -0
- agent_os/integrations/health.py +197 -0
- agent_os/integrations/langchain_adapter.py +654 -0
- agent_os/integrations/llamafirewall.py +343 -0
- agent_os/integrations/llamaindex_adapter.py +188 -0
- agent_os/integrations/logging.py +191 -0
- agent_os/integrations/maf_adapter.py +631 -0
- agent_os/integrations/mistral_adapter.py +365 -0
- agent_os/integrations/openai_adapter.py +816 -0
- agent_os/integrations/openai_agents_sdk.py +406 -0
- agent_os/integrations/policy_compose.py +171 -0
- agent_os/integrations/profiling.py +144 -0
- agent_os/integrations/pydantic_ai_adapter.py +420 -0
- agent_os/integrations/rate_limiter.py +130 -0
- agent_os/integrations/rbac.py +143 -0
- agent_os/integrations/registry.py +113 -0
- agent_os/integrations/scope_guard.py +303 -0
- agent_os/integrations/semantic_kernel_adapter.py +769 -0
- agent_os/integrations/smolagents_adapter.py +629 -0
- agent_os/integrations/templates.py +178 -0
- agent_os/integrations/token_budget.py +134 -0
- agent_os/integrations/tool_aliases.py +190 -0
- agent_os/integrations/webhooks.py +177 -0
- agent_os/lite.py +208 -0
- agent_os/mcp_gateway.py +385 -0
- agent_os/mcp_message_signer.py +273 -0
- agent_os/mcp_protocols.py +161 -0
- agent_os/mcp_response_scanner.py +232 -0
- agent_os/mcp_security.py +924 -0
- agent_os/mcp_session_auth.py +231 -0
- agent_os/mcp_sliding_rate_limiter.py +184 -0
- agent_os/memory_guard.py +409 -0
- agent_os/metrics.py +134 -0
- agent_os/mute.py +428 -0
- agent_os/mute_agent.py +209 -0
- agent_os/policies/__init__.py +77 -0
- agent_os/policies/async_evaluator.py +275 -0
- agent_os/policies/backends.py +670 -0
- agent_os/policies/bridge.py +169 -0
- agent_os/policies/budget.py +85 -0
- agent_os/policies/cli.py +294 -0
- agent_os/policies/conflict_resolution.py +270 -0
- agent_os/policies/data_classification.py +252 -0
- agent_os/policies/evaluator.py +239 -0
- agent_os/policies/policy_schema.json +228 -0
- agent_os/policies/rate_limiting.py +145 -0
- agent_os/policies/schema.py +115 -0
- agent_os/policies/shared.py +331 -0
- agent_os/prompt_injection.py +694 -0
- agent_os/providers.py +182 -0
- agent_os/py.typed +0 -0
- agent_os/retry.py +81 -0
- agent_os/reversibility.py +251 -0
- agent_os/sandbox.py +432 -0
- agent_os/sandbox_provider.py +140 -0
- agent_os/secure_codegen.py +525 -0
- agent_os/security_skills.py +538 -0
- agent_os/semantic_policy.py +422 -0
- agent_os/server/__init__.py +15 -0
- agent_os/server/__main__.py +25 -0
- agent_os/server/app.py +277 -0
- agent_os/server/models.py +104 -0
- agent_os/shift_left_metrics.py +130 -0
- agent_os/stateless.py +742 -0
- agent_os/supervisor.py +148 -0
- agent_os/task_outcome.py +148 -0
- agent_os/transparency.py +181 -0
- agent_os/trust_root.py +128 -0
- agent_os_kernel-3.1.0.dist-info/METADATA +1269 -0
- agent_os_kernel-3.1.0.dist-info/RECORD +337 -0
- agent_os_kernel-3.1.0.dist-info/WHEEL +4 -0
- agent_os_kernel-3.1.0.dist-info/entry_points.txt +2 -0
- agent_os_kernel-3.1.0.dist-info/licenses/LICENSE +21 -0
- agent_os_observability/__init__.py +27 -0
- agent_os_observability/dashboards.py +898 -0
- agent_os_observability/metrics.py +398 -0
- agent_os_observability/server.py +223 -0
- agent_os_observability/tracer.py +232 -0
- agent_primitives/__init__.py +24 -0
- agent_primitives/failures.py +84 -0
- agent_primitives/py.typed +0 -0
- amb_core/__init__.py +177 -0
- amb_core/adapters/__init__.py +57 -0
- amb_core/adapters/aws_sqs_broker.py +376 -0
- amb_core/adapters/azure_servicebus_broker.py +340 -0
- amb_core/adapters/kafka_broker.py +260 -0
- amb_core/adapters/nats_broker.py +285 -0
- amb_core/adapters/rabbitmq_broker.py +235 -0
- amb_core/adapters/redis_broker.py +262 -0
- amb_core/broker.py +145 -0
- amb_core/bus.py +481 -0
- amb_core/cloudevents.py +509 -0
- amb_core/dlq.py +345 -0
- amb_core/hf_utils.py +536 -0
- amb_core/memory_broker.py +410 -0
- amb_core/models.py +141 -0
- amb_core/persistence.py +529 -0
- amb_core/schema.py +294 -0
- amb_core/tracing.py +358 -0
- atr/__init__.py +640 -0
- atr/access.py +348 -0
- atr/composition.py +645 -0
- atr/decorator.py +357 -0
- atr/executor.py +384 -0
- atr/health.py +557 -0
- atr/hf_utils.py +449 -0
- atr/injection.py +422 -0
- atr/metrics.py +440 -0
- atr/policies.py +403 -0
- atr/py.typed +2 -0
- atr/registry.py +452 -0
- atr/schema.py +480 -0
- atr/tools/safe/__init__.py +75 -0
- atr/tools/safe/calculator.py +467 -0
- atr/tools/safe/datetime_tool.py +443 -0
- atr/tools/safe/file_reader.py +402 -0
- atr/tools/safe/http_client.py +316 -0
- atr/tools/safe/json_parser.py +374 -0
- atr/tools/safe/text_tool.py +537 -0
- atr/tools/safe/toolkit.py +175 -0
- caas/__init__.py +162 -0
- caas/api/__init__.py +7 -0
- caas/api/server.py +1328 -0
- caas/caching.py +834 -0
- caas/cli.py +210 -0
- caas/conversation.py +223 -0
- caas/decay.py +72 -0
- caas/detection/__init__.py +9 -0
- caas/detection/detector.py +238 -0
- caas/enrichment.py +130 -0
- caas/gateway/__init__.py +27 -0
- caas/gateway/trust_gateway.py +474 -0
- caas/hf_utils.py +479 -0
- caas/ingestion/__init__.py +23 -0
- caas/ingestion/processors.py +253 -0
- caas/ingestion/structure_parser.py +188 -0
- caas/models.py +356 -0
- caas/pragmatic_truth.py +444 -0
- caas/routing/__init__.py +10 -0
- caas/routing/heuristic_router.py +58 -0
- caas/storage/__init__.py +9 -0
- caas/storage/store.py +389 -0
- caas/triad.py +213 -0
- caas/tuning/__init__.py +9 -0
- caas/tuning/tuner.py +329 -0
- caas/vfs/__init__.py +14 -0
- caas/vfs/filesystem.py +452 -0
- cmvk/__init__.py +218 -0
- cmvk/audit.py +402 -0
- cmvk/benchmarks.py +478 -0
- cmvk/constitutional.py +904 -0
- cmvk/hf_utils.py +301 -0
- cmvk/metrics.py +473 -0
- cmvk/profiles.py +300 -0
- cmvk/py.typed +0 -0
- cmvk/types.py +12 -0
- cmvk/verification.py +956 -0
- emk/__init__.py +89 -0
- emk/causal.py +352 -0
- emk/hf_utils.py +421 -0
- emk/indexer.py +83 -0
- emk/py.typed +0 -0
- emk/schema.py +204 -0
- emk/sleep_cycle.py +347 -0
- emk/store.py +281 -0
- iatp/__init__.py +166 -0
- iatp/attestation.py +461 -0
- iatp/cli.py +317 -0
- iatp/hf_utils.py +472 -0
- iatp/ipc_pipes.py +580 -0
- iatp/main.py +412 -0
- iatp/models/__init__.py +447 -0
- iatp/policy_engine.py +337 -0
- iatp/py.typed +2 -0
- iatp/recovery.py +321 -0
- iatp/security/__init__.py +270 -0
- iatp/sidecar/__init__.py +519 -0
- iatp/telemetry/__init__.py +164 -0
- iatp/tests/__init__.py +1 -0
- iatp/tests/test_attestation.py +370 -0
- iatp/tests/test_cli.py +131 -0
- iatp/tests/test_ed25519_attestation.py +211 -0
- iatp/tests/test_models.py +130 -0
- iatp/tests/test_policy_engine.py +347 -0
- iatp/tests/test_recovery.py +281 -0
- iatp/tests/test_security.py +222 -0
- iatp/tests/test_sidecar.py +167 -0
- iatp/tests/test_telemetry.py +175 -0
- mcp_kernel_server/__init__.py +28 -0
- mcp_kernel_server/cli.py +274 -0
- mcp_kernel_server/resources.py +217 -0
- mcp_kernel_server/server.py +564 -0
- mcp_kernel_server/tools.py +1174 -0
- mute_agent/__init__.py +68 -0
- mute_agent/core/__init__.py +1 -0
- mute_agent/core/execution_agent.py +166 -0
- mute_agent/core/handshake_protocol.py +201 -0
- mute_agent/core/reasoning_agent.py +238 -0
- mute_agent/knowledge_graph/__init__.py +1 -0
- mute_agent/knowledge_graph/graph_elements.py +65 -0
- mute_agent/knowledge_graph/multidimensional_graph.py +170 -0
- mute_agent/knowledge_graph/subgraph.py +224 -0
- mute_agent/listener/__init__.py +43 -0
- mute_agent/listener/adapters/__init__.py +31 -0
- mute_agent/listener/adapters/base_adapter.py +189 -0
- mute_agent/listener/adapters/caas_adapter.py +344 -0
- mute_agent/listener/adapters/control_plane_adapter.py +436 -0
- mute_agent/listener/adapters/iatp_adapter.py +332 -0
- mute_agent/listener/adapters/scak_adapter.py +251 -0
- mute_agent/listener/listener.py +610 -0
- mute_agent/listener/state_observer.py +436 -0
- mute_agent/listener/threshold_config.py +313 -0
- mute_agent/super_system/__init__.py +1 -0
- mute_agent/super_system/router.py +204 -0
- mute_agent/visualization/__init__.py +10 -0
- mute_agent/visualization/graph_debugger.py +502 -0
- nexus/README.md +60 -0
- nexus/__init__.py +51 -0
- nexus/arbiter.py +359 -0
- nexus/client.py +466 -0
- nexus/dmz.py +444 -0
- nexus/escrow.py +430 -0
- nexus/exceptions.py +286 -0
- nexus/pyproject.toml +36 -0
- nexus/registry.py +393 -0
- nexus/reputation.py +425 -0
- nexus/schemas/__init__.py +51 -0
- nexus/schemas/compliance.py +276 -0
- nexus/schemas/escrow.py +251 -0
- nexus/schemas/manifest.py +225 -0
- nexus/schemas/receipt.py +208 -0
- nexus/tests/__init__.py +0 -0
- nexus/tests/conftest.py +146 -0
- nexus/tests/test_arbiter.py +192 -0
- nexus/tests/test_dmz.py +194 -0
- nexus/tests/test_escrow.py +276 -0
- nexus/tests/test_exceptions.py +225 -0
- nexus/tests/test_registry.py +232 -0
- nexus/tests/test_reputation.py +328 -0
- nexus/tests/test_schemas.py +295 -0
nexus/client.py
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
"""
|
|
4
|
+
Nexus Client
|
|
5
|
+
|
|
6
|
+
Client for Agent OS agents to interact with Nexus.
|
|
7
|
+
Handles registration, peer verification, and reputation sync.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from datetime import datetime, timezone
|
|
11
|
+
from typing import Optional, Literal
|
|
12
|
+
import asyncio
|
|
13
|
+
import aiohttp
|
|
14
|
+
|
|
15
|
+
from .schemas.manifest import AgentManifest
|
|
16
|
+
from .registry import AgentRegistry, RegistrationResult, PeerVerification
|
|
17
|
+
from .reputation import ReputationEngine, TrustScore
|
|
18
|
+
from .escrow import ProofOfOutcome, EscrowManager
|
|
19
|
+
from .arbiter import Arbiter
|
|
20
|
+
from .dmz import DMZProtocol, DataHandlingPolicy
|
|
21
|
+
from .exceptions import (
|
|
22
|
+
IATPUnverifiedPeerException,
|
|
23
|
+
IATPInsufficientTrustException,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class NexusClient:
|
|
28
|
+
"""
|
|
29
|
+
Client for Agent OS agents to interact with Nexus.
|
|
30
|
+
|
|
31
|
+
Installed in: agent_os.kernel.network
|
|
32
|
+
|
|
33
|
+
Provides:
|
|
34
|
+
- Agent registration and updates
|
|
35
|
+
- Peer verification before IATP handshake
|
|
36
|
+
- Reputation sync for local cache
|
|
37
|
+
- Escrow/reward management
|
|
38
|
+
- DMZ data transfer
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
# Default API endpoints
|
|
42
|
+
DEFAULT_API_URL = "https://api.nexus.agent-os.dev/v1"
|
|
43
|
+
DEFAULT_TRUST_THRESHOLD = 700
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
agent_manifest: AgentManifest,
|
|
48
|
+
api_key: str,
|
|
49
|
+
api_url: Optional[str] = None,
|
|
50
|
+
trust_threshold: int = DEFAULT_TRUST_THRESHOLD,
|
|
51
|
+
# For local/testing - use in-memory components
|
|
52
|
+
local_mode: bool = False,
|
|
53
|
+
):
|
|
54
|
+
self.manifest = agent_manifest
|
|
55
|
+
self.api_key = api_key
|
|
56
|
+
self.base_url = api_url or self.DEFAULT_API_URL
|
|
57
|
+
self.trust_threshold = trust_threshold
|
|
58
|
+
self.local_mode = local_mode
|
|
59
|
+
|
|
60
|
+
# Local cache of peer reputations
|
|
61
|
+
self._known_peers: dict[str, int] = {} # DID -> Trust Score
|
|
62
|
+
self._last_sync: Optional[datetime] = None
|
|
63
|
+
|
|
64
|
+
# For local mode testing
|
|
65
|
+
if local_mode:
|
|
66
|
+
self._local_registry = AgentRegistry()
|
|
67
|
+
self._local_reputation = ReputationEngine()
|
|
68
|
+
self._local_escrow = EscrowManager(self._local_reputation)
|
|
69
|
+
self._local_arbiter = Arbiter(self._local_reputation)
|
|
70
|
+
self._local_dmz = DMZProtocol()
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def agent_did(self) -> str:
|
|
74
|
+
"""Get this agent's DID."""
|
|
75
|
+
return self.manifest.identity.did
|
|
76
|
+
|
|
77
|
+
# ==================== Registration ====================
|
|
78
|
+
|
|
79
|
+
async def register(self) -> RegistrationResult:
|
|
80
|
+
"""
|
|
81
|
+
Register this agent on Nexus.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
RegistrationResult with status and initial trust score
|
|
85
|
+
"""
|
|
86
|
+
if self.local_mode:
|
|
87
|
+
signature = self._generate_signature(self.manifest.model_dump())
|
|
88
|
+
return await self._local_registry.register(self.manifest, signature)
|
|
89
|
+
|
|
90
|
+
async with aiohttp.ClientSession() as session:
|
|
91
|
+
async with session.post(
|
|
92
|
+
f"{self.base_url}/agents",
|
|
93
|
+
json=self.manifest.model_dump(),
|
|
94
|
+
headers=self._headers(),
|
|
95
|
+
) as resp:
|
|
96
|
+
data = await resp.json()
|
|
97
|
+
return RegistrationResult(**data)
|
|
98
|
+
|
|
99
|
+
async def update_manifest(self, manifest: AgentManifest) -> RegistrationResult:
|
|
100
|
+
"""Update this agent's manifest."""
|
|
101
|
+
self.manifest = manifest
|
|
102
|
+
|
|
103
|
+
if self.local_mode:
|
|
104
|
+
signature = self._generate_signature(manifest.model_dump())
|
|
105
|
+
return await self._local_registry.update(self.agent_did, manifest, signature)
|
|
106
|
+
|
|
107
|
+
async with aiohttp.ClientSession() as session:
|
|
108
|
+
async with session.put(
|
|
109
|
+
f"{self.base_url}/agents/{self.agent_did}",
|
|
110
|
+
json=manifest.model_dump(),
|
|
111
|
+
headers=self._headers(),
|
|
112
|
+
) as resp:
|
|
113
|
+
data = await resp.json()
|
|
114
|
+
return RegistrationResult(**data)
|
|
115
|
+
|
|
116
|
+
async def deregister(self) -> bool:
|
|
117
|
+
"""Remove this agent from Nexus."""
|
|
118
|
+
if self.local_mode:
|
|
119
|
+
signature = self._generate_signature({"did": self.agent_did})
|
|
120
|
+
return await self._local_registry.deregister(self.agent_did, signature)
|
|
121
|
+
|
|
122
|
+
async with aiohttp.ClientSession() as session:
|
|
123
|
+
async with session.delete(
|
|
124
|
+
f"{self.base_url}/agents/{self.agent_did}",
|
|
125
|
+
headers=self._headers(),
|
|
126
|
+
) as resp:
|
|
127
|
+
return resp.status == 200
|
|
128
|
+
|
|
129
|
+
# ==================== Peer Verification ====================
|
|
130
|
+
|
|
131
|
+
async def verify_peer(
|
|
132
|
+
self,
|
|
133
|
+
peer_did: str,
|
|
134
|
+
min_score: Optional[int] = None,
|
|
135
|
+
required_capabilities: Optional[list[str]] = None,
|
|
136
|
+
) -> PeerVerification:
|
|
137
|
+
"""
|
|
138
|
+
Verify a peer agent before IATP handshake.
|
|
139
|
+
|
|
140
|
+
This is the core viral mechanism - unverified peers get
|
|
141
|
+
directed to register on Nexus.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
peer_did: DID of the peer to verify
|
|
145
|
+
min_score: Minimum required trust score (default: trust_threshold)
|
|
146
|
+
required_capabilities: Capabilities the peer must have
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
PeerVerification result
|
|
150
|
+
|
|
151
|
+
Raises:
|
|
152
|
+
IATPUnverifiedPeerException: If peer is not registered
|
|
153
|
+
IATPInsufficientTrustException: If peer's score is below threshold
|
|
154
|
+
"""
|
|
155
|
+
threshold = min_score or self.trust_threshold
|
|
156
|
+
|
|
157
|
+
if self.local_mode:
|
|
158
|
+
return await self._local_registry.verify_peer(
|
|
159
|
+
peer_did, threshold, required_capabilities
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Check local cache first
|
|
163
|
+
if peer_did in self._known_peers:
|
|
164
|
+
cached_score = self._known_peers[peer_did]
|
|
165
|
+
if cached_score < threshold:
|
|
166
|
+
raise IATPInsufficientTrustException(
|
|
167
|
+
peer_did, cached_score, threshold
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Verify with Nexus API
|
|
171
|
+
async with aiohttp.ClientSession() as session:
|
|
172
|
+
async with session.get(
|
|
173
|
+
f"{self.base_url}/agents/{peer_did}/verify",
|
|
174
|
+
params={
|
|
175
|
+
"min_score": threshold,
|
|
176
|
+
"capabilities": ",".join(required_capabilities or []),
|
|
177
|
+
},
|
|
178
|
+
headers=self._headers(),
|
|
179
|
+
) as resp:
|
|
180
|
+
if resp.status == 404:
|
|
181
|
+
raise IATPUnverifiedPeerException(peer_did)
|
|
182
|
+
|
|
183
|
+
data = await resp.json()
|
|
184
|
+
|
|
185
|
+
if data.get("error") == "IATP_INSUFFICIENT_TRUST":
|
|
186
|
+
raise IATPInsufficientTrustException(
|
|
187
|
+
peer_did,
|
|
188
|
+
data["current_score"],
|
|
189
|
+
data["required_score"],
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
# Update cache
|
|
193
|
+
self._known_peers[peer_did] = data.get("trust_score", 0)
|
|
194
|
+
|
|
195
|
+
return PeerVerification(**data)
|
|
196
|
+
|
|
197
|
+
async def quick_verify(self, peer_did: str) -> bool:
|
|
198
|
+
"""
|
|
199
|
+
Quick check if peer meets trust threshold.
|
|
200
|
+
|
|
201
|
+
Uses local cache when possible for speed.
|
|
202
|
+
"""
|
|
203
|
+
try:
|
|
204
|
+
await self.verify_peer(peer_did)
|
|
205
|
+
return True
|
|
206
|
+
except (IATPUnverifiedPeerException, IATPInsufficientTrustException):
|
|
207
|
+
return False
|
|
208
|
+
|
|
209
|
+
# ==================== Reputation Sync ====================
|
|
210
|
+
|
|
211
|
+
async def sync_reputation(
|
|
212
|
+
self,
|
|
213
|
+
force: bool = False,
|
|
214
|
+
) -> dict[str, int]:
|
|
215
|
+
"""
|
|
216
|
+
Sync local known_peers cache with global reputation.
|
|
217
|
+
|
|
218
|
+
Called periodically by the kernel to keep cache fresh.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
force: Force sync even if recently synced
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Updated mapping of DID -> Trust Score
|
|
225
|
+
"""
|
|
226
|
+
# Rate limit syncs (every 5 minutes unless forced)
|
|
227
|
+
if not force and self._last_sync:
|
|
228
|
+
elapsed = (datetime.now(timezone.utc) - self._last_sync).total_seconds()
|
|
229
|
+
if elapsed < 300: # 5 minutes
|
|
230
|
+
return self._known_peers
|
|
231
|
+
|
|
232
|
+
if self.local_mode:
|
|
233
|
+
self._known_peers = await self._local_registry.get_reputation_sync()
|
|
234
|
+
else:
|
|
235
|
+
async with aiohttp.ClientSession() as session:
|
|
236
|
+
async with session.get(
|
|
237
|
+
f"{self.base_url}/reputation/sync",
|
|
238
|
+
headers=self._headers(),
|
|
239
|
+
) as resp:
|
|
240
|
+
data = await resp.json()
|
|
241
|
+
self._known_peers = data.get("scores", {})
|
|
242
|
+
|
|
243
|
+
self._last_sync = datetime.now(timezone.utc)
|
|
244
|
+
return self._known_peers
|
|
245
|
+
|
|
246
|
+
async def report_outcome(
|
|
247
|
+
self,
|
|
248
|
+
task_id: str,
|
|
249
|
+
peer_did: str,
|
|
250
|
+
outcome: Literal["success", "failure", "dispute"],
|
|
251
|
+
) -> None:
|
|
252
|
+
"""Report task outcome to update reputation."""
|
|
253
|
+
if self.local_mode:
|
|
254
|
+
self._local_reputation.record_task_outcome(peer_did, outcome)
|
|
255
|
+
return
|
|
256
|
+
|
|
257
|
+
async with aiohttp.ClientSession() as session:
|
|
258
|
+
await session.post(
|
|
259
|
+
f"{self.base_url}/reputation/{peer_did}/report",
|
|
260
|
+
json={
|
|
261
|
+
"task_id": task_id,
|
|
262
|
+
"reporter_did": self.agent_did,
|
|
263
|
+
"outcome": outcome,
|
|
264
|
+
},
|
|
265
|
+
headers=self._headers(),
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# ==================== Escrow / Proof of Outcome ====================
|
|
269
|
+
|
|
270
|
+
async def create_escrow(
|
|
271
|
+
self,
|
|
272
|
+
provider_did: str,
|
|
273
|
+
task_hash: str,
|
|
274
|
+
credits: int,
|
|
275
|
+
timeout_seconds: int = 3600,
|
|
276
|
+
) -> dict:
|
|
277
|
+
"""
|
|
278
|
+
Create an escrow for a task.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
provider_did: DID of the agent providing the service
|
|
282
|
+
task_hash: SHA-256 hash of the task specification
|
|
283
|
+
credits: Number of credits to escrow
|
|
284
|
+
timeout_seconds: Timeout for task completion
|
|
285
|
+
"""
|
|
286
|
+
if self.local_mode:
|
|
287
|
+
poo = ProofOfOutcome(self._local_escrow)
|
|
288
|
+
receipt = await poo.create_escrow(
|
|
289
|
+
requester_did=self.agent_did,
|
|
290
|
+
provider_did=provider_did,
|
|
291
|
+
task_hash=task_hash,
|
|
292
|
+
credits=credits,
|
|
293
|
+
timeout_seconds=timeout_seconds,
|
|
294
|
+
)
|
|
295
|
+
return receipt.model_dump()
|
|
296
|
+
|
|
297
|
+
async with aiohttp.ClientSession() as session:
|
|
298
|
+
async with session.post(
|
|
299
|
+
f"{self.base_url}/escrow",
|
|
300
|
+
json={
|
|
301
|
+
"requester_did": self.agent_did,
|
|
302
|
+
"provider_did": provider_did,
|
|
303
|
+
"task_hash": task_hash,
|
|
304
|
+
"credits": credits,
|
|
305
|
+
"timeout_seconds": timeout_seconds,
|
|
306
|
+
},
|
|
307
|
+
headers=self._headers(),
|
|
308
|
+
) as resp:
|
|
309
|
+
return await resp.json()
|
|
310
|
+
|
|
311
|
+
async def release_escrow(
|
|
312
|
+
self,
|
|
313
|
+
escrow_id: str,
|
|
314
|
+
outcome: Literal["success", "failure", "dispute"],
|
|
315
|
+
output_hash: Optional[str] = None,
|
|
316
|
+
) -> dict:
|
|
317
|
+
"""Release an escrow based on outcome."""
|
|
318
|
+
if self.local_mode:
|
|
319
|
+
poo = ProofOfOutcome(self._local_escrow)
|
|
320
|
+
resolution = await poo.release_escrow(
|
|
321
|
+
escrow_id=escrow_id,
|
|
322
|
+
outcome=outcome,
|
|
323
|
+
output_hash=output_hash,
|
|
324
|
+
)
|
|
325
|
+
return {
|
|
326
|
+
"escrow_id": resolution.escrow_id,
|
|
327
|
+
"status": resolution.final_status.value,
|
|
328
|
+
"credits_to_provider": resolution.credits_to_provider,
|
|
329
|
+
"credits_to_requester": resolution.credits_to_requester,
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async with aiohttp.ClientSession() as session:
|
|
333
|
+
async with session.post(
|
|
334
|
+
f"{self.base_url}/escrow/{escrow_id}/release",
|
|
335
|
+
json={
|
|
336
|
+
"outcome": outcome,
|
|
337
|
+
"output_hash": output_hash,
|
|
338
|
+
},
|
|
339
|
+
headers=self._headers(),
|
|
340
|
+
) as resp:
|
|
341
|
+
return await resp.json()
|
|
342
|
+
|
|
343
|
+
# ==================== DMZ Protocol ====================
|
|
344
|
+
|
|
345
|
+
async def initiate_dmz_transfer(
|
|
346
|
+
self,
|
|
347
|
+
receiver_did: str,
|
|
348
|
+
data: bytes,
|
|
349
|
+
classification: Literal["public", "internal", "confidential", "pii"],
|
|
350
|
+
policy: DataHandlingPolicy,
|
|
351
|
+
) -> dict:
|
|
352
|
+
"""Initiate a secure DMZ transfer."""
|
|
353
|
+
if self.local_mode:
|
|
354
|
+
request = await self._local_dmz.initiate_transfer(
|
|
355
|
+
sender_did=self.agent_did,
|
|
356
|
+
receiver_did=receiver_did,
|
|
357
|
+
data=data,
|
|
358
|
+
classification=classification,
|
|
359
|
+
policy=policy,
|
|
360
|
+
)
|
|
361
|
+
return request.model_dump()
|
|
362
|
+
|
|
363
|
+
# Would implement API call for remote mode
|
|
364
|
+
raise NotImplementedError("Remote DMZ not yet implemented")
|
|
365
|
+
|
|
366
|
+
async def sign_dmz_policy(
|
|
367
|
+
self,
|
|
368
|
+
transfer_id: str,
|
|
369
|
+
) -> dict:
|
|
370
|
+
"""Sign a DMZ data handling policy to receive access."""
|
|
371
|
+
if self.local_mode:
|
|
372
|
+
signature = self._generate_signature({"transfer_id": transfer_id})
|
|
373
|
+
signed = await self._local_dmz.sign_policy(
|
|
374
|
+
transfer_id, self.agent_did, signature
|
|
375
|
+
)
|
|
376
|
+
return {
|
|
377
|
+
"policy_hash": signed.policy_hash,
|
|
378
|
+
"signed_at": signed.signed_at.isoformat(),
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
raise NotImplementedError("Remote DMZ not yet implemented")
|
|
382
|
+
|
|
383
|
+
async def get_dmz_key(self, transfer_id: str) -> bytes:
|
|
384
|
+
"""Get decryption key for a DMZ transfer."""
|
|
385
|
+
if self.local_mode:
|
|
386
|
+
return await self._local_dmz.release_key(transfer_id, self.agent_did)
|
|
387
|
+
|
|
388
|
+
raise NotImplementedError("Remote DMZ not yet implemented")
|
|
389
|
+
|
|
390
|
+
# ==================== Discovery ====================
|
|
391
|
+
|
|
392
|
+
async def discover_agents(
|
|
393
|
+
self,
|
|
394
|
+
capabilities: Optional[list[str]] = None,
|
|
395
|
+
min_score: int = 500,
|
|
396
|
+
privacy_policy: Optional[str] = None,
|
|
397
|
+
limit: int = 100,
|
|
398
|
+
) -> list[dict]:
|
|
399
|
+
"""Discover agents matching criteria."""
|
|
400
|
+
if self.local_mode:
|
|
401
|
+
manifests = await self._local_registry.discover_agents(
|
|
402
|
+
capabilities=capabilities,
|
|
403
|
+
min_score=min_score,
|
|
404
|
+
privacy_policy=privacy_policy,
|
|
405
|
+
limit=limit,
|
|
406
|
+
)
|
|
407
|
+
return [m.model_dump() for m in manifests]
|
|
408
|
+
|
|
409
|
+
async with aiohttp.ClientSession() as session:
|
|
410
|
+
params = {"min_score": min_score, "limit": limit}
|
|
411
|
+
if capabilities:
|
|
412
|
+
params["capabilities"] = ",".join(capabilities)
|
|
413
|
+
if privacy_policy:
|
|
414
|
+
params["privacy_policy"] = privacy_policy
|
|
415
|
+
|
|
416
|
+
async with session.get(
|
|
417
|
+
f"{self.base_url}/agents/discover",
|
|
418
|
+
params=params,
|
|
419
|
+
headers=self._headers(),
|
|
420
|
+
) as resp:
|
|
421
|
+
data = await resp.json()
|
|
422
|
+
return data.get("agents", [])
|
|
423
|
+
|
|
424
|
+
# ==================== Credits ====================
|
|
425
|
+
|
|
426
|
+
async def get_credits(self) -> int:
|
|
427
|
+
"""Get credit balance."""
|
|
428
|
+
if self.local_mode:
|
|
429
|
+
return self._local_escrow.get_agent_credits(self.agent_did)
|
|
430
|
+
|
|
431
|
+
async with aiohttp.ClientSession() as session:
|
|
432
|
+
async with session.get(
|
|
433
|
+
f"{self.base_url}/credits/{self.agent_did}",
|
|
434
|
+
headers=self._headers(),
|
|
435
|
+
) as resp:
|
|
436
|
+
data = await resp.json()
|
|
437
|
+
return data.get("credits", 0)
|
|
438
|
+
|
|
439
|
+
# ==================== Internal Helpers ====================
|
|
440
|
+
|
|
441
|
+
def _headers(self) -> dict:
|
|
442
|
+
"""Get API request headers."""
|
|
443
|
+
return {
|
|
444
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
445
|
+
"X-Agent-DID": self.agent_did,
|
|
446
|
+
"Content-Type": "application/json",
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
def _generate_signature(self, data: dict) -> str:
|
|
450
|
+
"""Generate signature for data (placeholder)."""
|
|
451
|
+
import hashlib
|
|
452
|
+
import json
|
|
453
|
+
canonical = json.dumps(data, sort_keys=True, default=str)
|
|
454
|
+
return f"sig_{hashlib.sha256(canonical.encode()).hexdigest()[:32]}"
|
|
455
|
+
|
|
456
|
+
# ==================== Context Manager ====================
|
|
457
|
+
|
|
458
|
+
async def __aenter__(self):
|
|
459
|
+
"""Async context manager entry."""
|
|
460
|
+
await self.register()
|
|
461
|
+
return self
|
|
462
|
+
|
|
463
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
464
|
+
"""Async context manager exit."""
|
|
465
|
+
# Don't deregister on exit - agent should persist
|
|
466
|
+
pass
|