coreason-manifest 0.6.0__py3-none-any.whl → 0.7.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.
@@ -1,79 +1,17 @@
1
- # Prosperity-3.0
2
- """Coreason Manifest Package.
3
-
4
- This package provides the core functionality for the Coreason Manifest system,
5
- including loading, validation, policy enforcement, and integrity checking of
6
- agent definitions.
7
-
8
- The `coreason-manifest` package serves as the definitive source of truth for
9
- Asset definitions in the CoReason-AI ecosystem.
10
-
11
- Usage:
12
- from coreason_manifest import ManifestEngine, ManifestConfig
13
-
14
- config = ManifestConfig(policy_path="./policies/gx_compliant.rego")
15
- engine = ManifestEngine(config)
16
- agent_def = engine.load_and_validate("agent.yaml", "./src")
17
- """
18
-
19
- from .engine import ManifestConfig, ManifestEngine, ManifestEngineAsync
20
- from .errors import (
21
- IntegrityCompromisedError,
22
- ManifestError,
23
- ManifestSyntaxError,
24
- PolicyViolationError,
25
- )
26
- from .integrity import IntegrityChecker
27
- from .loader import ManifestLoader
28
- from .models import (
29
- AgentDefinition,
30
- AgentDependencies,
31
- AgentInterface,
32
- AgentMetadata,
33
- AgentTopology,
34
- ModelConfig,
35
- Step,
36
- )
37
- from .policy import PolicyEnforcer
38
- from .recipes import (
39
- AgentNode,
40
- CouncilConfig,
41
- Edge,
42
- GraphTopology,
43
- HumanNode,
44
- LogicNode,
45
- Node,
46
- RecipeManifest,
47
- VisualMetadata,
48
- )
49
- from .validator import SchemaValidator
1
+ from .definitions.agent import AgentDefinition
2
+ from .definitions.audit import AuditLog
3
+ from .definitions.simulation import SimulationScenario, SimulationTrace, SimulationTurn
4
+ from .definitions.topology import Edge, Node, Topology
5
+ from .recipes import RecipeManifest
50
6
 
51
7
  __all__ = [
52
8
  "AgentDefinition",
53
- "AgentDependencies",
54
- "AgentInterface",
55
- "AgentMetadata",
56
- "AgentNode",
57
- "AgentTopology",
58
- "CouncilConfig",
59
- "Edge",
60
- "GraphTopology",
61
- "HumanNode",
62
- "IntegrityChecker",
63
- "IntegrityCompromisedError",
64
- "LogicNode",
65
- "ManifestConfig",
66
- "ManifestEngine",
67
- "ManifestEngineAsync",
68
- "ManifestError",
69
- "ManifestLoader",
70
- "ManifestSyntaxError",
71
- "ModelConfig",
9
+ "Topology",
72
10
  "Node",
73
- "PolicyEnforcer",
74
- "PolicyViolationError",
11
+ "Edge",
12
+ "SimulationScenario",
13
+ "SimulationTrace",
14
+ "SimulationTurn",
15
+ "AuditLog",
75
16
  "RecipeManifest",
76
- "SchemaValidator",
77
- "Step",
78
- "VisualMetadata",
79
17
  ]
