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
amb_core/cloudevents.py
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
"""CloudEvents specification support for AMB.
|
|
4
|
+
|
|
5
|
+
This module provides CloudEvents v1.0 compatibility, enabling interoperability
|
|
6
|
+
with other systems that support the CNCF CloudEvents specification.
|
|
7
|
+
|
|
8
|
+
CloudEvents Spec: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
from amb_core.cloudevents import CloudEvent, to_cloudevent, from_cloudevent
|
|
12
|
+
|
|
13
|
+
# Convert AMB Message to CloudEvent
|
|
14
|
+
message = Message(id="123", topic="fraud.alerts", payload={"risk": 0.9})
|
|
15
|
+
cloud_event = to_cloudevent(message, source="/agent-os/fraud-detector")
|
|
16
|
+
|
|
17
|
+
# Send as JSON (CloudEvents structured content mode)
|
|
18
|
+
json_data = cloud_event.to_json()
|
|
19
|
+
|
|
20
|
+
# Convert CloudEvent back to AMB Message
|
|
21
|
+
message = from_cloudevent(cloud_event)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from datetime import datetime, timezone
|
|
25
|
+
from typing import Any, Dict, Optional, Union
|
|
26
|
+
from pydantic import BaseModel, Field, field_validator, ConfigDict
|
|
27
|
+
import json
|
|
28
|
+
import uuid
|
|
29
|
+
|
|
30
|
+
from amb_core.models import Message, MessagePriority
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# CloudEvents spec version
|
|
34
|
+
CLOUDEVENTS_SPEC_VERSION = "1.0"
|
|
35
|
+
|
|
36
|
+
# CloudEvents content type
|
|
37
|
+
CLOUDEVENTS_CONTENT_TYPE = "application/cloudevents+json"
|
|
38
|
+
|
|
39
|
+
# Agent OS event type prefix
|
|
40
|
+
AGENT_OS_TYPE_PREFIX = "dev.agent-os"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class CloudEvent(BaseModel):
|
|
44
|
+
"""
|
|
45
|
+
CloudEvents v1.0 specification compliant event.
|
|
46
|
+
|
|
47
|
+
This model implements the CloudEvents specification required and optional attributes.
|
|
48
|
+
See: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md
|
|
49
|
+
|
|
50
|
+
Required Attributes:
|
|
51
|
+
- id: Unique identifier for the event
|
|
52
|
+
- source: Context in which the event happened (URI-reference)
|
|
53
|
+
- specversion: CloudEvents specification version
|
|
54
|
+
- type: Type of event (reverse-DNS naming recommended)
|
|
55
|
+
|
|
56
|
+
Optional Attributes:
|
|
57
|
+
- datacontenttype: Content type of data
|
|
58
|
+
- dataschema: Schema that data adheres to
|
|
59
|
+
- subject: Subject of the event in the context of the producer
|
|
60
|
+
- time: Timestamp of when the event happened
|
|
61
|
+
- data: Event payload
|
|
62
|
+
|
|
63
|
+
Extension Attributes (Agent OS specific):
|
|
64
|
+
- priority: Message priority (amb extension)
|
|
65
|
+
- traceid: Distributed trace ID (amb extension)
|
|
66
|
+
- spanid: Span ID for tracing (amb extension)
|
|
67
|
+
- parentspanid: Parent span ID (amb extension)
|
|
68
|
+
- ttl: Time-to-live in seconds (amb extension)
|
|
69
|
+
- sender: Sender identifier (amb extension)
|
|
70
|
+
- correlationid: Correlation ID for request-response (amb extension)
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
# Required attributes (CloudEvents spec)
|
|
74
|
+
id: str = Field(..., description="Unique identifier for the event")
|
|
75
|
+
source: str = Field(..., description="URI-reference identifying the context")
|
|
76
|
+
specversion: str = Field(default=CLOUDEVENTS_SPEC_VERSION, description="CloudEvents spec version")
|
|
77
|
+
type: str = Field(..., description="Event type (reverse-DNS naming)")
|
|
78
|
+
|
|
79
|
+
# Optional attributes (CloudEvents spec)
|
|
80
|
+
datacontenttype: Optional[str] = Field(
|
|
81
|
+
default="application/json",
|
|
82
|
+
description="Content type of the data attribute"
|
|
83
|
+
)
|
|
84
|
+
dataschema: Optional[str] = Field(
|
|
85
|
+
None,
|
|
86
|
+
description="URI identifying the schema that data adheres to"
|
|
87
|
+
)
|
|
88
|
+
subject: Optional[str] = Field(
|
|
89
|
+
None,
|
|
90
|
+
description="Subject of the event in the context of the event producer"
|
|
91
|
+
)
|
|
92
|
+
time: Optional[datetime] = Field(
|
|
93
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
94
|
+
description="Timestamp of when the event happened (RFC 3339)"
|
|
95
|
+
)
|
|
96
|
+
data: Optional[Dict[str, Any]] = Field(
|
|
97
|
+
default_factory=dict,
|
|
98
|
+
description="Event payload"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Extension attributes (Agent OS / AMB specific)
|
|
102
|
+
# Prefixed with 'amb' namespace per CloudEvents extension naming conventions
|
|
103
|
+
ambpriority: Optional[int] = Field(
|
|
104
|
+
None,
|
|
105
|
+
description="Message priority (AMB extension)"
|
|
106
|
+
)
|
|
107
|
+
ambtraceid: Optional[str] = Field(
|
|
108
|
+
None,
|
|
109
|
+
description="Distributed trace ID (AMB extension)"
|
|
110
|
+
)
|
|
111
|
+
ambspanid: Optional[str] = Field(
|
|
112
|
+
None,
|
|
113
|
+
description="Span ID within the trace (AMB extension)"
|
|
114
|
+
)
|
|
115
|
+
ambparentspanid: Optional[str] = Field(
|
|
116
|
+
None,
|
|
117
|
+
description="Parent span ID (AMB extension)"
|
|
118
|
+
)
|
|
119
|
+
ambttl: Optional[int] = Field(
|
|
120
|
+
None,
|
|
121
|
+
description="Time-to-live in seconds (AMB extension)"
|
|
122
|
+
)
|
|
123
|
+
ambsender: Optional[str] = Field(
|
|
124
|
+
None,
|
|
125
|
+
description="Sender identifier (AMB extension)"
|
|
126
|
+
)
|
|
127
|
+
ambcorrelationid: Optional[str] = Field(
|
|
128
|
+
None,
|
|
129
|
+
description="Correlation ID for request-response patterns (AMB extension)"
|
|
130
|
+
)
|
|
131
|
+
ambreplyto: Optional[str] = Field(
|
|
132
|
+
None,
|
|
133
|
+
description="Topic to reply to (AMB extension)"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
model_config = ConfigDict(
|
|
137
|
+
json_encoders={
|
|
138
|
+
datetime: lambda v: v.isoformat() if v else None
|
|
139
|
+
},
|
|
140
|
+
extra="allow", # Allow additional extension attributes
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
@field_validator('specversion')
|
|
144
|
+
@classmethod
|
|
145
|
+
def validate_specversion(cls, v: str) -> str:
|
|
146
|
+
"""Validate CloudEvents spec version."""
|
|
147
|
+
if v != CLOUDEVENTS_SPEC_VERSION:
|
|
148
|
+
raise ValueError(f"Unsupported specversion: {v}. Expected: {CLOUDEVENTS_SPEC_VERSION}")
|
|
149
|
+
return v
|
|
150
|
+
|
|
151
|
+
@field_validator('source')
|
|
152
|
+
@classmethod
|
|
153
|
+
def validate_source(cls, v: str) -> str:
|
|
154
|
+
"""Validate source is a URI-reference."""
|
|
155
|
+
if not v:
|
|
156
|
+
raise ValueError("source cannot be empty")
|
|
157
|
+
return v
|
|
158
|
+
|
|
159
|
+
@field_validator('type')
|
|
160
|
+
@classmethod
|
|
161
|
+
def validate_type(cls, v: str) -> str:
|
|
162
|
+
"""Validate type is non-empty."""
|
|
163
|
+
if not v:
|
|
164
|
+
raise ValueError("type cannot be empty")
|
|
165
|
+
return v
|
|
166
|
+
|
|
167
|
+
def to_json(self, **kwargs) -> str:
|
|
168
|
+
"""
|
|
169
|
+
Serialize to CloudEvents JSON format (structured content mode).
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
JSON string representation
|
|
173
|
+
"""
|
|
174
|
+
return self.model_dump_json(exclude_none=True, **kwargs)
|
|
175
|
+
|
|
176
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
177
|
+
"""
|
|
178
|
+
Convert to dictionary (excludes None values).
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Dictionary representation
|
|
182
|
+
"""
|
|
183
|
+
return self.model_dump(exclude_none=True)
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def from_json(cls, json_str: str) -> "CloudEvent":
|
|
187
|
+
"""
|
|
188
|
+
Parse from CloudEvents JSON format.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
json_str: JSON string to parse
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
CloudEvent instance
|
|
195
|
+
"""
|
|
196
|
+
data = json.loads(json_str)
|
|
197
|
+
return cls.model_validate(data)
|
|
198
|
+
|
|
199
|
+
@classmethod
|
|
200
|
+
def from_dict(cls, data: Dict[str, Any]) -> "CloudEvent":
|
|
201
|
+
"""
|
|
202
|
+
Create from dictionary.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
data: Dictionary with CloudEvent attributes
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
CloudEvent instance
|
|
209
|
+
"""
|
|
210
|
+
return cls.model_validate(data)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def topic_to_type(topic: str, prefix: str = AGENT_OS_TYPE_PREFIX) -> str:
|
|
214
|
+
"""
|
|
215
|
+
Convert an AMB topic to a CloudEvents type.
|
|
216
|
+
|
|
217
|
+
CloudEvents recommends reverse-DNS naming for types.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
topic: AMB topic (e.g., "fraud.alerts")
|
|
221
|
+
prefix: Type prefix (default: "dev.agent-os")
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
CloudEvents type (e.g., "dev.agent-os.fraud.alerts")
|
|
225
|
+
|
|
226
|
+
Example:
|
|
227
|
+
>>> topic_to_type("fraud.alerts")
|
|
228
|
+
"dev.agent-os.fraud.alerts"
|
|
229
|
+
"""
|
|
230
|
+
return f"{prefix}.{topic}"
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def type_to_topic(event_type: str, prefix: str = AGENT_OS_TYPE_PREFIX) -> str:
|
|
234
|
+
"""
|
|
235
|
+
Convert a CloudEvents type back to an AMB topic.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
event_type: CloudEvents type (e.g., "dev.agent-os.fraud.alerts")
|
|
239
|
+
prefix: Type prefix to strip (default: "dev.agent-os")
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
AMB topic (e.g., "fraud.alerts")
|
|
243
|
+
|
|
244
|
+
Example:
|
|
245
|
+
>>> type_to_topic("dev.agent-os.fraud.alerts")
|
|
246
|
+
"fraud.alerts"
|
|
247
|
+
"""
|
|
248
|
+
full_prefix = f"{prefix}."
|
|
249
|
+
if event_type.startswith(full_prefix):
|
|
250
|
+
return event_type[len(full_prefix):]
|
|
251
|
+
return event_type
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def to_cloudevent(
|
|
255
|
+
message: Message,
|
|
256
|
+
source: str,
|
|
257
|
+
*,
|
|
258
|
+
type_prefix: str = AGENT_OS_TYPE_PREFIX,
|
|
259
|
+
dataschema: Optional[str] = None
|
|
260
|
+
) -> CloudEvent:
|
|
261
|
+
"""
|
|
262
|
+
Convert an AMB Message to a CloudEvent.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
message: AMB Message to convert
|
|
266
|
+
source: CloudEvents source URI (identifies the event producer)
|
|
267
|
+
type_prefix: Prefix for the event type (default: "dev.agent-os")
|
|
268
|
+
dataschema: Optional URI of the data schema
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
CloudEvent instance
|
|
272
|
+
|
|
273
|
+
Example:
|
|
274
|
+
message = Message(
|
|
275
|
+
id="msg-123",
|
|
276
|
+
topic="fraud.alerts",
|
|
277
|
+
payload={"transaction_id": "tx-456", "risk_score": 0.95},
|
|
278
|
+
priority=Priority.CRITICAL,
|
|
279
|
+
sender="fraud-detector"
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
event = to_cloudevent(message, source="/agent-os/fraud-detector")
|
|
283
|
+
# Result:
|
|
284
|
+
# {
|
|
285
|
+
# "specversion": "1.0",
|
|
286
|
+
# "id": "msg-123",
|
|
287
|
+
# "source": "/agent-os/fraud-detector",
|
|
288
|
+
# "type": "dev.agent-os.fraud.alerts",
|
|
289
|
+
# "datacontenttype": "application/json",
|
|
290
|
+
# "time": "2026-02-03T04:30:00Z",
|
|
291
|
+
# "data": {"transaction_id": "tx-456", "risk_score": 0.95},
|
|
292
|
+
# "ambpriority": 15,
|
|
293
|
+
# "ambsender": "fraud-detector"
|
|
294
|
+
# }
|
|
295
|
+
"""
|
|
296
|
+
return CloudEvent(
|
|
297
|
+
id=message.id,
|
|
298
|
+
source=source,
|
|
299
|
+
type=topic_to_type(message.topic, type_prefix),
|
|
300
|
+
subject=message.topic, # Original topic as subject
|
|
301
|
+
time=message.timestamp,
|
|
302
|
+
data=message.payload,
|
|
303
|
+
dataschema=dataschema,
|
|
304
|
+
|
|
305
|
+
# AMB extensions
|
|
306
|
+
ambpriority=message.priority.value if message.priority else None,
|
|
307
|
+
ambtraceid=message.trace_id,
|
|
308
|
+
ambspanid=message.span_id,
|
|
309
|
+
ambparentspanid=message.parent_span_id,
|
|
310
|
+
ambttl=message.ttl,
|
|
311
|
+
ambsender=message.sender,
|
|
312
|
+
ambcorrelationid=message.correlation_id,
|
|
313
|
+
ambreplyto=message.reply_to,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def from_cloudevent(
|
|
318
|
+
event: CloudEvent,
|
|
319
|
+
*,
|
|
320
|
+
type_prefix: str = AGENT_OS_TYPE_PREFIX
|
|
321
|
+
) -> Message:
|
|
322
|
+
"""
|
|
323
|
+
Convert a CloudEvent to an AMB Message.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
event: CloudEvent to convert
|
|
327
|
+
type_prefix: Prefix to strip from event type (default: "dev.agent-os")
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
AMB Message instance
|
|
331
|
+
|
|
332
|
+
Example:
|
|
333
|
+
event = CloudEvent(
|
|
334
|
+
id="evt-123",
|
|
335
|
+
source="/external-system",
|
|
336
|
+
type="dev.agent-os.user.events",
|
|
337
|
+
data={"user_id": "u-456", "action": "login"}
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
message = from_cloudevent(event)
|
|
341
|
+
# message.topic == "user.events"
|
|
342
|
+
# message.payload == {"user_id": "u-456", "action": "login"}
|
|
343
|
+
"""
|
|
344
|
+
# Determine topic from type or subject
|
|
345
|
+
topic = event.subject or type_to_topic(event.type, type_prefix)
|
|
346
|
+
|
|
347
|
+
# Map priority
|
|
348
|
+
priority = MessagePriority.NORMAL
|
|
349
|
+
if event.ambpriority is not None:
|
|
350
|
+
try:
|
|
351
|
+
priority = MessagePriority(event.ambpriority)
|
|
352
|
+
except ValueError:
|
|
353
|
+
# Use closest valid priority
|
|
354
|
+
if event.ambpriority >= MessagePriority.CRITICAL:
|
|
355
|
+
priority = MessagePriority.CRITICAL
|
|
356
|
+
elif event.ambpriority >= MessagePriority.URGENT:
|
|
357
|
+
priority = MessagePriority.URGENT
|
|
358
|
+
elif event.ambpriority >= MessagePriority.HIGH:
|
|
359
|
+
priority = MessagePriority.HIGH
|
|
360
|
+
elif event.ambpriority >= MessagePriority.NORMAL:
|
|
361
|
+
priority = MessagePriority.NORMAL
|
|
362
|
+
elif event.ambpriority >= MessagePriority.LOW:
|
|
363
|
+
priority = MessagePriority.LOW
|
|
364
|
+
else:
|
|
365
|
+
priority = MessagePriority.BACKGROUND
|
|
366
|
+
|
|
367
|
+
return Message(
|
|
368
|
+
id=event.id,
|
|
369
|
+
topic=topic,
|
|
370
|
+
payload=event.data or {},
|
|
371
|
+
priority=priority,
|
|
372
|
+
timestamp=event.time or datetime.now(timezone.utc),
|
|
373
|
+
sender=event.ambsender,
|
|
374
|
+
correlation_id=event.ambcorrelationid,
|
|
375
|
+
reply_to=event.ambreplyto,
|
|
376
|
+
ttl=event.ambttl,
|
|
377
|
+
trace_id=event.ambtraceid,
|
|
378
|
+
span_id=event.ambspanid,
|
|
379
|
+
parent_span_id=event.ambparentspanid,
|
|
380
|
+
metadata={
|
|
381
|
+
"cloudevents.source": event.source,
|
|
382
|
+
"cloudevents.type": event.type,
|
|
383
|
+
"cloudevents.dataschema": event.dataschema,
|
|
384
|
+
}
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class CloudEventBatch(BaseModel):
|
|
389
|
+
"""
|
|
390
|
+
Batch of CloudEvents for bulk transmission.
|
|
391
|
+
|
|
392
|
+
CloudEvents batching spec: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/formats/json-format.md#4-json-batch-format
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
events: list[CloudEvent] = Field(default_factory=list)
|
|
396
|
+
|
|
397
|
+
def to_json(self) -> str:
|
|
398
|
+
"""Serialize batch to JSON array."""
|
|
399
|
+
def serialize_event(e: CloudEvent) -> Dict[str, Any]:
|
|
400
|
+
d = e.to_dict()
|
|
401
|
+
# Convert datetime to ISO format
|
|
402
|
+
if "time" in d and isinstance(d["time"], datetime):
|
|
403
|
+
d["time"] = d["time"].isoformat()
|
|
404
|
+
return d
|
|
405
|
+
|
|
406
|
+
return json.dumps([serialize_event(e) for e in self.events])
|
|
407
|
+
|
|
408
|
+
@classmethod
|
|
409
|
+
def from_json(cls, json_str: str) -> "CloudEventBatch":
|
|
410
|
+
"""Parse batch from JSON array."""
|
|
411
|
+
data = json.loads(json_str)
|
|
412
|
+
events = [CloudEvent.from_dict(e) for e in data]
|
|
413
|
+
return cls(events=events)
|
|
414
|
+
|
|
415
|
+
def __len__(self) -> int:
|
|
416
|
+
return len(self.events)
|
|
417
|
+
|
|
418
|
+
def __iter__(self):
|
|
419
|
+
return iter(self.events)
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
# HTTP binding headers for CloudEvents
|
|
423
|
+
# See: https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/bindings/http-protocol-binding.md
|
|
424
|
+
HTTP_HEADERS = {
|
|
425
|
+
"id": "ce-id",
|
|
426
|
+
"source": "ce-source",
|
|
427
|
+
"specversion": "ce-specversion",
|
|
428
|
+
"type": "ce-type",
|
|
429
|
+
"datacontenttype": "content-type",
|
|
430
|
+
"dataschema": "ce-dataschema",
|
|
431
|
+
"subject": "ce-subject",
|
|
432
|
+
"time": "ce-time",
|
|
433
|
+
# AMB extensions
|
|
434
|
+
"ambpriority": "ce-ambpriority",
|
|
435
|
+
"ambtraceid": "ce-ambtraceid",
|
|
436
|
+
"ambspanid": "ce-ambspanid",
|
|
437
|
+
"ambparentspanid": "ce-ambparentspanid",
|
|
438
|
+
"ambttl": "ce-ambttl",
|
|
439
|
+
"ambsender": "ce-ambsender",
|
|
440
|
+
"ambcorrelationid": "ce-ambcorrelationid",
|
|
441
|
+
"ambreplyto": "ce-ambreplyto",
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
def to_http_headers(event: CloudEvent) -> Dict[str, str]:
|
|
446
|
+
"""
|
|
447
|
+
Convert CloudEvent to HTTP headers (binary content mode).
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
event: CloudEvent to convert
|
|
451
|
+
|
|
452
|
+
Returns:
|
|
453
|
+
Dictionary of HTTP headers
|
|
454
|
+
|
|
455
|
+
Example:
|
|
456
|
+
headers = to_http_headers(event)
|
|
457
|
+
# {
|
|
458
|
+
# "ce-id": "msg-123",
|
|
459
|
+
# "ce-source": "/agent-os/detector",
|
|
460
|
+
# "ce-type": "dev.agent-os.fraud.alerts",
|
|
461
|
+
# "ce-specversion": "1.0",
|
|
462
|
+
# "content-type": "application/json",
|
|
463
|
+
# ...
|
|
464
|
+
# }
|
|
465
|
+
"""
|
|
466
|
+
headers = {}
|
|
467
|
+
event_dict = event.to_dict()
|
|
468
|
+
|
|
469
|
+
for attr, header in HTTP_HEADERS.items():
|
|
470
|
+
if attr in event_dict and event_dict[attr] is not None:
|
|
471
|
+
value = event_dict[attr]
|
|
472
|
+
if isinstance(value, datetime):
|
|
473
|
+
value = value.isoformat()
|
|
474
|
+
elif not isinstance(value, str):
|
|
475
|
+
value = str(value)
|
|
476
|
+
headers[header] = value
|
|
477
|
+
|
|
478
|
+
return headers
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def from_http_headers(headers: Dict[str, str], data: Optional[Dict[str, Any]] = None) -> CloudEvent:
|
|
482
|
+
"""
|
|
483
|
+
Create CloudEvent from HTTP headers (binary content mode).
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
headers: HTTP headers (case-insensitive)
|
|
487
|
+
data: Request body as parsed JSON
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
CloudEvent instance
|
|
491
|
+
"""
|
|
492
|
+
# Normalize header names to lowercase
|
|
493
|
+
normalized = {k.lower(): v for k, v in headers.items()}
|
|
494
|
+
|
|
495
|
+
# Reverse mapping
|
|
496
|
+
header_to_attr = {v.lower(): k for k, v in HTTP_HEADERS.items()}
|
|
497
|
+
|
|
498
|
+
event_data = {}
|
|
499
|
+
for header, value in normalized.items():
|
|
500
|
+
if header in header_to_attr:
|
|
501
|
+
attr = header_to_attr[header]
|
|
502
|
+
# Convert types as needed
|
|
503
|
+
if attr in ("ambpriority", "ambttl"):
|
|
504
|
+
value = int(value)
|
|
505
|
+
event_data[attr] = value
|
|
506
|
+
|
|
507
|
+
event_data["data"] = data
|
|
508
|
+
|
|
509
|
+
return CloudEvent.from_dict(event_data)
|