Wrap a Python callable `(str, Json) -> Json` for tool sanitize/intercept fns.
(py_fn: Py<PyAny>)
| 184 | |
| 185 | /// Wrap a Python callable `(str, Json) -> Json` for tool sanitize/intercept fns. |
| 186 | pub fn wrap_py_tool_fn(py_fn: Py<PyAny>) -> ToolSanitizeFn { |
| 187 | Arc::new(move |name: &str, args: Json| { |
| 188 | Python::attach(|py| { |
| 189 | let py_args = match json_to_py(py, &args) { |
| 190 | Ok(v) => v, |
| 191 | Err(e) => { |
| 192 | eprintln!("nemo_relay: json_to_py failed in tool fn for '{name}': {e}"); |
| 193 | return args.clone(); |
| 194 | } |
| 195 | }; |
| 196 | let result = match py_fn.call1(py, (name, py_args)) { |
| 197 | Ok(v) => v, |
| 198 | Err(e) => { |
| 199 | eprintln!("nemo_relay: Python tool callable failed for '{name}': {e}"); |
| 200 | return args.clone(); |
| 201 | } |
| 202 | }; |
| 203 | py_to_json(result.bind(py)).unwrap_or_else(|e| { |
| 204 | eprintln!("nemo_relay: py_to_json failed in tool fn for '{name}': {e}"); |
| 205 | args.clone() |
| 206 | }) |
| 207 | }) |
| 208 | }) |
| 209 | } |
| 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 { |