sapiens_tools 0.10.0

The tools - Sapiens
Documentation
use indoc::indoc;
use insta::assert_display_snapshot;
use pyo3::PyResult;
use sapiens::tools::toolbox::{invoke_tool, InvokeResult, Toolbox};
use sapiens_tools::conclude::ConcludeTool;
use sapiens_tools::dummy::DummyTool;
use sapiens_tools::python::PythonTool;

#[pyo3_asyncio::tokio::test]
async fn test_tool_invocation() -> PyResult<()> {
    let data = indoc! {r#"
    # Action
    ```yaml        
    tool_name: SandboxedPython
    parameters:
        code: |
            print("Hello world!")          
    ```
    "#};

    let mut toolbox = Toolbox::default();
    toolbox.add_advanced_tool(PythonTool::default()).await;

    let res = invoke_tool(toolbox, data).await;

    match res {
        InvokeResult::Success {
            tool_name, result, ..
        } => {
            assert_eq!(tool_name, "SandboxedPython");
            assert_eq!(result, "stdout: |\n  Hello world!\nstderr: ''\n");
        }
        _ => panic!("Unexpected result: {:?}", res),
    }

    Ok(())
}

#[pyo3_asyncio::tokio::test]
async fn test_tool_simple_invocation() -> PyResult<()> {
    let data = indoc! {r#"
    # Action
    ```yaml        
    tool_name: Conclude
    parameters:
        original_question: |
            print("Hello world!")
        conclusion: |
            Hello world!          
    ```
    "#};

    let mut toolbox = Toolbox::default();
    toolbox.add_advanced_tool(PythonTool::default()).await;
    toolbox.add_tool(ConcludeTool::default()).await;

    let res = invoke_tool(toolbox, data).await;

    match res {
        InvokeResult::Success {
            tool_name, result, ..
        } => {
            assert_eq!(tool_name, "Conclude");
            assert_display_snapshot!(result);
        }
        _ => panic!("Unexpected result: {:?}", res),
    }

    Ok(())
}

#[pyo3_asyncio::tokio::test]
async fn test_tool_invocation_in_python() -> PyResult<()> {
    let data = indoc! {r#"
    # Action
    ```yaml        
    tool_name: SandboxedPython
    parameters:
        code: |
            print("Hello world!")
            rooms = toolbox.invoke("Dummy", {"blah": "blah"})
            print(rooms)
            rooms = tools.Dummy(blah="blah")
            print(rooms)          
    ```
    "#};

    let mut toolbox = Toolbox::default();
    toolbox.add_advanced_tool(PythonTool::default()).await;
    toolbox.add_tool(DummyTool::default()).await;

    let res = invoke_tool(toolbox, data).await;

    match res {
        InvokeResult::Success {
            tool_name, result, ..
        } => {
            assert_eq!(tool_name, "SandboxedPython");
            assert_display_snapshot!(result);
        }
        _ => panic!("Unexpected result: {:?}", res),
    }

    Ok(())
}

#[pyo3_asyncio::tokio::test]
async fn test_exit_in_python() -> PyResult<()> {
    let data = indoc! {r#"
    # Action
    ```yaml        
    tool_name: SandboxedPython
    parameters:
        code: |
            print("Bye bye!")
            exit(0)
    ```
    "#};

    let mut toolbox = Toolbox::default();
    toolbox.add_advanced_tool(PythonTool::default()).await;
    toolbox.add_tool(DummyTool::default()).await;

    let res = invoke_tool(toolbox, data).await;

    match res {
        InvokeResult::Error { tool_name, e, .. } => {
            assert_eq!(tool_name, "SandboxedPython");
            assert_display_snapshot!(e);
        }
        _ => panic!("Unexpected result: {:?}", res),
    }

    Ok(())
}

#[pyo3_asyncio::tokio::test]
async fn test_multiple_tool_invocations() -> PyResult<()> {
    let data = indoc! {r#"
    # Action
    ```yaml        
    tool_name: SandboxedPython
    parameters:
        code: |
            print("Hello world 1!")          
    ```
    
    # And another action
    ```yaml        
    tool_name: SandboxedPython
    parameters:
        code: |
            print("Hello world 2!")          
    ```
    
    # And yet another action
    ```        
    tool_name: SandboxedPython
    input:
        code: |
            print("Hello world 3!")          
    ```
    "#};

    let mut toolbox = Toolbox::default();
    toolbox.add_advanced_tool(PythonTool::default()).await;

    let res = invoke_tool(toolbox, data).await;

    match res {
        InvokeResult::Success {
            tool_name, result, ..
        } => {
            assert_eq!(tool_name, "SandboxedPython");
            assert_display_snapshot!(result);
        }
        _ => panic!("Unexpected result: {:?}", res),
    }

    Ok(())
}

#[pyo3_asyncio::tokio::test]
async fn test_python() -> PyResult<()> {
    let mut toolbox = Toolbox::default();
    toolbox.add_tool(DummyTool::default()).await;
    toolbox.add_advanced_tool(PythonTool::default()).await;

    let data = indoc! {r#"```yaml
   tool_name: SandboxedPython
   parameters:
     code: |           
       args = {
           'blah': "hello"
       }
       output = tools.Dummy(**args)           
      
       something = output['something']                       

       print(f"And the result is: {something}")
   ```
"#};

    let res = invoke_tool(toolbox, data).await;

    match res {
        InvokeResult::Success {
            tool_name, result, ..
        } => {
            assert_eq!(tool_name, "SandboxedPython");
            assert_display_snapshot!(result);
        }
        _ => panic!("Unexpected result: {:?}", res),
    }

    Ok(())
}

#[pyo3_asyncio::tokio::test]
async fn test_python_docstring() -> PyResult<()> {
    let mut toolbox = Toolbox::default();
    toolbox.add_tool(DummyTool::default()).await;
    toolbox.add_advanced_tool(PythonTool::default()).await;

    let data = indoc! {r#"```yaml
   tool_name: SandboxedPython
   parameters:
     code: |                  
       output = help(tools.Dummy)           
       print(f"And the docstring is: {output}")
   ```
"#};

    let res = invoke_tool(toolbox, data).await;

    match res {
        InvokeResult::Success {
            tool_name, result, ..
        } => {
            assert_eq!(tool_name, "SandboxedPython");
            assert_display_snapshot!(result);
        }
        _ => panic!("Unexpected result: {:?}", res),
    }

    Ok(())
}