File without changes
@@ -0,0 +1,7 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class AuditLog(BaseModel):
5
+ """Audit log entry."""
6
+
7
+ pass
@@ -0,0 +1,19 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class SimulationScenario(BaseModel):
5
+ """Definition of a simulation scenario."""
6
+
7
+ pass
8
+
9
+
10
+ class SimulationTrace(BaseModel):
11
+ """Trace of a simulation execution."""
12
+
13
+ pass
14
+
15
+
16
+ class SimulationTurn(BaseModel):
17
+ """A single turn in a simulation."""
18
+
19
+ pass
@@ -0,0 +1,140 @@
1
+ # Copyright (c) 2025 CoReason, Inc.
2
+ #
3
+ # This software is proprietary and dual-licensed.
4
+ # Licensed under the Prosperity Public License 3.0 (the "License").
5
+ # A copy of the license is available at https://prosperitylicense.com/versions/3.0.0
6
+ # For details, see the LICENSE file.
7
+ # Commercial use beyond a 30-day trial requires a separate license.
8
+ #
9
+ # Source Code: https://github.com/CoReason-AI/coreason_maco
10
+
11
+ from typing import Annotated, List, Literal, Optional, Union
12
+
13
+ from pydantic import BaseModel, ConfigDict, Field
14
+
15
+
16
+ class CouncilConfig(BaseModel):
17
+ """Configuration for 'Architectural Triangulation'.
18
+
19
+ Attributes:
20
+ strategy: The strategy for the council (e.g., 'consensus').
21
+ voters: List of agents or models that vote.
22
+ """
23
+
24
+ model_config = ConfigDict(extra="forbid")
25
+
26
+ strategy: str = Field(default="consensus", description="The strategy for the council, e.g., 'consensus'.")
27
+ voters: List[str] = Field(..., description="List of agents or models that vote.")
28
+
29
+
30
+ class VisualMetadata(BaseModel):
31
+ """Data explicitly for the UI.
32
+
33
+ Attributes:
34
+ label: The label to display for the node.
35
+ x_y_coordinates: The X and Y coordinates for the node on the canvas.
36
+ icon: The icon to represent the node.
37
+ animation_style: The animation style for the node.
38
+ """
39
+
40
+ model_config = ConfigDict(extra="forbid")
41
+
42
+ label: Optional[str] = Field(None, description="The label to display for the node.")
43
+ x_y_coordinates: Optional[List[float]] = Field(
44
+ None, description="The X and Y coordinates for the node on the canvas."
45
+ )
46
+ icon: Optional[str] = Field(None, description="The icon to represent the node.")
47
+ animation_style: Optional[str] = Field(None, description="The animation style for the node.")
48
+
49
+
50
+ class BaseNode(BaseModel):
51
+ """Base model for all node types.
52
+
53
+ Attributes:
54
+ id: Unique identifier for the node.
55
+ council_config: Optional configuration for architectural triangulation.
56
+ visual: Visual metadata for the UI.
57
+ """
58
+
59
+ model_config = ConfigDict(extra="forbid")
60
+
61
+ id: str = Field(..., description="Unique identifier for the node.")
62
+ council_config: Optional[CouncilConfig] = Field(
63
+ None, description="Optional configuration for architectural triangulation."
64
+ )
65
+ visual: Optional[VisualMetadata] = Field(None, description="Visual metadata for the UI.")
66
+
67
+
68
+ class AgentNode(BaseNode):
69
+ """A node that calls a specific atomic agent.
70
+
71
+ Attributes:
72
+ type: The type of the node (must be 'agent').
73
+ agent_name: The name of the atomic agent to call.
74
+ """
75
+
76
+ type: Literal["agent"] = Field("agent", description="Discriminator for AgentNode.")
77
+ agent_name: str = Field(..., description="The name of the atomic agent to call.")
78
+
79
+
80
+ class HumanNode(BaseNode):
81
+ """A node that pauses execution for user input/approval.
82
+
83
+ Attributes:
84
+ type: The type of the node (must be 'human').
85
+ timeout_seconds: Optional timeout in seconds for the user interaction.
86
+ """
87
+
88
+ type: Literal["human"] = Field("human", description="Discriminator for HumanNode.")
89
+ timeout_seconds: Optional[int] = Field(None, description="Optional timeout in seconds for the user interaction.")
90
+
91
+
92
+ class LogicNode(BaseNode):
93
+ """A node that executes pure Python logic.
94
+
95
+ Attributes:
96
+ type: The type of the node (must be 'logic').
97
+ code: The Python logic code to execute.
98
+ """
99
+
100
+ type: Literal["logic"] = Field("logic", description="Discriminator for LogicNode.")
101
+ code: str = Field(..., description="The Python logic code to execute.")
102
+
103
+
104
+ # Discriminated Union for polymorphism
105
+ Node = Annotated[
106
+ Union[AgentNode, HumanNode, LogicNode], Field(discriminator="type", description="Polymorphic node definition.")
107
+ ]
108
+
109
+
110
+ class Edge(BaseModel):
111
+ """Represents a connection between two nodes.
112
+
113
+ Attributes:
114
+ source_node_id: The ID of the source node.
115
+ target_node_id: The ID of the target node.
116
+ condition: Optional Python expression for conditional branching.
117
+ """
118
+
119
+ model_config = ConfigDict(extra="forbid")
120
+
121
+ source_node_id: str = Field(..., description="The ID of the source node.")
122
+ target_node_id: str = Field(..., description="The ID of the target node.")
123
+ condition: Optional[str] = Field(None, description="Optional Python expression for conditional branching.")
124
+
125
+
126
+ class GraphTopology(BaseModel):
127
+ """The topology definition of the recipe.
128
+
129
+ Attributes:
130
+ nodes: List of nodes in the graph.
131
+ edges: List of edges connecting the nodes.
132
+ """
133
+
134
+ model_config = ConfigDict(extra="forbid")
135
+
136
+ nodes: List[Node] = Field(..., description="List of nodes in the graph.")
137
+ edges: List[Edge] = Field(..., description="List of edges connecting the nodes.")
138
+
139
+
140
+ Topology = GraphTopology
@@ -8,135 +8,12 @@
8
8
  #
