Wrap a Python callable `(str, Json) -> Optional[str]` for tool conditional guardrails.
(py_fn: Py<PyAny>)
| 210 | |
| 211 | /// Wrap a Python callable `(str, Json) -> Optional[str]` for tool conditional guardrails. |
| 212 | pub fn wrap_py_tool_conditional_fn(py_fn: Py<PyAny>) -> ToolConditionalFn { |
| 213 | Arc::new(move |name: &str, args: &Json| { |
| 214 | Python::attach(|py| { |
| 215 | let py_args = json_to_py(py, args).map_err(|e| { |
| 216 | FlowError::Internal(format!( |
| 217 | "tool conditional json_to_py failed for '{name}': {e}" |
| 218 | )) |
| 219 | })?; |
| 220 | let result = py_fn.call1(py, (name, py_args)).map_err(|e| { |
| 221 | FlowError::Internal(format!( |
| 222 | "Python tool conditional callable failed for '{name}': {e}" |
| 223 | )) |
| 224 | })?; |
| 225 | let bound = result.bind(py); |
| 226 | if bound.is_none() { |
| 227 | Ok(None) |
| 228 | } else { |
| 229 | bound.extract::<String>().map(Some).map_err(|e| { |
| 230 | FlowError::Internal(format!( |
| 231 | "tool conditional guardrail for '{name}' returned unexpected type (expected str or None): {e}" |
| 232 | )) |
| 233 | }) |
| 234 | } |
| 235 | }) |
| 236 | }) |
| 237 | } |
| 238 | |
| 239 | /// Wrap a Python callable `(str, Json) -> Json` for tool request intercepts. |
| 240 | pub fn wrap_py_tool_request_intercept_fn(py_fn: Py<PyAny>) -> ToolInterceptFn { |