Skip to content

Commit

Permalink
Merge branch 'main' into agallardol/add-check-method
Browse files Browse the repository at this point in the history
  • Loading branch information
agallardol committed Nov 27, 2024
2 parents 14055a8 + 71b87d5 commit 13d16f7
Show file tree
Hide file tree
Showing 8 changed files with 314 additions and 141 deletions.
113 changes: 70 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@

[![Mutable.ai Auto Wiki](https://img.shields.io/badge/Auto_Wiki-Mutable.ai-blue)](https://wiki.mutable.ai/dcSpark/shinkai-tools)

Shinkai Tools serves as the ecosystem to execute Shinkai tools, provided by the Shinkai team or third-party developers, in a secure environment. It provides a sandboxed space for executing these tools,
Shinkai Tools serves as the ecosystem to execute Shinkai tools, provided by the Shinkai team or third-party developers, in a secure environment. It provides a sandboxed space for executing these tools,
ensuring that they run safely and efficiently, while also allowing for seamless integration with Rust code.

This repository is a comprehensive collection of tools and utilities designed to facilitate the integration of JavaScript and Rust code. It provides a framework for executing Deno scripts within a Rust environment, allowing for seamless communication and data exchange between the two languages.

The primary components of this repository include:

* `apps/shinkai-tool-*` These are small Deno tools designed to perform specific tasks. Each tool is a self-contained project with its own configuration and build process, allowing for easy maintenance and updates.
* `libs/shinkai-tools-builder` type definitions to make tools more readable and easy to code.
* `libs/shinkai-tools-runner` is a Rust library used to execute a tool in a secured and performant Deno environment, providing a safe and efficient way to run tools within the Shinkai ecosystem.
- `apps/shinkai-tool-*` These are small Deno tools designed to perform specific tasks. Each tool is a self-contained project with its own configuration and build process, allowing for easy maintenance and updates.
- `libs/shinkai-tools-builder` type definitions to make tools more readable and easy to code.
- `libs/shinkai-tools-runner` is a Rust library used to execute a tool in a secured and performant Deno environment, providing a safe and efficient way to run tools within the Shinkai ecosystem.

## Documentation

General Documentation: [https://docs.shinkai.com](https://docs.shinkai.com)

More In Depth Codebase Documentation (Mutable.ai): [https://wiki.mutable.ai/dcSpark/shinkai-tools](https://wiki.mutable.ai/dcSpark/shinkai-tools)

## Getting started

### Init Typescript side

```
# In windows admin privileges is required because rquickjs-sys uses a git patch
npm ci
Expand All @@ -30,54 +29,82 @@ npx nx run-many -t build
npx nx run-many -t test
```

## How to use a tool from Rust side (using shinkai_tools_runner)

To execute a tool from the Rust side, you can follow these steps:
#### Example Usage

1. First, ensure that the tool's JavaScript file is located in the correct directory as specified in the `Cargo.toml` file.
2. In your Rust code, import the necessary modules and create a new instance of the `Tool` struct.
3. Load the tool's JavaScript file using the `load` method, passing the path to the file as an argument.
4. Once the tool is loaded, you can call its functions using the `run` method, passing any required arguments as JSON strings.
To call a tool from the Rust side, you can use the following example:

Here's an example:
```rust
use shinkai_tools_runner::built_in_tools::get_tool;
use shinkai_tools_runner::tools::tool::Tool;
use shinkai_tools_runner::{Tool, CodeFiles};
use serde_json::json;

#[tokio::main]
async fn main() {
let tool_definition = get_tool("shinkai-tool-echo").unwrap();
let tool = Tool::new(
tool_definition.code.clone().unwrap(),
serde_json::Value::Null,
None,
);
let run_result = tool
.run(serde_json::json!({ "message": "valparaíso" }), None)
.await
.unwrap();
println!("{}", run_result.data["message"]);
// > "Hello, world!"
}
```

Also you can run inline tools. The only needed structure is a run method (it can be sync or async) with two parameters:

```rust
// Define the inline tool's Deno code
let js_code = r#"
function run(configurations, params) {
return { message: `Hello, ${params.name}!` };
console.log("Environment variable:", Deno.env.get('MOUNT')); // rw files /path/to/mount1,/path/to/mount2
console.log("Environment variable:", Deno.env.get('ASSETS')); // ro files /path/to/asset1,/path/to/asset2
console.log("Environment variable:", Deno.env.get('HOME')); // rw files /path/to/home
console.log("Environment variable:", Deno.env.get('SHINKAI_NODE_LOCATION')); // https://host.docker.internal:9554 (if it's running in docker) or 127.0.0.2:9554 (if it's running in host)
return { message: `Echoing: ${params.message}` };
}
"#;
let tool = Tool::new(js_code.to_string(), serde_json::Value::Null, None);
let run_result = tool
.run(serde_json::json!({ "name": "world" }), None)
.await
.unwrap();
println!("{}", run_result.data["message"]);
// > "Hello, world!"
"#;

// Set up the code files for the tool
// It's important to note that the entrypoint must be the name of the file in the `files` map.
// In this case, the entrypoint is `main.ts` and it's mapped to the `js_code` variable.
// You can also include other files in the `files` map if your tool needs them.
let code_files = CodeFiles {
files: std::collections::HashMap::from([("main.ts".to_string(), js_code.to_string())]),
entrypoint: "main.ts".to_string(),
};

// Create a random file to be used as a mount point. Basically it's a file that could be read/write by the tool
let test_file_path = tempfile::NamedTempFile::new().unwrap().into_temp_path();
std::fs::create_dir_all(test_file_path.parent().unwrap()).unwrap();
println!("test file path: {:?}", test_file_path);
std::fs::write(&test_file_path, "1").unwrap();

// Create the tool instance
let tool = Tool::new(
code_files,
json!({}),
Some(DenoRunnerOptions {
context: ExecutionContext {
// Here you specify where the system will store all the files related to execute code
storage: execution_storage.into(),
// Here you specify the context id, which is a unique identifier for the execution context.
// Tools in the same context share the same storage.
// It creates a folder with the context id and all the files related to the execution are stored in it.
context_id: context_id.clone(),
// The execution id is a unique identifier for the execution of the tool
// It creates logs for every execution and stores them in the storage folder.
execution_id: execution_id.clone(),
// The code id is a unique identifier for the code being executed.
// Used to identify the tools that's logging in the same execution.
code_id: "js_code1".into(),
// Here you specify the files that will be mounted with read/write permissions into the Deno execution environment.
mount_files: vec![test_file_path.to_path_buf().clone()],

// Here you specify the files that will be mounted with read-only permissions into the Deno execution environment.
// assets_files: vec![test_file_path.to_path_buf().clone()],
..Default::default()
},
..Default::default()
});

// Run the tool with input data
let result = tool.run(None, json!({"message": "Hello, Shinkai!"}), None).await.unwrap();

// Print the output
println!("Tool output: {:?}", result.data["message"]); // Echoing: ${params.message}

// After the execution you can find logs in the storage folder, specifically in storage/{context_id}/logs/{execution_id}_....log
}
```

This example demonstrates how to set up and call a Shinkai tool from Rust, including how to pass input data and handle the output.

## Adding a New Shinkai Tool

To add a new Shinkai tool to this project, follow these simple steps:
Expand Down
6 changes: 6 additions & 0 deletions libs/shinkai-tools-runner/src/tools/deno_execution_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ impl DenoExecutionStorage {
e
})?;
}
log::info!("creating deno.json file");
let deno_json_path = self.code_folder_path.join("deno.json");
std::fs::write(&deno_json_path, "{}").map_err(|e| {
log::error!("failed to write deno.json file: {}", e);
e
})?;

log::info!(
"creating log file if not exists: {}",
Expand Down
Loading

0 comments on commit 13d16f7

Please sign in to comment.