(self)
| 229 | return definition |
| 230 | |
| 231 | def validate(self) -> None: |
| 232 | node_ids = [node.id for node in self.nodes] |
| 233 | counts = Counter(node_ids) |
| 234 | duplicates = [nid for nid, count in counts.items() if count > 1] |
| 235 | if duplicates: |
| 236 | dup_list = ", ".join(sorted(duplicates)) |
| 237 | raise ConfigError(f"duplicate node ids detected: {dup_list}", extend_path(self.path, "nodes")) |
| 238 | |
| 239 | node_set = set(node_ids) |
| 240 | for start_node in self.start_nodes: |
| 241 | if start_node not in node_set: |
| 242 | raise ConfigError( |
| 243 | f"start node '{start_node}' not defined in nodes", |
| 244 | extend_path(self.path, "start"), |
| 245 | ) |
| 246 | for edge in self.edges: |
| 247 | if edge.source not in node_set: |
| 248 | raise ConfigError( |
| 249 | f"edge references unknown source node '{edge.source}'", |
| 250 | extend_path(self.path, f"edges->{edge.source}->{edge.target}"), |
| 251 | ) |
| 252 | if edge.target not in node_set: |
| 253 | raise ConfigError( |
| 254 | f"edge references unknown target node '{edge.target}'", |
| 255 | extend_path(self.path, f"edges->{edge.source}->{edge.target}"), |
| 256 | ) |
| 257 | |
| 258 | store_names = {store.name for store in self.memory} if self.memory else set() |
| 259 | |
| 260 | for node in self.nodes: |
| 261 | model = node.as_config(AgentConfig) |
| 262 | if model: |
| 263 | for attachment in model.memories: |
| 264 | if attachment.name not in store_names: |
| 265 | raise ConfigError( |
| 266 | f"memory reference '{attachment.name}' not defined in graph.memory", |
| 267 | attachment.path or extend_path(node.path, "config.memories"), |
| 268 | ) |
| 269 | |
| 270 | |
| 271 | @dataclass |
no test coverage detected