coreason-manifest 0.10.0__py3-none-any.whl → 0.12.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.
- coreason_manifest/__init__.py +35 -82
- coreason_manifest/{definitions/base.py → common.py} +18 -1
- coreason_manifest/governance.py +83 -0
- coreason_manifest/schemas/coreason-v2.schema.json +462 -0
- coreason_manifest/v2/__init__.py +1 -0
- coreason_manifest/v2/governance.py +144 -0
- coreason_manifest/v2/io.py +132 -0
- coreason_manifest/v2/resolver.py +67 -0
- coreason_manifest/v2/spec/__init__.py +1 -0
- coreason_manifest/v2/spec/contracts.py +34 -0
- coreason_manifest/v2/spec/definitions.py +196 -0
- coreason_manifest/v2/validator.py +48 -0
- {coreason_manifest-0.10.0.dist-info → coreason_manifest-0.12.0.dist-info}/METADATA +48 -71
- coreason_manifest-0.12.0.dist-info/RECORD +20 -0
- coreason_manifest/definitions/__init__.py +0 -60
- coreason_manifest/definitions/agent.py +0 -370
- coreason_manifest/definitions/audit.py +0 -181
- coreason_manifest/definitions/events.py +0 -423
- coreason_manifest/definitions/message.py +0 -188
- coreason_manifest/definitions/simulation.py +0 -79
- coreason_manifest/definitions/simulation_config.py +0 -46
- coreason_manifest/definitions/topology.py +0 -341
- coreason_manifest/recipes.py +0 -84
- coreason_manifest/schemas/agent.schema.json +0 -1051
- coreason_manifest/schemas/recipe.schema.json +0 -813
- coreason_manifest/v1/__init__.py +0 -15
- coreason_manifest-0.10.0.dist-info/RECORD +0 -22
- {coreason_manifest-0.10.0.dist-info → coreason_manifest-0.12.0.dist-info}/WHEEL +0 -0
- {coreason_manifest-0.10.0.dist-info → coreason_manifest-0.12.0.dist-info}/licenses/LICENSE +0 -0
- {coreason_manifest-0.10.0.dist-info → coreason_manifest-0.12.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,188 +0,0 @@
|
|
|
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-manifest
|
|
10
|
-
|
|
11
|
-
import functools
|
|
12
|
-
import json
|
|
13
|
-
import warnings
|
|
14
|
-
from enum import Enum
|
|
15
|
-
from typing import Annotated, Any, Dict, List, Literal, Optional, Union, cast
|
|
16
|
-
|
|
17
|
-
from pydantic import ConfigDict, Field, model_validator
|
|
18
|
-
|
|
19
|
-
from coreason_manifest.definitions.base import CoReasonBaseModel
|
|
20
|
-
|
|
21
|
-
# --- Enums ---
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class Role(str, Enum):
|
|
25
|
-
SYSTEM = "system"
|
|
26
|
-
USER = "user"
|
|
27
|
-
ASSISTANT = "assistant"
|
|
28
|
-
TOOL = "tool"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class Modality(str, Enum):
|
|
32
|
-
TEXT = "text"
|
|
33
|
-
IMAGE = "image"
|
|
34
|
-
AUDIO = "audio"
|
|
35
|
-
VIDEO = "video"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# --- Message Parts ---
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class TextPart(CoReasonBaseModel):
|
|
42
|
-
"""Represents text content sent to or received from the model."""
|
|
43
|
-
|
|
44
|
-
model_config = ConfigDict(extra="ignore")
|
|
45
|
-
type: Literal["text"] = "text"
|
|
46
|
-
content: str
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class BlobPart(CoReasonBaseModel):
|
|
50
|
-
"""Represents blob binary data sent inline to the model."""
|
|
51
|
-
|
|
52
|
-
model_config = ConfigDict(extra="ignore")
|
|
53
|
-
type: Literal["blob"] = "blob"
|
|
54
|
-
content: str # Base64 encoded string
|
|
55
|
-
modality: Modality
|
|
56
|
-
mime_type: Optional[str] = None
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class FilePart(CoReasonBaseModel):
|
|
60
|
-
"""Represents an external referenced file sent to the model by file id."""
|
|
61
|
-
|
|
62
|
-
model_config = ConfigDict(extra="ignore")
|
|
63
|
-
type: Literal["file"] = "file"
|
|
64
|
-
file_id: str
|
|
65
|
-
modality: Modality
|
|
66
|
-
mime_type: Optional[str] = None
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class UriPart(CoReasonBaseModel):
|
|
70
|
-
"""Represents an external referenced file sent to the model by URI."""
|
|
71
|
-
|
|
72
|
-
model_config = ConfigDict(extra="ignore")
|
|
73
|
-
type: Literal["uri"] = "uri"
|
|
74
|
-
uri: str
|
|
75
|
-
modality: Modality
|
|
76
|
-
mime_type: Optional[str] = None
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class ToolCallRequestPart(CoReasonBaseModel):
|
|
80
|
-
"""Represents a tool call requested by the model."""
|
|
81
|
-
|
|
82
|
-
model_config = ConfigDict(extra="ignore")
|
|
83
|
-
type: Literal["tool_call"] = "tool_call"
|
|
84
|
-
name: str
|
|
85
|
-
arguments: Union[Dict[str, Any], str] # Structured arguments or JSON string
|
|
86
|
-
id: Optional[str] = None
|
|
87
|
-
|
|
88
|
-
@functools.cached_property
|
|
89
|
-
def parsed_arguments(self) -> Dict[str, Any]:
|
|
90
|
-
"""Return arguments as a dictionary, parsing JSON if necessary."""
|
|
91
|
-
if isinstance(self.arguments, dict):
|
|
92
|
-
return self.arguments
|
|
93
|
-
try:
|
|
94
|
-
result = json.loads(self.arguments)
|
|
95
|
-
return cast(Dict[str, Any], result) if isinstance(result, dict) else {}
|
|
96
|
-
except (json.JSONDecodeError, TypeError):
|
|
97
|
-
return {}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class ToolCallResponsePart(CoReasonBaseModel):
|
|
101
|
-
"""Represents a tool call result sent to the model."""
|
|
102
|
-
|
|
103
|
-
model_config = ConfigDict(extra="ignore")
|
|
104
|
-
type: Literal["tool_call_response"] = "tool_call_response"
|
|
105
|
-
response: Any # The result of the tool call
|
|
106
|
-
id: Optional[str] = None
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
class ReasoningPart(CoReasonBaseModel):
|
|
110
|
-
"""Represents reasoning/thinking content received from the model."""
|
|
111
|
-
|
|
112
|
-
model_config = ConfigDict(extra="ignore")
|
|
113
|
-
type: Literal["reasoning"] = "reasoning"
|
|
114
|
-
content: str
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
# --- Union of All Parts ---
|
|
118
|
-
|
|
119
|
-
Part = Annotated[
|
|
120
|
-
Union[TextPart, BlobPart, FilePart, UriPart, ToolCallRequestPart, ToolCallResponsePart, ReasoningPart],
|
|
121
|
-
Field(discriminator="type"),
|
|
122
|
-
]
|
|
123
|
-
|
|
124
|
-
# --- Main Message Model ---
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
class ChatMessage(CoReasonBaseModel):
|
|
128
|
-
"""Represents a message in a conversation with an LLM."""
|
|
129
|
-
|
|
130
|
-
model_config = ConfigDict(extra="ignore")
|
|
131
|
-
|
|
132
|
-
role: Role
|
|
133
|
-
parts: List[Part] = Field(..., description="List of message parts that make up the message content.")
|
|
134
|
-
name: Optional[str] = None
|
|
135
|
-
|
|
136
|
-
@classmethod
|
|
137
|
-
def user(cls, content: str, name: Optional[str] = None) -> "ChatMessage":
|
|
138
|
-
"""Factory method to create a user message with text content."""
|
|
139
|
-
return cls(role=Role.USER, parts=[TextPart(content=content)], name=name)
|
|
140
|
-
|
|
141
|
-
@classmethod
|
|
142
|
-
def assistant(cls, content: str, name: Optional[str] = None) -> "ChatMessage":
|
|
143
|
-
"""Factory method to create an assistant message with text content."""
|
|
144
|
-
return cls(role=Role.ASSISTANT, parts=[TextPart(content=content)], name=name)
|
|
145
|
-
|
|
146
|
-
@classmethod
|
|
147
|
-
def tool(cls, tool_call_id: str, content: Any) -> "ChatMessage":
|
|
148
|
-
"""Factory method to create a tool message with the result."""
|
|
149
|
-
return cls(role=Role.TOOL, parts=[ToolCallResponsePart(id=tool_call_id, response=content)])
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
# --- Backward Compatibility ---
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
class FunctionCall(CoReasonBaseModel):
|
|
156
|
-
"""Deprecated: Use ToolCallRequestPart instead."""
|
|
157
|
-
|
|
158
|
-
name: str
|
|
159
|
-
arguments: str
|
|
160
|
-
|
|
161
|
-
@model_validator(mode="after")
|
|
162
|
-
def warn_deprecated(self) -> "FunctionCall":
|
|
163
|
-
warnings.warn(
|
|
164
|
-
"FunctionCall is deprecated. Use ToolCallRequestPart instead.",
|
|
165
|
-
DeprecationWarning,
|
|
166
|
-
stacklevel=2,
|
|
167
|
-
)
|
|
168
|
-
return self
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
class ToolCall(CoReasonBaseModel):
|
|
172
|
-
"""Deprecated: Use ToolCallRequestPart instead."""
|
|
173
|
-
|
|
174
|
-
id: str
|
|
175
|
-
type: str = "function"
|
|
176
|
-
function: FunctionCall
|
|
177
|
-
|
|
178
|
-
@model_validator(mode="after")
|
|
179
|
-
def warn_deprecated(self) -> "ToolCall":
|
|
180
|
-
warnings.warn(
|
|
181
|
-
"ToolCall is deprecated. Use ToolCallRequestPart instead.",
|
|
182
|
-
DeprecationWarning,
|
|
183
|
-
stacklevel=2,
|
|
184
|
-
)
|
|
185
|
-
return self
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Message = ChatMessage
|
|
@@ -1,79 +0,0 @@
|
|
|
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-manifest
|
|
10
|
-
|
|
11
|
-
from datetime import datetime
|
|
12
|
-
from enum import Enum
|
|
13
|
-
from typing import Any, Dict, List, Optional
|
|
14
|
-
from uuid import UUID
|
|
15
|
-
|
|
16
|
-
from pydantic import Field
|
|
17
|
-
|
|
18
|
-
from coreason_manifest.definitions.base import CoReasonBaseModel
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class StepType(str, Enum):
|
|
22
|
-
"""Type of the simulation step."""
|
|
23
|
-
|
|
24
|
-
INTERACTION = "interaction" # Normal User/Agent turn
|
|
25
|
-
SYSTEM_EVENT = "system_event" # Chaos injection, error, or info
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class ValidationLogic(str, Enum):
|
|
29
|
-
"""Logic used to validate the scenario outcome."""
|
|
30
|
-
|
|
31
|
-
EXACT_MATCH = "exact_match"
|
|
32
|
-
FUZZY = "fuzzy"
|
|
33
|
-
CODE_EVAL = "code_eval"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class SimulationScenario(CoReasonBaseModel):
|
|
37
|
-
"""Definition of a simulation scenario."""
|
|
38
|
-
|
|
39
|
-
id: str = Field(..., description="Unique identifier for the scenario.")
|
|
40
|
-
name: str = Field(..., description="Name of the scenario.")
|
|
41
|
-
objective: str = Field(..., description="The prompt/task instructions.")
|
|
42
|
-
difficulty: int = Field(..., description="Difficulty level (1-3, aligning with GAIA levels).", ge=1, le=3)
|
|
43
|
-
expected_outcome: Any = Field(..., description="The ground truth for validation.")
|
|
44
|
-
validation_logic: ValidationLogic = Field(..., description="Logic used to validate the outcome.")
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class SimulationStep(CoReasonBaseModel):
|
|
48
|
-
"""The atomic unit of execution in a simulation."""
|
|
49
|
-
|
|
50
|
-
step_id: UUID = Field(..., description="Atomic unit of execution ID.")
|
|
51
|
-
timestamp: datetime = Field(..., description="Execution timestamp.")
|
|
52
|
-
type: StepType = Field(default=StepType.INTERACTION, description="Type of the step.")
|
|
53
|
-
node_id: str = Field(..., description="The graph node executed.")
|
|
54
|
-
inputs: Dict[str, Any] = Field(..., description="Snapshot of entry state.")
|
|
55
|
-
thought: Optional[str] = Field(None, description="The Chain-of-Thought reasoning.")
|
|
56
|
-
action: Optional[Dict[str, Any]] = Field(None, description="Tool calls or API requests.")
|
|
57
|
-
observation: Optional[Dict[str, Any]] = Field(None, description="Tool outputs.")
|
|
58
|
-
snapshot: Dict[str, Any] = Field(
|
|
59
|
-
default_factory=dict, description="Full copy of the graph state at the completion of this step."
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class SimulationMetrics(CoReasonBaseModel):
|
|
64
|
-
"""Metrics gathered during simulation."""
|
|
65
|
-
|
|
66
|
-
turn_count: int
|
|
67
|
-
total_tokens: Optional[int] = None
|
|
68
|
-
cost_usd: Optional[float] = None
|
|
69
|
-
duration_ms: Optional[float] = None
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
class SimulationTrace(CoReasonBaseModel):
|
|
73
|
-
"""Trace of a simulation execution."""
|
|
74
|
-
|
|
75
|
-
trace_id: UUID = Field(..., description="Unique trace identifier.")
|
|
76
|
-
agent_version: str = Field(..., description="Agent SemVer version.")
|
|
77
|
-
steps: List[SimulationStep] = Field(..., description="List of execution steps.")
|
|
78
|
-
outcome: Dict[str, Any] = Field(..., description="Final result.")
|
|
79
|
-
metrics: SimulationMetrics = Field(..., description="Execution metrics (e.g., token usage, cost).")
|
|
@@ -1,46 +0,0 @@
|
|
|
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-manifest
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from typing import Optional
|
|
13
|
-
|
|
14
|
-
from pydantic import Field
|
|
15
|
-
|
|
16
|
-
from coreason_manifest.definitions.agent import Persona
|
|
17
|
-
from coreason_manifest.definitions.base import CoReasonBaseModel
|
|
18
|
-
from coreason_manifest.definitions.simulation import SimulationScenario
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class AdversaryProfile(CoReasonBaseModel):
|
|
22
|
-
name: str
|
|
23
|
-
goal: str
|
|
24
|
-
strategy_model: str # e.g., "claude-3-opus"
|
|
25
|
-
attack_model: str # e.g., "llama-3-uncensored"
|
|
26
|
-
persona: Optional[Persona] = Field(None, description="The full persona definition (name, description, directives).")
|
|
27
|
-
# Potential future field: 'system_prompt_override'
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class ChaosConfig(CoReasonBaseModel):
|
|
31
|
-
latency_ms: int = Field(default=0, ge=0)
|
|
32
|
-
error_rate: float = Field(default=0.0, ge=0.0, le=1.0)
|
|
33
|
-
noise_rate: float = Field(default=0.0, ge=0.0, le=1.0)
|
|
34
|
-
token_throttle: bool = False
|
|
35
|
-
exception_type: str = "RuntimeError"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class SimulationRequest(CoReasonBaseModel):
|
|
39
|
-
"""
|
|
40
|
-
Standard payload for triggering a simulation.
|
|
41
|
-
This would replace the local 'SimulationRequest' in the Simulator.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
scenario: SimulationScenario
|
|
45
|
-
profile: AdversaryProfile
|
|
46
|
-
chaos_config: ChaosConfig = Field(default_factory=ChaosConfig)
|
|
@@ -1,341 +0,0 @@
|
|
|
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-manifest
|
|
10
|
-
|
|
11
|
-
# Copyright (c) 2025 CoReason, Inc.
|
|
12
|
-
#
|
|
13
|
-
# This software is proprietary and dual-licensed.
|
|
14
|
-
# Licensed under the Prosperity Public License 3.0 (the "License").
|
|
15
|
-
# A copy of the license is available at https://prosperitylicense.com/versions/3.0.0
|
|
16
|
-
# For details, see the LICENSE file.
|
|
17
|
-
# Commercial use beyond a 30-day trial requires a separate license.
|
|
18
|
-
#
|
|
19
|
-
# Source Code: https://github.com/CoReason-AI/coreason_maco
|
|
20
|
-
|
|
21
|
-
from enum import Enum
|
|
22
|
-
from typing import Annotated, Any, Dict, List, Literal, Optional, Sequence, Union
|
|
23
|
-
|
|
24
|
-
from pydantic import ConfigDict, Field, StringConstraints, model_validator
|
|
25
|
-
|
|
26
|
-
from coreason_manifest.definitions.base import CoReasonBaseModel
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class StateDefinition(CoReasonBaseModel):
|
|
30
|
-
"""Defines the internal state (memory) of the Recipe.
|
|
31
|
-
|
|
32
|
-
Attributes:
|
|
33
|
-
schema: JSON Schema of the keys available in the shared memory.
|
|
34
|
-
persistence: Configuration for state durability.
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
model_config = ConfigDict(extra="forbid")
|
|
38
|
-
|
|
39
|
-
schema_: Dict[str, Any] = Field(
|
|
40
|
-
..., alias="schema", description="JSON Schema of the keys available in the shared memory."
|
|
41
|
-
)
|
|
42
|
-
persistence: Literal["ephemeral", "persistent"] = Field(
|
|
43
|
-
default="ephemeral", description="Configuration for state durability."
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class CouncilConfig(CoReasonBaseModel):
|
|
48
|
-
"""Configuration for 'Architectural Triangulation'.
|
|
49
|
-
|
|
50
|
-
Attributes:
|
|
51
|
-
strategy: The strategy for the council (e.g., 'consensus').
|
|
52
|
-
voters: List of agents or models that vote.
|
|
53
|
-
"""
|
|
54
|
-
|
|
55
|
-
model_config = ConfigDict(extra="forbid")
|
|
56
|
-
|
|
57
|
-
strategy: str = Field(default="consensus", description="The strategy for the council, e.g., 'consensus'.")
|
|
58
|
-
voters: List[str] = Field(..., description="List of agents or models that vote.")
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class VisualMetadata(CoReasonBaseModel):
|
|
62
|
-
"""Data explicitly for the UI.
|
|
63
|
-
|
|
64
|
-
Attributes:
|
|
65
|
-
label: The label to display for the node.
|
|
66
|
-
x_y_coordinates: The X and Y coordinates for the node on the canvas.
|
|
67
|
-
icon: The icon to represent the node.
|
|
68
|
-
animation_style: The animation style for the node.
|
|
69
|
-
"""
|
|
70
|
-
|
|
71
|
-
model_config = ConfigDict(extra="forbid")
|
|
72
|
-
|
|
73
|
-
label: Optional[str] = Field(None, description="The label to display for the node.")
|
|
74
|
-
x_y_coordinates: Optional[List[float]] = Field(
|
|
75
|
-
None, description="The X and Y coordinates for the node on the canvas."
|
|
76
|
-
)
|
|
77
|
-
icon: Optional[str] = Field(None, description="The icon to represent the node.")
|
|
78
|
-
animation_style: Optional[str] = Field(None, description="The animation style for the node.")
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class RuntimeVisualMetadata(VisualMetadata):
|
|
82
|
-
"""Visual metadata with runtime extensions.
|
|
83
|
-
|
|
84
|
-
Attributes:
|
|
85
|
-
color: Color override for the node (e.g., '#00FF00').
|
|
86
|
-
progress: Progress indicator (e.g., '0.5' or '50%').
|
|
87
|
-
animation: Animation override (e.g., 'pulse').
|
|
88
|
-
"""
|
|
89
|
-
|
|
90
|
-
color: Optional[str] = Field(None, description="Color override for the node.")
|
|
91
|
-
progress: Optional[str] = Field(None, description="Progress indicator.")
|
|
92
|
-
animation: Optional[str] = Field(None, description="Animation override.")
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
class BaseNode(CoReasonBaseModel):
|
|
96
|
-
"""Base model for all node types.
|
|
97
|
-
|
|
98
|
-
Attributes:
|
|
99
|
-
id: Unique identifier for the node.
|
|
100
|
-
council_config: Optional configuration for architectural triangulation.
|
|
101
|
-
visual: Visual metadata for the UI.
|
|
102
|
-
metadata: Generic metadata for operational context (e.g. cost tracking, SLAs).
|
|
103
|
-
"""
|
|
104
|
-
|
|
105
|
-
model_config = ConfigDict(extra="forbid")
|
|
106
|
-
|
|
107
|
-
id: str = Field(..., description="Unique identifier for the node.")
|
|
108
|
-
council_config: Optional[CouncilConfig] = Field(
|
|
109
|
-
None, description="Optional configuration for architectural triangulation."
|
|
110
|
-
)
|
|
111
|
-
visual: Optional[VisualMetadata] = Field(None, description="Visual metadata for the UI.")
|
|
112
|
-
metadata: Dict[str, Any] = Field(
|
|
113
|
-
default_factory=dict,
|
|
114
|
-
description="Generic metadata for operational context (e.g. cost tracking, SLAs).",
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
class AgentNode(BaseNode):
|
|
119
|
-
"""A node that calls a specific atomic agent.
|
|
120
|
-
|
|
121
|
-
Attributes:
|
|
122
|
-
type: The type of the node (must be 'agent').
|
|
123
|
-
agent_name: The name of the atomic agent to call.
|
|
124
|
-
system_prompt: Overrides the registry default prompt. Required for ad-hoc/optimized agents.
|
|
125
|
-
config: Runtime-specific configuration (e.g., model parameters, temperature). Merged with registry defaults.
|
|
126
|
-
overrides: Runtime overrides for the agent (e.g., temperature, prompt_template_vars).
|
|
127
|
-
"""
|
|
128
|
-
|
|
129
|
-
type: Literal["agent"] = Field("agent", description="Discriminator for AgentNode.")
|
|
130
|
-
agent_name: str = Field(..., description="The name of the atomic agent to call.")
|
|
131
|
-
system_prompt: Optional[str] = Field(
|
|
132
|
-
default=None,
|
|
133
|
-
description="Overrides the registry default prompt. Required for ad-hoc/optimized agents.",
|
|
134
|
-
)
|
|
135
|
-
config: Optional[Dict[str, Any]] = Field(
|
|
136
|
-
default=None,
|
|
137
|
-
description=(
|
|
138
|
-
"Runtime-specific configuration (e.g., model parameters, temperature). Merged with registry defaults."
|
|
139
|
-
),
|
|
140
|
-
)
|
|
141
|
-
overrides: Optional[Dict[str, Any]] = Field(
|
|
142
|
-
default=None,
|
|
143
|
-
description="Runtime overrides for the agent (e.g., temperature, prompt_template_vars).",
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
class HumanNode(BaseNode):
|
|
148
|
-
"""A node that pauses execution for user input/approval.
|
|
149
|
-
|
|
150
|
-
Attributes:
|
|
151
|
-
type: The type of the node (must be 'human').
|
|
152
|
-
timeout_seconds: Optional timeout in seconds for the user interaction.
|
|
153
|
-
"""
|
|
154
|
-
|
|
155
|
-
type: Literal["human"] = Field("human", description="Discriminator for HumanNode.")
|
|
156
|
-
timeout_seconds: Optional[int] = Field(None, description="Optional timeout in seconds for the user interaction.")
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
class LogicNode(BaseNode):
|
|
160
|
-
"""A node that executes pure Python logic.
|
|
161
|
-
|
|
162
|
-
Attributes:
|
|
163
|
-
type: The type of the node (must be 'logic').
|
|
164
|
-
code: The Python logic code to execute.
|
|
165
|
-
"""
|
|
166
|
-
|
|
167
|
-
type: Literal["logic"] = Field("logic", description="Discriminator for LogicNode.")
|
|
168
|
-
code: str = Field(..., description="The Python logic code to execute.")
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
class DataMappingStrategy(str, Enum):
|
|
172
|
-
"""Strategy for mapping data."""
|
|
173
|
-
|
|
174
|
-
DIRECT = "direct"
|
|
175
|
-
JSONPATH = "jsonpath"
|
|
176
|
-
LITERAL = "literal"
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
class DataMapping(CoReasonBaseModel):
|
|
180
|
-
"""Defines how to transform data between parent and child."""
|
|
181
|
-
|
|
182
|
-
model_config = ConfigDict(extra="forbid")
|
|
183
|
-
|
|
184
|
-
source: str = Field(..., description="The path/key source.")
|
|
185
|
-
strategy: DataMappingStrategy = Field(default=DataMappingStrategy.DIRECT, description="The mapping strategy.")
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
class RecipeNode(BaseNode):
|
|
189
|
-
"""A node that executes another Recipe as a sub-graph.
|
|
190
|
-
|
|
191
|
-
Attributes:
|
|
192
|
-
type: The type of the node (must be 'recipe').
|
|
193
|
-
recipe_id: The ID of the recipe to execute.
|
|
194
|
-
input_mapping: How parent state maps to child inputs (parent_key -> child_key).
|
|
195
|
-
output_mapping: How child result maps back to parent state (child_key -> parent_key).
|
|
196
|
-
"""
|
|
197
|
-
|
|
198
|
-
type: Literal["recipe"] = Field("recipe", description="Discriminator for RecipeNode.")
|
|
199
|
-
recipe_id: str = Field(..., description="The ID of the recipe to execute.")
|
|
200
|
-
input_mapping: Dict[str, Union[str, DataMapping]] = Field(
|
|
201
|
-
..., description="Mapping of parent state keys to child input keys."
|
|
202
|
-
)
|
|
203
|
-
output_mapping: Dict[str, Union[str, DataMapping]] = Field(
|
|
204
|
-
..., description="Mapping of child output keys to parent state keys."
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
class MapNode(BaseNode):
|
|
209
|
-
"""A node that spawns multiple parallel executions of a sub-branch.
|
|
210
|
-
|
|
211
|
-
Attributes:
|
|
212
|
-
type: The type of the node (must be 'map').
|
|
213
|
-
items_path: Dot-notation path to the list in the state.
|
|
214
|
-
processor_node_id: The node (or subgraph) to run for each item.
|
|
215
|
-
concurrency_limit: Max parallel executions.
|
|
216
|
-
"""
|
|
217
|
-
|
|
218
|
-
type: Literal["map"] = Field("map", description="Discriminator for MapNode.")
|
|
219
|
-
items_path: str = Field(..., description="Dot-notation path to the list in the state.")
|
|
220
|
-
processor_node_id: str = Field(..., description="The node (or subgraph) to run for each item.")
|
|
221
|
-
concurrency_limit: int = Field(..., description="Max parallel executions.")
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
# Discriminated Union for polymorphism
|
|
225
|
-
Node = Annotated[
|
|
226
|
-
Union[AgentNode, HumanNode, LogicNode, RecipeNode, MapNode],
|
|
227
|
-
Field(discriminator="type", description="Polymorphic node definition."),
|
|
228
|
-
]
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
class Edge(CoReasonBaseModel):
|
|
232
|
-
"""Represents a connection between two nodes.
|
|
233
|
-
|
|
234
|
-
Attributes:
|
|
235
|
-
source_node_id: The ID of the source node.
|
|
236
|
-
target_node_id: The ID of the target node.
|
|
237
|
-
condition: Optional Python expression for conditional branching.
|
|
238
|
-
"""
|
|
239
|
-
|
|
240
|
-
model_config = ConfigDict(extra="forbid")
|
|
241
|
-
|
|
242
|
-
source_node_id: str = Field(..., description="The ID of the source node.")
|
|
243
|
-
target_node_id: str = Field(..., description="The ID of the target node.")
|
|
244
|
-
condition: Optional[str] = Field(None, description="Optional Python expression for conditional branching.")
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
RouterRef = Annotated[
|
|
248
|
-
str,
|
|
249
|
-
StringConstraints(
|
|
250
|
-
pattern=r"^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*$",
|
|
251
|
-
strip_whitespace=True,
|
|
252
|
-
),
|
|
253
|
-
]
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
class RouterExpression(CoReasonBaseModel):
|
|
257
|
-
"""A structured expression for routing logic (e.g., CEL or JSONLogic)."""
|
|
258
|
-
|
|
259
|
-
model_config = ConfigDict(extra="forbid")
|
|
260
|
-
|
|
261
|
-
operator: str = Field(..., description="The operator (e.g., 'eq', 'gt').")
|
|
262
|
-
args: List[Any] = Field(..., description="Arguments for the expression.")
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
RouterDefinition = Annotated[
|
|
266
|
-
Union[RouterRef, RouterExpression],
|
|
267
|
-
Field(description="A reference to a python function or a logic expression."),
|
|
268
|
-
]
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
class ConditionalEdge(CoReasonBaseModel):
|
|
272
|
-
"""Represents a dynamic routing connection from one node to multiple potential targets.
|
|
273
|
-
|
|
274
|
-
Attributes:
|
|
275
|
-
source_node_id: The ID of the source node.
|
|
276
|
-
router_logic: A reference to a python function or a logic expression that returns the next node ID.
|
|
277
|
-
mapping: A dictionary mapping the router's output (e.g., "approve", "reject") to target Node IDs.
|
|
278
|
-
"""
|
|
279
|
-
|
|
280
|
-
model_config = ConfigDict(extra="forbid")
|
|
281
|
-
|
|
282
|
-
source_node_id: str = Field(..., description="The ID of the source node.")
|
|
283
|
-
router_logic: RouterDefinition = Field(
|
|
284
|
-
..., description="A reference to a python function or logic expression that determines the path."
|
|
285
|
-
)
|
|
286
|
-
mapping: Dict[str, str] = Field(..., description="Map of router output values to target node IDs.")
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
def validate_edge_integrity(
|
|
290
|
-
nodes: Sequence[Node],
|
|
291
|
-
edges: Sequence[Union[Edge, ConditionalEdge]],
|
|
292
|
-
) -> None:
|
|
293
|
-
"""Ensures that all edges point to valid nodes.
|
|
294
|
-
|
|
295
|
-
Args:
|
|
296
|
-
nodes: List of nodes in the graph.
|
|
297
|
-
edges: List of edges connecting the nodes.
|
|
298
|
-
|
|
299
|
-
Raises:
|
|
300
|
-
ValueError: If an edge points to a non-existent node.
|
|
301
|
-
"""
|
|
302
|
-
node_ids = {node.id for node in nodes}
|
|
303
|
-
|
|
304
|
-
for edge in edges:
|
|
305
|
-
if edge.source_node_id not in node_ids:
|
|
306
|
-
raise ValueError(f"Edge source node '{edge.source_node_id}' not found in nodes.")
|
|
307
|
-
|
|
308
|
-
# ConditionalEdge mapping targets
|
|
309
|
-
if isinstance(edge, ConditionalEdge):
|
|
310
|
-
for target_id in edge.mapping.values():
|
|
311
|
-
if target_id not in node_ids:
|
|
312
|
-
raise ValueError(f"ConditionalEdge target node '{target_id}' not found in nodes.")
|
|
313
|
-
else:
|
|
314
|
-
# Regular Edge
|
|
315
|
-
if edge.target_node_id not in node_ids:
|
|
316
|
-
raise ValueError(f"Edge target node '{edge.target_node_id}' not found in nodes.")
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
class GraphTopology(CoReasonBaseModel):
|
|
320
|
-
"""The topology definition of the recipe.
|
|
321
|
-
|
|
322
|
-
Attributes:
|
|
323
|
-
nodes: List of nodes in the graph.
|
|
324
|
-
edges: List of edges connecting the nodes.
|
|
325
|
-
state_schema: Optional schema definition for the graph state.
|
|
326
|
-
"""
|
|
327
|
-
|
|
328
|
-
model_config = ConfigDict(extra="forbid")
|
|
329
|
-
|
|
330
|
-
nodes: List[Node] = Field(..., description="List of nodes in the graph.")
|
|
331
|
-
edges: List[Union[Edge, ConditionalEdge]] = Field(..., description="List of edges connecting the nodes.")
|
|
332
|
-
state_schema: Optional[StateDefinition] = Field(default=None, description="Schema definition for the graph state.")
|
|
333
|
-
|
|
334
|
-
@model_validator(mode="after")
|
|
335
|
-
def validate_graph_integrity(self) -> "GraphTopology":
|
|
336
|
-
"""Ensures that all edges point to valid nodes."""
|
|
337
|
-
validate_edge_integrity(self.nodes, self.edges)
|
|
338
|
-
return self
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
Topology = GraphTopology
|