Parse a tool call from Python object
(
&self,
tool_call_obj: &Bound<'_, PyAny>,
_py: Python<'_>,
)
| 571 | |
| 572 | /// Parse a tool call from Python object |
| 573 | fn parse_tool_call( |
| 574 | &self, |
| 575 | tool_call_obj: &Bound<'_, PyAny>, |
| 576 | _py: Python<'_>, |
| 577 | ) -> PyResult<LlmToolCall> { |
| 578 | // Try to extract as dictionary first |
| 579 | if let Ok(dict) = tool_call_obj.downcast::<PyDict>() { |
| 580 | let id = dict |
| 581 | .get_item("id")? |
| 582 | .map(|item| item.extract::<String>()) |
| 583 | .transpose()? |
| 584 | .unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); |
| 585 | |
| 586 | let name = dict |
| 587 | .get_item("name")? |
| 588 | .ok_or_else(|| { |
| 589 | PyErr::new::<pyo3::exceptions::PyKeyError, _>("Missing 'name' in tool call") |
| 590 | })? |
| 591 | .extract::<String>()?; |
| 592 | |
| 593 | let parameters = dict |
| 594 | .get_item("parameters")? |
| 595 | .map(|p| self.python_to_json_value(&p)) |
| 596 | .transpose()? |
| 597 | .unwrap_or(Value::Object(serde_json::Map::new())); |
| 598 | |
| 599 | return Ok(LlmToolCall { |
| 600 | id, |
| 601 | name, |
| 602 | parameters, |
| 603 | }); |
| 604 | } |
| 605 | |
| 606 | // Try to extract as JSON string |
| 607 | if let Ok(json_str) = tool_call_obj.extract::<String>() { |
| 608 | return serde_json::from_str(&json_str).map_err(|e| { |
| 609 | PyErr::new::<pyo3::exceptions::PyValueError, _>(format!( |
| 610 | "Failed to parse tool call JSON: {}", |
| 611 | e |
| 612 | )) |
| 613 | }); |
| 614 | } |
| 615 | |
| 616 | Err(PyErr::new::<pyo3::exceptions::PyTypeError, _>( |
| 617 | "Tool call must be a dictionary or JSON string", |
| 618 | )) |
| 619 | } |
| 620 | |
| 621 | /// Convert JSON value to PyDict |
| 622 | fn json_to_pydict<'a>(&self, value: &Value, py: Python<'a>) -> PyResult<Bound<'a, PyDict>> { |
no test coverage detected