9
9
  # Source Code: https://github.com/CoReason-AI/coreason_maco
10
10
 
11
- from typing import Annotated, Any, Dict, List, Literal, Optional, Union
11
+ from typing import Any, Dict, Optional
12
12
 
13
13
  from pydantic import BaseModel, ConfigDict, Field
14
14
 
15
- from .models import VersionStr
16
-
17
-
18
- class CouncilConfig(BaseModel):
19
- """Configuration for 'Architectural Triangulation'.
20
-
21
- Attributes:
22
- strategy: The strategy for the council (e.g., 'consensus').
23
- voters: List of agents or models that vote.
24
- """
25
-
26
- model_config = ConfigDict(extra="forbid")
27
-
28
- strategy: str = Field(default="consensus", description="The strategy for the council, e.g., 'consensus'.")
29
- voters: List[str] = Field(..., description="List of agents or models that vote.")
30
-
31
-
32
- class VisualMetadata(BaseModel):
33
- """Data explicitly for the UI.
34
-
35
- Attributes:
36
- label: The label to display for the node.
37
- x_y_coordinates: The X and Y coordinates for the node on the canvas.
38
- icon: The icon to represent the node.
39
- animation_style: The animation style for the node.
40
- """
41
-
42
- model_config = ConfigDict(extra="forbid")
43
-
44
- label: Optional[str] = Field(None, description="The label to display for the node.")
45
- x_y_coordinates: Optional[List[float]] = Field(
46
- None, description="The X and Y coordinates for the node on the canvas."
47
- )
48
- icon: Optional[str] = Field(None, description="The icon to represent the node.")
49
- animation_style: Optional[str] = Field(None, description="The animation style for the node.")
50
-
51
-
52
- class BaseNode(BaseModel):
53
- """Base model for all node types.
54
-
55
- Attributes:
56
- id: Unique identifier for the node.
57
- council_config: Optional configuration for architectural triangulation.
58
- visual: Visual metadata for the UI.
59
- """
60
-
61
- model_config = ConfigDict(extra="forbid")
62
-
63
- id: str = Field(..., description="Unique identifier for the node.")
64
- council_config: Optional[CouncilConfig] = Field(
65
- None, description="Optional configuration for architectural triangulation."
66
- )
67
- visual: Optional[VisualMetadata] = Field(None, description="Visual metadata for the UI.")
68
-
69
-
70
- class AgentNode(BaseNode):
71
- """A node that calls a specific atomic agent.
72
-
73
- Attributes:
74
- type: The type of the node (must be 'agent').
75
- agent_name: The name of the atomic agent to call.
76
- """
77
-
78
- type: Literal["agent"] = Field("agent", description="Discriminator for AgentNode.")
79
- agent_name: str = Field(..., description="The name of the atomic agent to call.")
80
-
81
-
82
- class HumanNode(BaseNode):
83
- """A node that pauses execution for user input/approval.
84
-
85
- Attributes:
86
- type: The type of the node (must be 'human').
87
- timeout_seconds: Optional timeout in seconds for the user interaction.
88
- """
89
-
90
- type: Literal["human"] = Field("human", description="Discriminator for HumanNode.")
91
- timeout_seconds: Optional[int] = Field(None, description="Optional timeout in seconds for the user interaction.")
92
-
93
-
94
- class LogicNode(BaseNode):
95
- """A node that executes pure Python logic.
96
-
97
- Attributes:
98
- type: The type of the node (must be 'logic').
99
- code: The Python logic code to execute.
100
- """
101
-
102
- type: Literal["logic"] = Field("logic", description="Discriminator for LogicNode.")
103
- code: str = Field(..., description="The Python logic code to execute.")
104
-
105
-
106
- # Discriminated Union for polymorphism
107
- Node = Annotated[
108
- Union[AgentNode, HumanNode, LogicNode], Field(discriminator="type", description="Polymorphic node definition.")
109
- ]
110
-
111
-
112
- class Edge(BaseModel):
113
- """Represents a connection between two nodes.
114
-
115
- Attributes:
116
- source_node_id: The ID of the source node.
117
- target_node_id: The ID of the target node.
118
- condition: Optional Python expression for conditional branching.
119
- """
120
-
121
- model_config = ConfigDict(extra="forbid")
122
-
123
- source_node_id: str = Field(..., description="The ID of the source node.")
124
- target_node_id: str = Field(..., description="The ID of the target node.")
125
- condition: Optional[str] = Field(None, description="Optional Python expression for conditional branching.")
126
-
127
-
128
- class GraphTopology(BaseModel):
129
- """The topology definition of the recipe.
130
-
131
- Attributes:
132
- nodes: List of nodes in the graph.
133
- edges: List of edges connecting the nodes.
134
- """
135
-
136
- model_config = ConfigDict(extra="forbid")
137
-
138
- nodes: List[Node] = Field(..., description="List of nodes in the graph.")
139
- edges: List[Edge] = Field(..., description="List of edges connecting the nodes.")
15
+ from .definitions.agent import VersionStr
16
+ from .definitions.topology import GraphTopology
140
17
 
