Wrap a Python callable `(Json, next) -> Json` for tool execution intercepts. The `next` parameter is a `PyToolNextFn` that the Python code can `await`.
(
py_fn: Py<PyAny>,
)
| 394 | /// Wrap a Python callable `(Json, next) -> Json` for tool execution intercepts. |
| 395 | /// The `next` parameter is a `PyToolNextFn` that the Python code can `await`. |
| 396 | pub fn wrap_py_tool_exec_intercept_fn( |
| 397 | py_fn: Py<PyAny>, |
| 398 | ) -> Arc< |
| 399 | dyn Fn( |
| 400 | &str, |
| 401 | Json, |
| 402 | ToolExecutionNextFn, |
| 403 | ) -> Pin<Box<dyn Future<Output = FlowResult<Json>> + Send>> |
| 404 | + Send |
| 405 | + Sync, |
| 406 | > { |
| 407 | let py_fn = Arc::new(py_fn); |
| 408 | Arc::new(move |name: &str, args: Json, next: ToolExecutionNextFn| { |
| 409 | let py_fn = py_fn.clone(); |
| 410 | let name = name.to_string(); |
| 411 | Box::pin(async move { |
| 412 | let outcome: FlowResult< |
| 413 | Result<Json, Pin<Box<dyn Future<Output = PyResult<Py<PyAny>>> + Send>>>, |
| 414 | > = Python::attach(|py| { |
| 415 | let py_args = |
| 416 | json_to_py(py, &args).map_err(|e: PyErr| FlowError::Internal(e.to_string()))?; |
| 417 | let py_next = PyToolNextFn { inner: next }; |
| 418 | let result = py_fn |
| 419 | .call1( |
| 420 | py, |
| 421 | ( |
| 422 | &name, |
| 423 | py_args, |
| 424 | py_next |
| 425 | .into_pyobject(py) |
| 426 | .map_err(|e| FlowError::Internal(e.to_string()))? |
| 427 | .into_any(), |
| 428 | ), |
| 429 | ) |
| 430 | .map_err(|e: PyErr| FlowError::Internal(e.to_string()))?; |
| 431 | |
| 432 | let bound = result.bind(py); |
| 433 | if bound.getattr("__await__").is_ok() { |
| 434 | let future = pyo3_async_runtimes::tokio::into_future(result.into_bound(py)) |
| 435 | .map_err(|e| FlowError::Internal(e.to_string()))?; |
| 436 | Ok(Err(Box::pin(future) |
| 437 | as Pin< |
| 438 | Box<dyn Future<Output = PyResult<Py<PyAny>>> + Send>, |
| 439 | >)) |
| 440 | } else { |
| 441 | let json = |
| 442 | py_to_json(bound).map_err(|e: PyErr| FlowError::Internal(e.to_string()))?; |
| 443 | Ok(Ok(json)) |
| 444 | } |
| 445 | }); |
| 446 | |
| 447 | match outcome? { |
| 448 | Ok(json) => Ok(json), |
| 449 | Err(future) => { |
| 450 | let py_result = future |
| 451 | .await |
| 452 | .map_err(|e| FlowError::Internal(e.to_string()))?; |
| 453 | Python::attach(|py| { |