(cls, data: Mapping[str, Any], *, path: str)
| 167 | |
| 168 | @classmethod |
| 169 | def from_dict(cls, data: Mapping[str, Any], *, path: str) -> "Node": |
| 170 | mapping = require_mapping(data, path) |
| 171 | node_id = require_str(mapping, "id", path) |
| 172 | node_type = require_str(mapping, "type", path) |
| 173 | try: |
| 174 | schema = get_node_schema(node_type) |
| 175 | except SchemaLookupError as exc: |
| 176 | raise ConfigError( |
| 177 | f"unsupported node type '{node_type}'", |
| 178 | extend_path(path, "type"), |
| 179 | ) from exc |
| 180 | |
| 181 | description = optional_str(mapping, "description", path) |
| 182 | # keep_context = bool(mapping.get("keep_context", False)) |
| 183 | log_output = bool(mapping.get("log_output", True)) |
| 184 | context_window = int(mapping.get("context_window", 0)) |
| 185 | input_value = ensure_list(mapping.get("input")) |
| 186 | output_value = ensure_list(mapping.get("output")) |
| 187 | |
| 188 | input_messages: List[Message] = [] |
| 189 | for value in input_value: |
| 190 | if isinstance(value, dict) and "role" in value: |
| 191 | input_messages.append(Message.from_dict(value)) |
| 192 | elif isinstance(value, Message): |
| 193 | input_messages.append(value) |
| 194 | else: |
| 195 | input_messages.append(Message(role=MessageRole.USER, content=str(value))) |
| 196 | |
| 197 | if "config" not in mapping or mapping["config"] is None: |
| 198 | raise ConfigError("node config block required", extend_path(path, "config")) |
| 199 | config_obj = schema.config_cls.from_dict( |
| 200 | mapping["config"], path=extend_path(path, "config") |
| 201 | ) |
| 202 | |
| 203 | formatted_output: List[NodePayload] = [] |
| 204 | for value in output_value: |
| 205 | if isinstance(value, dict) and "role" in value: |
| 206 | formatted_output.append(Message.from_dict(value)) |
| 207 | elif isinstance(value, Message): |
| 208 | formatted_output.append(value) |
| 209 | else: |
| 210 | formatted_output.append( |
| 211 | Message(role=MessageRole.ASSISTANT, content=str(value)) |
| 212 | ) |
| 213 | |
| 214 | # Dynamic configuration parsing removed - dynamic is now on edges |
| 215 | |
| 216 | node = cls( |
| 217 | id=node_id, |
| 218 | type=node_type, |
| 219 | description=description, |
| 220 | log_output=log_output, |
| 221 | input=input_messages, |
| 222 | output=formatted_output, |
| 223 | # keep_context=keep_context, |
| 224 | context_window=context_window, |
| 225 | vars={}, |
| 226 | config=config_obj, |
no test coverage detected