141
18
 
142
19
  class RecipeManifest(BaseModel):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coreason_manifest
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: This package is the definitive source of truth. If it isn't in the manifest, it doesn't exist. If it violates the manifest, it doesn't run.
5
5
  License: # The Prosperity Public License 3.0.0
6
6
 
@@ -67,16 +67,10 @@ Requires-Python: >=3.12
67
67
  Classifier: License :: Other/Proprietary License
68
68
  Classifier: Programming Language :: Python :: 3.12
69
69
  Classifier: Operating System :: OS Independent
70
- Requires-Dist: aiofiles (>=23.2.1,<24.0.0)
71
- Requires-Dist: anyio (>=4.12.1,<5.0.0)
72
70
  Requires-Dist: coreason-identity (>=0.4.1,<0.5.0)
73
- Requires-Dist: fastapi (>=0.128.0,<0.129.0)
74
- Requires-Dist: httpx (>=0.28.1,<0.29.0)
75
- Requires-Dist: jsonschema (>=4.26.0,<5.0.0)
76
71
  Requires-Dist: loguru (>=0.7.2,<0.8.0)
77
72
  Requires-Dist: pydantic (>=2.12.5,<3.0.0)
78
73
  Requires-Dist: pyyaml (>=6.0.3,<7.0.0)
