MCPcopy Create free account
hub / github.com/NVIDIA/NeMo-Relay / wrap_py_tool_exec_intercept_fn

Function wrap_py_tool_exec_intercept_fn

crates/python/src/py_callable.rs:396–461  ·  view source on GitHub ↗

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>,
)

Source from the content-addressed store, hash-verified

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`.
396pub 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| {

Calls 2

json_to_pyFunction · 0.85
py_to_jsonFunction · 0.85