79
- Requires-Dist: uvicorn (>=0.40.0,<0.41.0)
80
74
  Project-URL: Documentation, https://github.com/CoReason-AI/coreason_manifest
81
75
  Project-URL: Homepage, https://github.com/CoReason-AI/coreason_manifest
82
76
  Project-URL: Repository, https://github.com/CoReason-AI/coreason_manifest
@@ -0,0 +1,16 @@
1
+ coreason_manifest/__init__.py,sha256=SNFD_w_XEalq8Mo6AEQNYsI-KEUkC9hf5r7d2jv-21k,453
2
+ coreason_manifest/definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ coreason_manifest/definitions/agent.py,sha256=EuaE1Wl5T8f_eI9vF1VFp5hd0y9C7E52zAjB52EulKw,7497
4
+ coreason_manifest/definitions/audit.py,sha256=_wWZN7sBlxVESrIPXFILit-6QWH6BCUQ1UGCAkxBlgI,97
5
+ coreason_manifest/definitions/simulation.py,sha256=grC1_UeJc7l-IpgBuQhIuyKn22ZtgsoTk3FRRXE-NOo,302
6
+ coreason_manifest/definitions/topology.py,sha256=a7pdCyvtVCFEewKehH58is55_2PCJC1C7yldCV2tdxM,4825
7
+ coreason_manifest/recipes.py,sha256=ti17QdH6RhZbeve8jhROJgEkD-3GYOFoTk5pe3Ok_0I,1598
8
+ coreason_manifest/schemas/__init__.py,sha256=9TMs6jWKCIewAKkj-u0tq9c6N_-0CU6b5s9q6MTS6v4,17
9
+ coreason_manifest/schemas/agent.schema.json,sha256=VigUX3ltX7YaW9P7n0DNYGNOf8C6VCuXNy71u3LB9i4,6812
10
+ coreason_manifest/utils/__init__.py,sha256=Q9gXiBtX3mD9GTu4z0JDHSHkbXC-MRHagrOaOmRH_1Q,435
11
+ coreason_manifest/utils/logger.py,sha256=A7E6Hd_Jk1XDUajNEJQl-WtUv9M2LT76b4_TsbxnILw,1227
12
+ coreason_manifest-0.7.0.dist-info/METADATA,sha256=J4MUZyT1RTEnZRoOPgVK_sISJ8CeU24kdkdL47E21Oo,7169
13
+ coreason_manifest-0.7.0.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
14
+ coreason_manifest-0.7.0.dist-info/licenses/LICENSE,sha256=3tYb7ZQe7sVXcbNmX22fDESFjOSIlCZodUGpZMkuSlk,3063
15
+ coreason_manifest-0.7.0.dist-info/licenses/NOTICE,sha256=tqzUyP9VTCGxoHLgBI0AC1i0G7m_PSyESFL8Jwuw0dA,610
16
+ coreason_manifest-0.7.0.dist-info/RECORD,,
@@ -1,222 +0,0 @@
1
- # Prosperity-3.0
2
- """Engine for the Coreason Manifest system.
3
-
4
- This module provides the main entry point for verifying and loading Agent Manifests.
5
- It coordinates schema validation, policy enforcement, and integrity checking.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import time
11
- from dataclasses import dataclass, field
12
- from pathlib import Path
13
- from typing import Any, List, Optional, Union, cast
14
-
15
- import anyio
16
- import anyio.to_thread
17
-
18
- from coreason_manifest.integrity import IntegrityChecker
19
- from coreason_manifest.loader import ManifestLoader
20
- from coreason_manifest.models import AgentDefinition
21
- from coreason_manifest.policy import PolicyEnforcer
22
- from coreason_manifest.utils.logger import logger
23
- from coreason_manifest.validator import SchemaValidator
24
-
25
-
26
- @dataclass
27
- class ManifestConfig:
28
- """Configuration for the ManifestEngine.
29
-
30
- Attributes:
31
- policy_path: Path to the Rego policy file.
32
- opa_path: Path to the OPA executable. Defaults to "opa".
33
- tbom_path: Optional path to the Trusted Bill of Materials.
34
- extra_data_paths: Additional data paths to load into OPA.
35
- """
36
-
37
- policy_path: Union[str, Path]
38
- opa_path: str = "opa"
39
- tbom_path: Optional[Union[str, Path]] = None
40
- extra_data_paths: List[Union[str, Path]] = field(default_factory=list)
41
-
42
-
43
- class ManifestEngineAsync:
44
- """The async core for verifying and loading Agent Manifests.
45
-
46
- This class coordinates the validation process, including:
47
- 1. Loading raw YAML.
48
- 2. Validating against JSON Schema.
49
- 3. Converting to AgentDefinition Pydantic model (Normalization).
50
- 4. Enforcing Policy (Rego).
51
- 5. Verifying Integrity (Hash check).
52
- """
53
-
54
- def __init__(self, config: ManifestConfig) -> None:
55
- """Initialize the ManifestEngineAsync.
56
-
57
- Args:
58
- config: Configuration including policy path and OPA path.
59
- """
60
- self.config = config
61
- self.schema_validator = SchemaValidator()
62
-
63
- # Collect data paths
64
- data_paths = list(config.extra_data_paths)
65
- if config.tbom_path:
66
- data_paths.append(config.tbom_path)
67
-
68
- self.policy_enforcer = PolicyEnforcer(
69
- policy_path=config.policy_path,
70
- opa_path=config.opa_path,
71
- data_paths=data_paths,
72
- )
73
-
74
- async def __aenter__(self) -> ManifestEngineAsync:
75
- """Async context manager entry."""
76
- return self
77
-
78
- async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
79
- """Async context manager exit."""
80
- # Clean up resources if necessary.
81
- pass
82
-
83
- async def validate_manifest_dict(self, raw_data: dict[str, Any]) -> AgentDefinition:
84
- """Validates an Agent Manifest dictionary in memory.
85
-
86
- Performs:
87
- 1. Normalization (stripping version prefixes)
88
- 2. Schema Validation
89
- 3. Model Conversion
90
- 4. Policy Enforcement
91
-
92
- Does NOT perform Integrity Check (hashing).
93
-
94
- Args:
95
- raw_data: The raw dictionary of the manifest.
96
-
97
- Returns:
98
- AgentDefinition: The fully validated agent definition.
99
-
100
- Raises:
101
- ManifestSyntaxError: If structure or schema is invalid.
102
- PolicyViolationError: If business rules are violated.
103
- """
104
- # 1. Normalization (ensure version string is clean before schema/model validation)
105
- # We access the static method on ManifestLoader.
106
- ManifestLoader._normalize_data(raw_data)
107
-
108
- # 2. Schema Validation
109
- logger.debug("Running Schema Validation...")
110
- self.schema_validator.validate(raw_data)
111
-
112
- # 3. Model Conversion (Normalization) (CPU bound)
113
- logger.debug("Converting to AgentDefinition...")
114
- agent_def = await anyio.to_thread.run_sync(ManifestLoader.load_from_dict, raw_data)
115
- logger.info(f"Validating Agent {agent_def.metadata.id} v{agent_def.metadata.version}")
116
-
117
- # 4. Policy Enforcement (Subprocess / Blocking)
118
- logger.debug("Enforcing Policies...")
119
- # We assume policy is checked against the Normalized data (model dumped back to dict)
120
- normalized_data = agent_def.model_dump(mode="json")
121
- start_time = time.perf_counter()
122
- try:
123
- # PolicyEnforcer.evaluate is synchronous and runs subprocess.run, so we wrap it.
124
- await anyio.to_thread.run_sync(self.policy_enforcer.evaluate, normalized_data)
125
- duration_ms = (time.perf_counter() - start_time) * 1000
126
- logger.info(f"Policy Check: Pass - {duration_ms:.2f}ms")
127
- except Exception:
128
- duration_ms = (time.perf_counter() - start_time) * 1000
129
- logger.info(f"Policy Check: Fail - {duration_ms:.2f}ms")
130
- raise
131
-
132
- return cast(AgentDefinition, agent_def)
133
-
134
- async def load_and_validate(self, manifest_path: Union[str, Path], source_dir: Union[str, Path]) -> AgentDefinition:
135
- """Loads, validates, and verifies an Agent Manifest asynchronously.
136
-
137
- Args:
138
- manifest_path: Path to the agent.yaml file.
139
- source_dir: Path to the source code directory.
140
-
141
- Returns:
142
- AgentDefinition: The fully validated and verified agent definition.
143
-
144
- Raises:
145
- ManifestSyntaxError: If structure or schema is invalid.
146
- PolicyViolationError: If business rules are violated.
147
- IntegrityCompromisedError: If source code hash does not match.
148
- FileNotFoundError: If files are missing.
149
- """
150
- manifest_path = Path(manifest_path)
151
- source_dir = Path(source_dir)
152
-
153
- logger.info(f"Validating Agent Manifest: {manifest_path}")
154
-
155
- # 1. Load Raw YAML (I/O)
156
- raw_data = await ManifestLoader.load_raw_from_file_async(manifest_path)
157
-
158
- # 2. Validate Manifest Dict (Schema, Model, Policy)
159
- agent_def = await self.validate_manifest_dict(raw_data)
160
-
161
- # 5. Integrity Check (Heavy I/O and CPU)
162
- logger.debug("Verifying Integrity...")
163
- # IntegrityChecker.verify is synchronous and does heavy IO, so we wrap it.
164
- await anyio.to_thread.run_sync(IntegrityChecker.verify, agent_def, source_dir, manifest_path)
165
-
166
- logger.info("Agent validation successful.")
167
- return agent_def
168
-
169
-
170
- class ManifestEngine:
171
- """The Sync Facade for ManifestEngineAsync.
172
-
173
- Allows synchronous usage of the async core via anyio.run.
174
- """
175
-
176
- def __init__(self, config: ManifestConfig) -> None:
177
- """Initialize the ManifestEngine facade.
178
-
179
- Args:
180
- config: Configuration including policy path and OPA path.
181
- """
182
- self._async = ManifestEngineAsync(config)
183
-
184
- def __getattr__(self, name: str) -> Any:
185
- """Delegate attribute access to the async engine instance.
186
-
187
- This ensures backward compatibility for accessing attributes like
188
- 'config', 'schema_validator', and 'policy_enforcer'.
189
- """
190
- return getattr(self._async, name)
191
-
192
- def __enter__(self) -> ManifestEngine:
193
- """Context manager entry."""
194
- anyio.run(self._async.__aenter__)
195
- return self
196
-
197
- def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
198
- """Context manager exit."""
199
- anyio.run(self._async.__aexit__, exc_type, exc_val, exc_tb)
200
-
201
- def load_and_validate(self, manifest_path: Union[str, Path], source_dir: Union[str, Path]) -> AgentDefinition:
202
- """Loads, validates, and verifies an Agent Manifest synchronously.
203
-
204
- Args:
205
- manifest_path: Path to the agent.yaml file.
206
- source_dir: Path to the source code directory.
207
-
208
- Returns:
209
- AgentDefinition: The fully validated and verified agent definition.
210
- """
211
- return cast(AgentDefinition, anyio.run(self._async.load_and_validate, manifest_path, source_dir))
212
-
213
- def validate_manifest_dict(self, raw_data: dict[str, Any]) -> AgentDefinition:
214
- """Validates an Agent Manifest dictionary synchronously.
215
-
216
- Args:
217
- raw_data: The raw dictionary of the manifest.
218
-
219
- Returns:
220
- AgentDefinition: The fully validated agent definition.
221
- """
222
- return cast(AgentDefinition, anyio.run(self._async.validate_manifest_dict, raw_data))