From cdeaed8842e1f75e2b726f1db6453e0b1660a572 Mon Sep 17 00:00:00 2001 From: Eddie Date: Tue, 4 Feb 2025 17:38:19 -0300 Subject: [PATCH 1/4] Added runner/os/tool-set fields to tools --- .../src/network/handle_commands_list.rs | 4 + .../network/v2_api/api_v2_commands_tools.rs | 66 ++-- .../tool_execution/execution_coordinator.rs | 27 +- .../tool_execution/execution_deno_dynamic.rs | 51 ++- .../execution_python_dynamic.rs | 11 +- .../native_tools/config_setup.rs | 6 +- .../shinkai-node/src/tools/tool_prompts.rs | 38 ++- .../src/api_v2/api_v2_handlers_tools.rs | 6 +- .../shinkai-http-api/src/node_commands.rs | 44 ++- .../shinkai-message-primitives/src/lib.rs | 2 +- .../src/shinkai_tool_manager.rs | 76 ++++- .../shinkai-sqlite/src/tool_playground.rs | 33 +- .../src/tools/deno_tools.rs | 196 +++++++---- .../shinkai-tools-primitives/src/tools/mod.rs | 1 + .../src/tools/python_tools.rs | 160 ++++++++- .../src/tools/shinkai_tool.rs | 34 +- .../src/tools/tool_playground.rs | 65 +++- .../src/tools/tool_types.rs | 309 ++++++++++++++++++ 18 files changed, 972 insertions(+), 157 deletions(-) create mode 100644 shinkai-libs/shinkai-tools-primitives/src/tools/tool_types.rs diff --git a/shinkai-bin/shinkai-node/src/network/handle_commands_list.rs b/shinkai-bin/shinkai-node/src/network/handle_commands_list.rs index 65ae3780c..34991cf39 100644 --- a/shinkai-bin/shinkai-node/src/network/handle_commands_list.rs +++ b/shinkai-bin/shinkai-node/src/network/handle_commands_list.rs @@ -2384,6 +2384,8 @@ impl Node { app_id, llm_provider, mounts, + runner, + operating_system, res, } => { let db_clone = Arc::clone(&self.db); @@ -2403,6 +2405,8 @@ impl Node { llm_provider, node_name, mounts, + runner, + operating_system, res, ) .await; diff --git a/shinkai-bin/shinkai-node/src/network/v2_api/api_v2_commands_tools.rs b/shinkai-bin/shinkai-node/src/network/v2_api/api_v2_commands_tools.rs index b676f2e75..0fbaf4548 100644 --- a/shinkai-bin/shinkai-node/src/network/v2_api/api_v2_commands_tools.rs +++ b/shinkai-bin/shinkai-node/src/network/v2_api/api_v2_commands_tools.rs @@ -1,43 +1,61 @@ use crate::{ - llm_provider::job_manager::JobManager, managers::IdentityManager, network::{node_error::NodeError, node_shareable_logic::download_zip_file, Node}, tools::{ - tool_definitions::definition_generation::{generate_tool_definitions, get_all_deno_tools}, tool_execution::execution_coordinator::{execute_code, execute_tool_cmd}, tool_generation::v2_create_and_send_job_message, tool_prompts::{generate_code_prompt, tool_metadata_implementation_prompt} - }, utils::environment::NodeEnvironment + llm_provider::job_manager::JobManager, + managers::IdentityManager, + network::{node_error::NodeError, node_shareable_logic::download_zip_file, Node}, + tools::{ + tool_definitions::definition_generation::{generate_tool_definitions, get_all_deno_tools}, + tool_execution::execution_coordinator::{execute_code, execute_tool_cmd}, + tool_generation::v2_create_and_send_job_message, + tool_prompts::{generate_code_prompt, tool_metadata_implementation_prompt}, + }, + utils::environment::NodeEnvironment, }; - use async_channel::Sender; +use chrono::Utc; use ed25519_dalek::{ed25519::signature::SignerMut, SigningKey}; use reqwest::StatusCode; use serde_json::{json, Map, Value}; - use shinkai_http_api::node_api_router::{APIError, SendResponseBodyData}; use shinkai_message_primitives::{ schemas::{ - inbox_name::InboxName, indexable_version::IndexableVersion, job::JobLike, job_config::JobConfig, shinkai_name::ShinkaiSubidentityType, tool_router_key::ToolRouterKey - }, shinkai_message::shinkai_message_schemas::{CallbackAction, JobCreationInfo, MessageSchemaType}, shinkai_utils::{shinkai_message_builder::ShinkaiMessageBuilder, signatures::clone_signature_secret_key} + inbox_name::InboxName, indexable_version::IndexableVersion, job::JobLike, job_config::JobConfig, + shinkai_name::ShinkaiSubidentityType, tool_router_key::ToolRouterKey, + }, + shinkai_message::shinkai_message_schemas::{CallbackAction, JobCreationInfo, MessageSchemaType}, + shinkai_utils::{shinkai_message_builder::ShinkaiMessageBuilder, signatures::clone_signature_secret_key}, }; use shinkai_message_primitives::{ schemas::{ - shinkai_name::ShinkaiName, shinkai_tools::{CodeLanguage, DynamicToolType} - }, shinkai_message::shinkai_message_schemas::JobMessage + shinkai_name::ShinkaiName, + shinkai_tools::{CodeLanguage, DynamicToolType}, + }, + shinkai_message::shinkai_message_schemas::JobMessage, }; use shinkai_sqlite::{errors::SqliteManagerError, SqliteManager}; +use shinkai_tools_primitives::tools::tool_types::{OperatingSystem, RunnerType}; use shinkai_tools_primitives::tools::{ - deno_tools::DenoTool, error::ToolError, python_tools::PythonTool, shinkai_tool::{ShinkaiTool, ShinkaiToolWithAssets}, tool_config::{OAuth, ToolConfig}, tool_output_arg::ToolOutputArg, tool_playground::ToolPlayground + deno_tools::DenoTool, + error::ToolError, + python_tools::PythonTool, + shinkai_tool::{ShinkaiTool, ShinkaiToolWithAssets}, + tool_config::{OAuth, ToolConfig}, + tool_output_arg::ToolOutputArg, + tool_playground::ToolPlayground, }; - +use std::path::PathBuf; use std::{ - collections::HashMap, env, fs::File, io::{Read, Write}, sync::Arc, time::Instant + collections::HashMap, + env, + fs::File, + io::{Read, Write}, + sync::Arc, + time::Instant, }; +use tokio::fs; use tokio::{process::Command, sync::Mutex}; -use zip::{write::FileOptions, ZipWriter}; - use x25519_dalek::PublicKey as EncryptionPublicKey; use x25519_dalek::StaticSecret as EncryptionStaticKey; - -use chrono::Utc; - -use std::path::PathBuf; -use tokio::fs; +use zip::{write::FileOptions, ZipWriter}; impl Node { /// Searches for Shinkai tools using both vector and full-text search (FTS) @@ -505,6 +523,9 @@ impl Node { sql_queries: Some(payload.metadata.sql_queries), file_inbox: None, assets: payload.assets.clone(), + runner: payload.metadata.runner, + operating_system: payload.metadata.operating_system, + tool_set: payload.metadata.tool_set, }; ShinkaiTool::Deno(tool, false) } @@ -529,6 +550,9 @@ impl Node { sql_queries: Some(payload.metadata.sql_queries), file_inbox: None, assets: payload.assets.clone(), + runner: payload.metadata.runner, + operating_system: payload.metadata.operating_system, + tool_set: payload.metadata.tool_set, }; ShinkaiTool::Python(tool, false) } @@ -882,6 +906,8 @@ impl Node { llm_provider: String, node_name: ShinkaiName, mounts: Option>, + runner: Option, + operating_system: Option>, res: Sender>, ) -> Result<(), NodeError> { if Self::validate_bearer_token(&bearer, db.clone(), &res).await.is_err() { @@ -909,6 +935,8 @@ impl Node { bearer, node_name, mounts, + runner, + operating_system, ) .await; diff --git a/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_coordinator.rs b/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_coordinator.rs index 27ab80d6e..e25a63147 100644 --- a/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_coordinator.rs +++ b/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_coordinator.rs @@ -1,13 +1,19 @@ use crate::llm_provider::job_manager::JobManager; +use crate::managers::IdentityManager; use crate::tools::tool_definitions::definition_generation::generate_tool_definitions; use crate::tools::tool_execution::execution_custom::try_to_execute_rust_tool; use crate::tools::tool_execution::execution_deno_dynamic::{check_deno_tool, execute_deno_tool}; use crate::tools::tool_execution::execution_header_generator::{check_tool, generate_execution_environment}; use crate::tools::tool_execution::execution_python_dynamic::execute_python_tool; use crate::utils::environment::fetch_node_environment; - +use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; +use chrono::Utc; +use ed25519_dalek::SigningKey; +use regex::Regex; +use reqwest::Client; use serde_json::json; use serde_json::{Map, Value}; +use sha2::{Digest, Sha256}; use shinkai_message_primitives::schemas::shinkai_name::ShinkaiName; use shinkai_message_primitives::schemas::shinkai_tools::CodeLanguage; use shinkai_message_primitives::schemas::shinkai_tools::DynamicToolType; @@ -15,21 +21,12 @@ use shinkai_message_primitives::schemas::tool_router_key::ToolRouterKey; use shinkai_sqlite::oauth_manager::OAuthToken; use shinkai_sqlite::SqliteManager; use shinkai_tools_primitives::tools::error::ToolError; - use shinkai_tools_primitives::tools::shinkai_tool::ShinkaiTool; use shinkai_tools_primitives::tools::tool_config::{OAuth, ToolConfig}; -use tokio::sync::Mutex; - -use crate::managers::IdentityManager; -use ed25519_dalek::SigningKey; - -use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine}; -use chrono::Utc; -use regex::Regex; -use reqwest::Client; -use sha2::{Digest, Sha256}; +use shinkai_tools_primitives::tools::tool_types::{OperatingSystem, RunnerType}; use std::collections::HashMap; use std::sync::Arc; +use tokio::sync::Mutex; use x25519_dalek::PublicKey as EncryptionPublicKey; use x25519_dalek::StaticSecret as EncryptionStaticKey; @@ -418,6 +415,8 @@ pub async fn execute_code( bearer: String, node_name: ShinkaiName, mounts: Option>, + runner: Option, + operating_system: Option>, ) -> Result { eprintln!("[execute_code] tool_type: {}", tool_type); // Route based on the prefix @@ -439,6 +438,8 @@ pub async fn execute_code( support_files, code, mounts, + runner, + operating_system, ) .await } @@ -459,6 +460,8 @@ pub async fn execute_code( support_files, code, mounts, + runner, + operating_system, ) .await } diff --git a/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_deno_dynamic.rs b/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_deno_dynamic.rs index 0ab8ab5b0..da1bf44e8 100644 --- a/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_deno_dynamic.rs +++ b/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_deno_dynamic.rs @@ -3,11 +3,12 @@ use std::path::PathBuf; use serde_json::{Map, Value}; use shinkai_message_primitives::schemas::shinkai_name::ShinkaiName; -use shinkai_tools_primitives::tools::deno_tools::{DenoTool, ToolResult}; +use shinkai_tools_primitives::tools::deno_tools::DenoTool; use shinkai_tools_primitives::tools::error::ToolError; use shinkai_tools_primitives::tools::parameters::Parameters; use shinkai_tools_primitives::tools::tool_config::{OAuth, ToolConfig}; use shinkai_tools_primitives::tools::tool_output_arg::ToolOutputArg; +use shinkai_tools_primitives::tools::tool_types::{OperatingSystem, RunnerType, ToolResult}; use super::execution_header_generator::{check_tool, generate_execution_environment}; use crate::utils::environment::fetch_node_environment; @@ -27,6 +28,8 @@ pub async fn execute_deno_tool( support_files: HashMap, code: String, mounts: Option>, + runner: Option, + operating_system: Option>, ) -> Result { // Create a minimal DenoTool instance let tool = DenoTool { @@ -49,6 +52,13 @@ pub async fn execute_deno_tool( sql_queries: None, file_inbox: None, assets: None, + runner: runner.unwrap_or_default(), + operating_system: operating_system.unwrap_or(vec![ + OperatingSystem::Linux, + OperatingSystem::MacOS, + OperatingSystem::Windows, + ]), + tool_set: None, }; let env = generate_execution_environment( @@ -98,21 +108,24 @@ pub async fn execute_deno_tool( } } - match tool.run_on_demand( - env, - node_env.api_listen_address.ip().to_string(), - node_env.api_listen_address.port(), - support_files, - parameters, - extra_config, - node_storage_path, - app_id.clone(), - tool_id.clone(), - node_name, - false, - assets_files, - mounts, - ).await { + match tool + .run_on_demand( + env, + node_env.api_listen_address.ip().to_string(), + node_env.api_listen_address.port(), + support_files, + parameters, + extra_config, + node_storage_path, + app_id.clone(), + tool_id.clone(), + node_name, + false, + assets_files, + mounts, + ) + .await + { Ok(run_result) => Ok(run_result.data), Err(e) => Err(e), } @@ -145,6 +158,9 @@ pub async fn check_deno_tool( sql_queries: None, file_inbox: None, assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux, OperatingSystem::MacOS, OperatingSystem::Windows], + tool_set: None, }; let node_env = fetch_node_environment(); @@ -160,5 +176,6 @@ pub async fn check_deno_tool( node_storage_path, app_id.clone(), tool_id.clone(), - ).await + ) + .await } diff --git a/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_python_dynamic.rs b/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_python_dynamic.rs index a5730ed1f..2b93ff821 100644 --- a/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_python_dynamic.rs +++ b/shinkai-bin/shinkai-node/src/tools/tool_execution/execution_python_dynamic.rs @@ -6,12 +6,12 @@ use serde_json::{Map, Value}; use shinkai_message_primitives::schemas::shinkai_name::ShinkaiName; use shinkai_sqlite::SqliteManager; use shinkai_tools_primitives::tools::{ - deno_tools::ToolResult, error::ToolError, parameters::Parameters, python_tools::PythonTool, tool_config::{OAuth, ToolConfig}, tool_output_arg::ToolOutputArg, + tool_types::{OperatingSystem, RunnerType, ToolResult}, }; use std::sync::Arc; @@ -28,6 +28,8 @@ pub async fn execute_python_tool( support_files: HashMap, code: String, mounts: Option>, + runner: Option, + operating_system: Option>, ) -> Result { // Create a minimal DenoTool instance let tool = PythonTool { @@ -50,6 +52,13 @@ pub async fn execute_python_tool( file_inbox: None, oauth: oauth.clone(), assets: None, + runner: runner.unwrap_or_default(), + operating_system: operating_system.unwrap_or(vec![ + OperatingSystem::Linux, + OperatingSystem::MacOS, + OperatingSystem::Windows, + ]), + tool_set: None, }; let env = generate_execution_environment( diff --git a/shinkai-bin/shinkai-node/src/tools/tool_implementation/native_tools/config_setup.rs b/shinkai-bin/shinkai-node/src/tools/tool_implementation/native_tools/config_setup.rs index ffe2f2a29..c715c68b2 100644 --- a/shinkai-bin/shinkai-node/src/tools/tool_implementation/native_tools/config_setup.rs +++ b/shinkai-bin/shinkai-node/src/tools/tool_implementation/native_tools/config_setup.rs @@ -310,8 +310,8 @@ mod tests { use super::*; use shinkai_embedding::model_type::{EmbeddingModelType, OllamaTextEmbeddingsInference}; - use shinkai_tools_primitives::tools::deno_tools::ToolResult; use shinkai_tools_primitives::tools::tool_config::BasicConfig; + use shinkai_tools_primitives::tools::tool_types::{OperatingSystem, RunnerType, ToolResult}; use shinkai_tools_primitives::tools::{deno_tools::DenoTool, shinkai_tool::ShinkaiTool}; use std::path::PathBuf; use std::sync::Arc; @@ -339,7 +339,6 @@ mod tests { fn create_deno_tool() -> ShinkaiTool { let mut initial_tool = ShinkaiTool::Deno( DenoTool { - name: "Test Tool".to_string(), homepage: Some("http://127.0.0.1/index.html".to_string()), author: "Test Author".to_string(), @@ -374,6 +373,9 @@ mod tests { sql_queries: None, file_inbox: None, assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }, true, ); diff --git a/shinkai-bin/shinkai-node/src/tools/tool_prompts.rs b/shinkai-bin/shinkai-node/src/tools/tool_prompts.rs index 91f3f560d..1cf577f8d 100644 --- a/shinkai-bin/shinkai-node/src/tools/tool_prompts.rs +++ b/shinkai-bin/shinkai-node/src/tools/tool_prompts.rs @@ -326,6 +326,9 @@ pub async fn tool_metadata_implementation_prompt( "author": "{identity_name}", "version": "1.0.0", "keywords": [], + "runner": "any", + "operatingSystem": ["linux", "macos", "windows"], + "tool_set": "", "configurations": {{ "type": "object", "properties": {{}}, @@ -387,6 +390,23 @@ pub async fn tool_metadata_implementation_prompt( "type": "string" }} }}, + "runner": {{ + "type": "string", + "enum": ["any", "only_host", "only_docker"], + "description": "The type of runner required for this tool" + }}, + "operatingSystem": {{ + "type": "array", + "description": "List of supported operating systems", + "items": {{ + "type": "string", + "enum": ["linux", "macos", "windows"] + }} + }}, + "tool_set": {{ + "type": "string", + "description": "Optional Tool Set identifier" + }}, "configurations": {{ "$ref": "#/$defs/root_type", "description": "A JSON schema that defines the function's configurations" @@ -512,6 +532,8 @@ pub async fn tool_metadata_implementation_prompt( "description", "author", "keywords", + "runner", + "operatingSystem", "configurations", "parameters", "result", @@ -623,6 +645,9 @@ pub async fn tool_metadata_implementation_prompt( "creator", "shinkai" ], + "runner": "any", + "operatingSystem": ["linux", "macos", "windows"], + "tool_set": "", "configurations": {{ "type": "object", "properties": {{ @@ -665,7 +690,10 @@ pub async fn tool_metadata_implementation_prompt( "local:::__official_shinkai:::shinkai_sqlite_query_executor", "local:::shinkai_tool_echo:::shinkai_echo" ], - "oauth": {oauth_example} + "oauth": {oauth_example}, + "runner": "any", + "operatingSystem": ["linux", "macos", "windows"], + "tool_set": "" }}; ``` @@ -683,6 +711,9 @@ pub async fn tool_metadata_implementation_prompt( "content conversion", "URL to Markdown", ], + "runner": "any", + "operatingSystem": ["linux", "macos", "windows"], + "tool_set": "", "configurations": {{ "type": "object", "properties": {{}}, @@ -721,7 +752,10 @@ pub async fn tool_metadata_implementation_prompt( }} ], "tools": [], - "oauth": {oauth_example} + "oauth": {oauth_example}, + "runner": "any", + "operatingSystem": ["linux", "macos", "windows"], + "tool_set": "" }}; ``` diff --git a/shinkai-libs/shinkai-http-api/src/api_v2/api_v2_handlers_tools.rs b/shinkai-libs/shinkai-http-api/src/api_v2/api_v2_handlers_tools.rs index 29d125845..b32a3e445 100644 --- a/shinkai-libs/shinkai-http-api/src/api_v2/api_v2_handlers_tools.rs +++ b/shinkai-libs/shinkai-http-api/src/api_v2/api_v2_handlers_tools.rs @@ -2,7 +2,7 @@ use async_channel::Sender; use serde::Deserialize; use serde_json::{Map, Value}; use shinkai_message_primitives::{schemas::{shinkai_tools::{CodeLanguage, DynamicToolType}, tool_router_key::ToolRouterKey}, shinkai_message::shinkai_message_schemas::JobMessage}; -use shinkai_tools_primitives::tools::{shinkai_tool::{ShinkaiTool, ShinkaiToolWithAssets}, tool_config::OAuth, tool_playground::ToolPlayground}; +use shinkai_tools_primitives::tools::{shinkai_tool::ShinkaiToolWithAssets, tool_config::OAuth, tool_playground::ToolPlayground, tool_types::{OperatingSystem, RunnerType}}; use utoipa::{OpenApi, ToSchema}; use warp::Filter; use reqwest::StatusCode; @@ -1060,6 +1060,8 @@ pub struct CodeExecutionRequest { #[serde(deserialize_with = "deserialize_tool_router_keys")] pub tools: Vec, pub mounts: Option>, + pub runner: Option, + pub operating_system: Option>, } // Define a custom default function for oauth @@ -1119,6 +1121,8 @@ pub async fn code_execution_handler( app_id: safe_folder_name(&app_id), llm_provider: payload.llm_provider, mounts: payload.mounts, + runner: payload.runner, + operating_system: payload.operating_system, res: res_sender, }) .await diff --git a/shinkai-libs/shinkai-http-api/src/node_commands.rs b/shinkai-libs/shinkai-http-api/src/node_commands.rs index e425c6a1b..f259be705 100644 --- a/shinkai-libs/shinkai-http-api/src/node_commands.rs +++ b/shinkai-libs/shinkai-http-api/src/node_commands.rs @@ -6,16 +6,40 @@ use ed25519_dalek::VerifyingKey; use serde_json::{Map, Value}; use shinkai_message_primitives::{ schemas::{ - coinbase_mpc_config::CoinbaseMPCWalletConfig, crontab::{CronTask, CronTaskAction}, custom_prompt::CustomPrompt, identity::{Identity, StandardIdentity}, job_config::JobConfig, llm_providers::{agent::Agent, serialized_llm_provider::SerializedLLMProvider}, shinkai_name::ShinkaiName, shinkai_subscription::ShinkaiSubscription, shinkai_tool_offering::{ShinkaiToolOffering, UsageTypeInquiry}, shinkai_tools::{CodeLanguage, DynamicToolType}, smart_inbox::{SmartInbox, V2SmartInbox}, tool_router_key::ToolRouterKey, wallet_complementary::{WalletRole, WalletSource}, wallet_mixed::NetworkIdentifier - }, shinkai_message::{ - shinkai_message::ShinkaiMessage, shinkai_message_schemas::{ - APIAddOllamaModels, APIAvailableSharedItems, APIChangeJobAgentRequest, APIExportSheetPayload, APIImportSheetPayload, APISetSheetUploadedFilesPayload, APIVecFsCopyFolder, APIVecFsCopyItem, APIVecFsCreateFolder, APIVecFsDeleteFolder, APIVecFsDeleteItem, APIVecFsMoveFolder, APIVecFsMoveItem, APIVecFsRetrievePathSimplifiedJson, APIVecFsRetrieveSourceFile, APIVecFsSearchItems, ExportInboxMessagesFormat, IdentityPermissions, JobCreationInfo, JobMessage, RegistrationCodeType, V2ChatMessage - } - }, shinkai_utils::job_scope::MinimalJobScope + coinbase_mpc_config::CoinbaseMPCWalletConfig, + crontab::{CronTask, CronTaskAction}, + custom_prompt::CustomPrompt, + identity::{Identity, StandardIdentity}, + job_config::JobConfig, + llm_providers::{agent::Agent, serialized_llm_provider::SerializedLLMProvider}, + shinkai_name::ShinkaiName, + shinkai_subscription::ShinkaiSubscription, + shinkai_tool_offering::{ShinkaiToolOffering, UsageTypeInquiry}, + shinkai_tools::{CodeLanguage, DynamicToolType}, + smart_inbox::{SmartInbox, V2SmartInbox}, + tool_router_key::ToolRouterKey, + wallet_complementary::{WalletRole, WalletSource}, + wallet_mixed::NetworkIdentifier, + }, + shinkai_message::{ + shinkai_message::ShinkaiMessage, + shinkai_message_schemas::{ + APIAddOllamaModels, APIAvailableSharedItems, APIChangeJobAgentRequest, APIExportSheetPayload, + APIImportSheetPayload, APISetSheetUploadedFilesPayload, APIVecFsCopyFolder, APIVecFsCopyItem, + APIVecFsCreateFolder, APIVecFsDeleteFolder, APIVecFsDeleteItem, APIVecFsMoveFolder, APIVecFsMoveItem, + APIVecFsRetrievePathSimplifiedJson, APIVecFsRetrieveSourceFile, APIVecFsSearchItems, + ExportInboxMessagesFormat, IdentityPermissions, JobCreationInfo, JobMessage, RegistrationCodeType, + V2ChatMessage, + }, + }, + shinkai_utils::job_scope::MinimalJobScope, }; use shinkai_tools_primitives::tools::{ - shinkai_tool::{ShinkaiTool, ShinkaiToolHeader, ShinkaiToolWithAssets}, tool_config::OAuth, tool_playground::ToolPlayground + shinkai_tool::{ShinkaiTool, ShinkaiToolHeader, ShinkaiToolWithAssets}, + tool_config::OAuth, + tool_playground::ToolPlayground, + tool_types::{OperatingSystem, RunnerType}, }; // use crate::{ // prompts::custom_prompt::CustomPrompt, tools::shinkai_tool::{ShinkaiTool, ShinkaiToolHeader}, wallet::{ @@ -27,7 +51,9 @@ use x25519_dalek::PublicKey as EncryptionPublicKey; use crate::node_api_router::SendResponseBody; use super::{ - api_v1::api_v1_handlers::APIUseRegistrationCodeSuccessResponse, api_v2::api_v2_handlers_general::InitialRegistrationRequest, node_api_router::{APIError, GetPublicKeysResponse, SendResponseBodyData} + api_v1::api_v1_handlers::APIUseRegistrationCodeSuccessResponse, + api_v2::api_v2_handlers_general::InitialRegistrationRequest, + node_api_router::{APIError, GetPublicKeysResponse, SendResponseBodyData}, }; pub enum NodeCommand { @@ -944,6 +970,8 @@ pub enum NodeCommand { app_id: String, llm_provider: String, mounts: Option>, + runner: Option, + operating_system: Option>, res: Sender>, }, V2ApiGenerateToolDefinitions { diff --git a/shinkai-libs/shinkai-message-primitives/src/lib.rs b/shinkai-libs/shinkai-message-primitives/src/lib.rs index 8e4f568b8..38e40138a 100644 --- a/shinkai-libs/shinkai-message-primitives/src/lib.rs +++ b/shinkai-libs/shinkai-message-primitives/src/lib.rs @@ -1,3 +1,3 @@ -pub mod shinkai_message; pub mod schemas; +pub mod shinkai_message; pub mod shinkai_utils; diff --git a/shinkai-libs/shinkai-sqlite/src/shinkai_tool_manager.rs b/shinkai-libs/shinkai-sqlite/src/shinkai_tool_manager.rs index 1d5053026..3ed8ec95b 100644 --- a/shinkai-libs/shinkai-sqlite/src/shinkai_tool_manager.rs +++ b/shinkai-libs/shinkai-sqlite/src/shinkai_tool_manager.rs @@ -922,13 +922,15 @@ mod tests { use shinkai_message_primitives::schemas::wallet_mixed::Asset; use shinkai_message_primitives::schemas::wallet_mixed::NetworkIdentifier; use shinkai_tools_primitives::tools::deno_tools::DenoTool; - use shinkai_tools_primitives::tools::deno_tools::ToolResult; use shinkai_tools_primitives::tools::network_tool::NetworkTool; use shinkai_tools_primitives::tools::parameters::Parameters; use shinkai_tools_primitives::tools::python_tools::PythonTool; use shinkai_tools_primitives::tools::tool_config::BasicConfig; use shinkai_tools_primitives::tools::tool_config::ToolConfig; use shinkai_tools_primitives::tools::tool_output_arg::ToolOutputArg; + use shinkai_tools_primitives::tools::tool_types::OperatingSystem; + use shinkai_tools_primitives::tools::tool_types::RunnerType; + use shinkai_tools_primitives::tools::tool_types::ToolResult; use std::path::PathBuf; use tempfile::NamedTempFile; @@ -967,6 +969,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; // Wrap the DenoTool in a ShinkaiTool::Deno variant @@ -1039,6 +1044,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let deno_tool_2 = DenoTool { @@ -1061,6 +1069,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let deno_tool_3 = DenoTool { @@ -1083,6 +1094,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let shinkai_tool_1 = ShinkaiTool::Deno(deno_tool_1, true); @@ -1142,6 +1156,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let deno_tool_2 = DenoTool { @@ -1164,6 +1181,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let deno_tool_3 = DenoTool { @@ -1186,6 +1206,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; // Wrap the DenoTools in ShinkaiTool::Deno variants @@ -1275,6 +1298,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; // Wrap the DenoTool in a ShinkaiTool::Deno variant @@ -1321,6 +1347,9 @@ mod tests { sql_queries: None, file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }, DenoTool { name: "Text Analysis Helper".to_string(), @@ -1342,6 +1371,9 @@ mod tests { sql_queries: None, file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }, DenoTool { name: "Data Visualization Tool".to_string(), @@ -1363,6 +1395,9 @@ mod tests { sql_queries: None, file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }, ]; @@ -1427,6 +1462,9 @@ mod tests { file_inbox: None, assets: None, oauth: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let disabled_tool = DenoTool { @@ -1449,6 +1487,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; // Add both tools to the database @@ -1538,6 +1579,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let disabled_non_network_tool = DenoTool { @@ -1560,6 +1604,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let usage_type = UsageType::PerUse(ToolPrice::Payment(vec![AssetPayment { @@ -1690,6 +1737,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let tool2 = DenoTool { @@ -1712,6 +1762,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let tool3 = DenoTool { @@ -1734,6 +1787,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; // Add tools to database with specific vectors @@ -1816,6 +1872,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let deno_tool_v2 = DenoTool { @@ -1838,6 +1897,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; // Wrap the DenoTools in ShinkaiTool::Deno variants @@ -1932,6 +1994,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let shinkai_tool_v1 = ShinkaiTool::Deno(deno_tool_v1.clone(), true); let vector_v1 = SqliteManager::generate_vector_for_testing(0.1); @@ -1966,6 +2031,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let shinkai_tool_v2 = ShinkaiTool::Deno(deno_tool_v2.clone(), true); @@ -2029,6 +2097,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let shinkai_tool_v1 = ShinkaiTool::Python(python_tool_v1, true); manager @@ -2061,6 +2132,9 @@ mod tests { sql_queries: Some(vec![]), file_inbox: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let shinkai_tool_v2 = ShinkaiTool::Python(python_tool_v2, true); let upgraded = manager diff --git a/shinkai-libs/shinkai-sqlite/src/tool_playground.rs b/shinkai-libs/shinkai-sqlite/src/tool_playground.rs index f6d87cebb..c06d18efa 100644 --- a/shinkai-libs/shinkai-sqlite/src/tool_playground.rs +++ b/shinkai-libs/shinkai-sqlite/src/tool_playground.rs @@ -2,7 +2,10 @@ use crate::{SqliteManager, SqliteManagerError}; use rusqlite::{params, Result}; use serde_json; use shinkai_message_primitives::schemas::{indexable_version::IndexableVersion, shinkai_tools::CodeLanguage}; -use shinkai_tools_primitives::tools::tool_playground::{ToolPlayground, ToolPlaygroundMetadata}; +use shinkai_tools_primitives::tools::{ + tool_playground::{ToolPlayground, ToolPlaygroundMetadata}, + tool_types::{OperatingSystem, RunnerType}, +}; impl SqliteManager { // Adds or updates a ToolPlayground entry in the tool_playground table @@ -210,6 +213,10 @@ impl SqliteManager { let mut oauth = None; let mut assets = None; let mut homepage: Option = None; + let mut operating_system = + vec![OperatingSystem::Linux, OperatingSystem::MacOS, OperatingSystem::Windows]; + let mut runner = RunnerType::Any; + let mut tool_set = None; if let Ok(tool_data) = self.get_tool_by_key(tool_router_key) { // found data sql_queries = tool_data.sql_queries(); @@ -218,6 +225,9 @@ impl SqliteManager { oauth = tool_data.get_oauth(); assets = tool_data.get_assets(); homepage = tool_data.get_homepage(); + operating_system = tool_data.get_operating_system(); + runner = tool_data.get_runner(); + tool_set = tool_data.get_tool_set(); } Ok(ToolPlayground { @@ -236,6 +246,9 @@ impl SqliteManager { sql_queries, tools, oauth, + operating_system, + runner, + tool_set, }, tool_router_key: row.get(7)?, job_id: row.get(8)?, @@ -306,6 +319,9 @@ impl SqliteManager { sql_queries: vec![], tools: None, oauth: None, + operating_system: vec![OperatingSystem::Linux, OperatingSystem::MacOS, OperatingSystem::Windows], + runner: RunnerType::Any, + tool_set: None, }, tool_router_key: row.get(7)?, job_id: row.get(8)?, @@ -365,10 +381,11 @@ mod tests { use super::*; use shinkai_embedding::model_type::{EmbeddingModelType, OllamaTextEmbeddingsInference}; use shinkai_tools_primitives::tools::{ - deno_tools::{DenoTool, ToolResult}, + deno_tools::DenoTool, parameters::Parameters, shinkai_tool::ShinkaiTool, tool_output_arg::ToolOutputArg, + tool_types::{OperatingSystem, RunnerType, ToolResult}, }; use std::path::PathBuf; use tempfile::NamedTempFile; @@ -404,6 +421,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux], + tool_set: None, }; let shinkai_tool = ShinkaiTool::Deno(deno_tool, true); @@ -433,6 +453,9 @@ mod tests { sql_queries: vec![], tools: None, oauth: None, + operating_system: vec![OperatingSystem::Linux], + runner: RunnerType::Any, + tool_set: None, }, tool_router_key: Some(tool_router_key), job_id: "job_123".to_string(), @@ -532,6 +555,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux], + tool_set: None, }; let shinkai_tool = ShinkaiTool::Deno(deno_tool, true); @@ -605,6 +631,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux], + tool_set: None, }; let shinkai_tool = ShinkaiTool::Deno(deno_tool, true); diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs index 4ce016315..0dde57a33 100644 --- a/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs @@ -1,18 +1,11 @@ -use std::collections::HashMap; -use std::env; -use std::fs::create_dir_all; -use std::hash::RandomState; -use std::path::{Path, PathBuf}; -use std::time::{SystemTime, UNIX_EPOCH}; - use super::parameters::Parameters; use super::tool_config::{OAuth, ToolConfig}; use super::tool_output_arg::ToolOutputArg; use super::tool_playground::{SqlQuery, SqlTable}; +use super::tool_types::{OperatingSystem, RunnerType, ToolResult}; use crate::tools::error::ToolError; use crate::tools::shared_execution::{get_files_after_with_protocol, update_result_with_modified_files}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use serde_json::{Map, Value as JsonValue}; +use serde_json::Map; use shinkai_message_primitives::schemas::shinkai_name::ShinkaiName; use shinkai_message_primitives::schemas::tool_router_key::ToolRouterKey; use shinkai_tools_runner::tools::code_files::CodeFiles; @@ -22,6 +15,12 @@ use shinkai_tools_runner::tools::execution_context::ExecutionContext; use shinkai_tools_runner::tools::execution_error::ExecutionError; use shinkai_tools_runner::tools::run_result::RunResult; use shinkai_tools_runner::tools::shinkai_node_location::ShinkaiNodeLocation; +use std::collections::HashMap; +use std::env; +use std::fs::create_dir_all; +use std::hash::RandomState; +use std::path::{Path, PathBuf}; +use std::time::{SystemTime, UNIX_EPOCH}; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct DenoTool { @@ -47,6 +46,9 @@ pub struct DenoTool { pub file_inbox: Option, pub oauth: Option>, pub assets: Option>, + pub runner: RunnerType, + pub operating_system: Vec, + pub tool_set: Option, } impl DenoTool { @@ -521,61 +523,6 @@ impl DenoTool { } } -#[derive(Debug, Clone, PartialEq)] -pub struct ToolResult { - pub r#type: String, - pub properties: serde_json::Value, - pub required: Vec, -} - -impl Serialize for ToolResult { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let helper = Helper { - result_type: self.r#type.clone(), - properties: self.properties.clone(), - required: self.required.clone(), - }; - - helper.serialize(serializer) - } -} - -impl<'de> Deserialize<'de> for ToolResult { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let helper = Helper::deserialize(deserializer)?; - - Ok(ToolResult { - r#type: helper.result_type, - properties: helper.properties, - required: helper.required, - }) - } -} - -#[derive(Serialize, Deserialize)] -struct Helper { - #[serde(rename = "type", alias = "result_type")] - result_type: String, - properties: JsonValue, - required: Vec, -} - -impl ToolResult { - pub fn new(result_type: String, properties: serde_json::Value, required: Vec) -> Self { - ToolResult { - r#type: result_type, - properties, - required, - } - } -} - #[cfg(test)] mod tests { use crate::tools::tool_config::BasicConfig; @@ -756,6 +703,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux], + tool_set: None, }; // Test check_required_config_fields with no values set @@ -847,4 +797,122 @@ mod tests { assert!(!config.required); assert_eq!(config.key_value, None); } + + #[test] + fn test_deno_tool_runner_types() { + let tool = DenoTool { + name: "Test Tool".to_string(), + homepage: None, + author: "Test Author".to_string(), + version: "1.0.0".to_string(), + js_code: "".to_string(), + tools: vec![], + config: vec![], + description: "Test description".to_string(), + keywords: vec![], + input_args: Parameters::new(), + output_arg: ToolOutputArg { json: "".to_string() }, + activated: false, + embedding: None, + result: ToolResult::new("object".to_string(), json!({}), vec![]), + sql_tables: None, + sql_queries: None, + file_inbox: None, + oauth: None, + assets: None, + runner: RunnerType::OnlyDocker, + operating_system: vec![], + tool_set: None, + }; + + // Test serialization/deserialization with RunnerType + let serialized = serde_json::to_string(&tool).expect("Failed to serialize DenoTool"); + let deserialized: DenoTool = serde_json::from_str(&serialized).expect("Failed to deserialize DenoTool"); + + assert_eq!(deserialized.runner, RunnerType::OnlyDocker); + + // Test different runner types + let mut tool_any = tool.clone(); + tool_any.runner = RunnerType::Any; + let serialized = serde_json::to_string(&tool_any).expect("Failed to serialize DenoTool"); + let deserialized: DenoTool = serde_json::from_str(&serialized).expect("Failed to deserialize DenoTool"); + assert_eq!(deserialized.runner, RunnerType::Any); + } + + #[test] + fn test_deno_tool_operating_systems() { + let tool = DenoTool { + name: "Test Tool".to_string(), + homepage: None, + author: "Test Author".to_string(), + version: "1.0.0".to_string(), + js_code: "".to_string(), + tools: vec![], + config: vec![], + description: "Test description".to_string(), + keywords: vec![], + input_args: Parameters::new(), + output_arg: ToolOutputArg { json: "".to_string() }, + activated: false, + embedding: None, + result: ToolResult::new("object".to_string(), json!({}), vec![]), + sql_tables: None, + sql_queries: None, + file_inbox: None, + oauth: None, + assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux, OperatingSystem::Windows], + tool_set: None, + }; + + // Test serialization/deserialization with operating systems + let serialized = serde_json::to_string(&tool).expect("Failed to serialize DenoTool"); + let deserialized: DenoTool = serde_json::from_str(&serialized).expect("Failed to deserialize DenoTool"); + + assert_eq!(deserialized.operating_system.len(), 2); + assert!(deserialized.operating_system.contains(&OperatingSystem::Linux)); + assert!(deserialized.operating_system.contains(&OperatingSystem::Windows)); + } + + #[test] + fn test_deno_tool_tool_set() { + let tool = DenoTool { + name: "Test Tool".to_string(), + homepage: None, + author: "Test Author".to_string(), + version: "1.0.0".to_string(), + js_code: "".to_string(), + tools: vec![], + config: vec![], + description: "Test description".to_string(), + keywords: vec![], + input_args: Parameters::new(), + output_arg: ToolOutputArg { json: "".to_string() }, + activated: false, + embedding: None, + result: ToolResult::new("object".to_string(), json!({}), vec![]), + sql_tables: None, + sql_queries: None, + file_inbox: None, + oauth: None, + assets: None, + runner: RunnerType::Any, + operating_system: vec![], + tool_set: Some("test-tool-set".to_string()), + }; + + // Test serialization/deserialization with tool_set + let serialized = serde_json::to_string(&tool).expect("Failed to serialize DenoTool"); + let deserialized: DenoTool = serde_json::from_str(&serialized).expect("Failed to deserialize DenoTool"); + + assert_eq!(deserialized.tool_set, Some("test-tool-set".to_string())); + + // Test with None tool_set + let mut tool_no_set = tool.clone(); + tool_no_set.tool_set = None; + let serialized = serde_json::to_string(&tool_no_set).expect("Failed to serialize DenoTool"); + let deserialized: DenoTool = serde_json::from_str(&serialized).expect("Failed to deserialize DenoTool"); + assert_eq!(deserialized.tool_set, None); + } } diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/mod.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/mod.rs index a951e9fec..563fcd9d0 100644 --- a/shinkai-libs/shinkai-tools-primitives/src/tools/mod.rs +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/mod.rs @@ -11,3 +11,4 @@ pub mod tool_config; pub mod tool_output_arg; pub mod tool_playground; pub mod tool_router_dep; +pub mod tool_types; diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/python_tools.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/python_tools.rs index c02717d48..7794c8400 100644 --- a/shinkai-libs/shinkai-tools-primitives/src/tools/python_tools.rs +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/python_tools.rs @@ -1,9 +1,9 @@ -use std::collections::HashMap; -use std::fs::create_dir_all; -use std::path::{Path, PathBuf}; -use std::time::{SystemTime, UNIX_EPOCH}; -use std::{env, thread}; - +use super::parameters::Parameters; +use super::shared_execution::update_result_with_modified_files; +use super::tool_config::{OAuth, ToolConfig}; +use super::tool_output_arg::ToolOutputArg; +use super::tool_playground::{SqlQuery, SqlTable}; +use super::tool_types::{OperatingSystem, RunnerType, ToolResult}; use crate::tools::error::ToolError; use crate::tools::shared_execution::get_files_after_with_protocol; use shinkai_message_primitives::schemas::shinkai_name::ShinkaiName; @@ -15,14 +15,11 @@ use shinkai_tools_runner::tools::python_runner::PythonRunner; use shinkai_tools_runner::tools::python_runner_options::PythonRunnerOptions; use shinkai_tools_runner::tools::run_result::RunResult; use shinkai_tools_runner::tools::shinkai_node_location::ShinkaiNodeLocation; -use tokio::runtime::Runtime; - -use super::deno_tools::ToolResult; -use super::parameters::Parameters; -use super::shared_execution::update_result_with_modified_files; -use super::tool_config::{OAuth, ToolConfig}; -use super::tool_output_arg::ToolOutputArg; -use super::tool_playground::{SqlQuery, SqlTable}; +use std::collections::HashMap; +use std::env; +use std::fs::create_dir_all; +use std::path::{Path, PathBuf}; +use std::time::{SystemTime, UNIX_EPOCH}; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] pub struct PythonTool { @@ -48,6 +45,9 @@ pub struct PythonTool { pub file_inbox: Option, pub oauth: Option>, pub assets: Option>, + pub runner: RunnerType, + pub operating_system: Vec, + pub tool_set: Option, } impl PythonTool { @@ -331,3 +331,135 @@ impl PythonTool { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_python_tool_with_runner_type() { + let tool = PythonTool { + version: "1.0".to_string(), + name: "test_tool".to_string(), + homepage: None, + author: "test_author".to_string(), + py_code: "print('hello')".to_string(), + tools: vec![], + config: vec![], + description: "test description".to_string(), + keywords: vec!["test".to_string()], + input_args: Parameters::new(), + output_arg: ToolOutputArg { json: "".to_string() }, + activated: true, + embedding: None, + result: ToolResult::new("object".to_string(), serde_json::Value::Null, vec![]), + sql_tables: None, + sql_queries: None, + file_inbox: None, + oauth: None, + assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, + }; + + assert_eq!(tool.runner, RunnerType::OnlyHost); + } + + #[test] + fn test_python_tool_with_operating_systems() { + let tool = PythonTool { + version: "1.0".to_string(), + name: "test_tool".to_string(), + homepage: None, + author: "test_author".to_string(), + py_code: "print('hello')".to_string(), + tools: vec![], + config: vec![], + description: "test description".to_string(), + keywords: vec!["test".to_string()], + input_args: Parameters::new(), + output_arg: ToolOutputArg { json: "".to_string() }, + activated: true, + embedding: None, + result: ToolResult::new("object".to_string(), serde_json::Value::Null, vec![]), + sql_tables: None, + sql_queries: None, + file_inbox: None, + oauth: None, + assets: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux, OperatingSystem::Windows], + tool_set: None, + }; + + assert_eq!(tool.operating_system.len(), 2); + assert!(tool.operating_system.contains(&OperatingSystem::Linux)); + assert!(tool.operating_system.contains(&OperatingSystem::Windows)); + } + + #[test] + fn test_python_tool_with_tool_set() { + let tool = PythonTool { + version: "1.0".to_string(), + name: "test_tool".to_string(), + homepage: None, + author: "test_author".to_string(), + py_code: "print('hello')".to_string(), + tools: vec![], + config: vec![], + description: "test description".to_string(), + keywords: vec!["test".to_string()], + input_args: Parameters::new(), + output_arg: ToolOutputArg { json: "".to_string() }, + activated: true, + embedding: None, + result: ToolResult::new("object".to_string(), serde_json::Value::Null, vec![]), + sql_tables: None, + sql_queries: None, + file_inbox: None, + oauth: None, + assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Linux], + tool_set: Some("test_set".to_string()), + }; + + assert_eq!(tool.tool_set, Some("test_set".to_string())); + } + + #[test] + fn test_python_tool_serialization() { + let tool = PythonTool { + version: "1.0".to_string(), + name: "test_tool".to_string(), + homepage: None, + author: "test_author".to_string(), + py_code: "print('hello')".to_string(), + tools: vec![], + config: vec![], + description: "test description".to_string(), + keywords: vec!["test".to_string()], + input_args: Parameters::new(), + output_arg: ToolOutputArg { json: "".to_string() }, + activated: true, + embedding: None, + result: ToolResult::new("object".to_string(), serde_json::Value::Null, vec![]), + sql_tables: None, + sql_queries: None, + file_inbox: None, + oauth: None, + assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Linux], + tool_set: Some("test_set".to_string()), + }; + + let json = tool.to_json().unwrap(); + let deserialized = PythonTool::from_json(&json).unwrap(); + + assert_eq!(tool.runner, deserialized.runner); + assert_eq!(tool.operating_system, deserialized.operating_system); + assert_eq!(tool.tool_set, deserialized.tool_set); + } +} diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs index 608d24e82..fd124b293 100644 --- a/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs @@ -12,6 +12,7 @@ use shinkai_message_primitives::schemas::{ use super::tool_config::OAuth; use super::tool_playground::{SqlQuery, SqlTable}; +use super::tool_types::{OperatingSystem, RunnerType}; use super::{ deno_tools::DenoTool, network_tool::NetworkTool, parameters::Parameters, python_tools::PythonTool, tool_config::ToolConfig, tool_output_arg::ToolOutputArg, @@ -227,6 +228,30 @@ impl ShinkaiTool { ) } + pub fn get_runner(&self) -> RunnerType { + match self { + ShinkaiTool::Deno(d, _) => d.runner.clone(), + ShinkaiTool::Python(p, _) => p.runner.clone(), + _ => RunnerType::Any, + } + } + + pub fn get_operating_system(&self) -> Vec { + match self { + ShinkaiTool::Deno(d, _) => d.operating_system.clone(), + ShinkaiTool::Python(p, _) => p.operating_system.clone(), + _ => vec![OperatingSystem::Linux, OperatingSystem::MacOS, OperatingSystem::Windows], + } + } + + pub fn get_tool_set(&self) -> Option { + match self { + ShinkaiTool::Deno(d, _) => d.tool_set.clone(), + ShinkaiTool::Python(p, _) => p.tool_set.clone(), + _ => None, + } + } + /// Sets the embedding for the tool pub fn set_embedding(&mut self, embedding: Vec) { match self { @@ -456,7 +481,8 @@ impl From for ShinkaiTool { #[cfg(test)] mod tests { use super::*; - use crate::tools::deno_tools::{DenoTool, ToolResult}; + use crate::tools::deno_tools::DenoTool; + use crate::tools::tool_types::{OperatingSystem, RunnerType, ToolResult}; use serde_json::json; use shinkai_tools_runner::tools::tool_definition::ToolDefinition; @@ -489,6 +515,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Linux], + tool_set: None, }; // Create a ShinkaiTool instance @@ -568,6 +597,9 @@ mod tests { file_inbox: None, oauth: None, assets: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let shinkai_tool = ShinkaiTool::Deno(deno_tool, true); diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/tool_playground.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/tool_playground.rs index 6725f80d1..3fad77b51 100644 --- a/shinkai-libs/shinkai-tools-primitives/src/tools/tool_playground.rs +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/tool_playground.rs @@ -1,7 +1,7 @@ use super::{ - deno_tools::ToolResult, parameters::Parameters, tool_config::{BasicConfig, OAuth, ToolConfig}, + tool_types::{OperatingSystem, RunnerType, ToolResult}, }; use serde::{Deserialize, Deserializer, Serialize}; use serde_json::Value as JsonValue; @@ -46,7 +46,6 @@ pub struct ToolPlaygroundMetadata { pub configurations: Vec, pub parameters: Parameters, pub result: ToolResult, - #[serde(default)] #[serde(deserialize_with = "deserialize_sql_tables")] #[serde(serialize_with = "serialize_sql_tables")] @@ -61,6 +60,9 @@ pub struct ToolPlaygroundMetadata { #[serde(deserialize_with = "deserialize_tools", serialize_with = "serialize_tools")] pub tools: Option>, pub oauth: Option>, + pub runner: RunnerType, + pub operating_system: Vec, + pub tool_set: Option, } fn deserialize_configurations<'de, D>(deserializer: D) -> Result, D::Error> @@ -267,7 +269,10 @@ mod tests { "type": "string", "properties": "{}", "required": [] - } + }, + "runner": "any", + "operating_system": ["windows"], + "tool_set": null }, "tool_router_key": "example_key", "job_id": "job_123", @@ -345,7 +350,10 @@ mod tests { } }, "required": [] - } + }, + "runner": "any", + "operating_system": ["windows"], + "tool_set": null }, "job_id": "123", "job_id_history": [], @@ -398,7 +406,10 @@ mod tests { "query": "SELECT markdown FROM website_data WHERE url = :url" } ], - "sql_database_path": "test.db" + "sql_database_path": "test.db", + "runner": "any", + "operating_system": ["windows"], + "tool_set": null }, "tool_router_key": "example_key", "job_id": "job_123", @@ -437,7 +448,10 @@ mod tests { "tools": [ "local:::toolkit1:::tool1", "local:::toolkit2:::tool2:::1.0" - ] + ], + "runner": "any", + "operating_system": ["windows"], + "tool_set": null }, "tool_router_key": "example_key", "job_id": "job_123", @@ -488,7 +502,10 @@ mod tests { "not::enough::colons", "local:::toolkit1:::tool1:::version:::extra", "local:::toolkit2:::tool2" - ] + ], + "runner": "any", + "operating_system": ["macos"], + "tool_set": null }, "tool_router_key": "example_key", "job_id": "job_123", @@ -528,7 +545,10 @@ mod tests { "properties": "{}", "required": [] }, - "tools": [] + "tools": [], + "runner": "any", + "operating_system": ["linux"], + "tool_set": null }, "tool_router_key": "example_key", "job_id": "job_123", @@ -561,7 +581,10 @@ mod tests { "properties": "{}", "required": [] }, - "tools": [123, true, null, {"key": "value"}] + "tools": [123, true, null, {"key": "value"}], + "runner": "any", + "operating_system": ["linux"], + "tool_set": null }, "tool_router_key": "example_key", "job_id": "job_123", @@ -627,6 +650,9 @@ mod tests { sql_queries: vec![], tools: None, oauth: None, + runner: RunnerType::OnlyHost, + operating_system: vec![OperatingSystem::Linux], + tool_set: None, }; let serialized = serde_json::to_value(&metadata).unwrap(); @@ -664,7 +690,10 @@ mod tests { "sqlTables": [], "sqlQueries": [], "tools": null, - "oauth": null + "oauth": null, + "runner": "only_host", + "operating_system": ["linux"], + "tool_set": null }); assert_eq!(serialized, expected); @@ -760,6 +789,9 @@ mod tests { ), ]), oauth: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Windows], + tool_set: None, }; let serialized = serde_json::to_value(&metadata).unwrap(); @@ -791,7 +823,10 @@ mod tests { "local:::toolkit1:::tool1", "local:::toolkit2:::tool2:::1.0" ], - "oauth": null + "oauth": null, + "runner": "any", + "operating_system": ["windows"], + "tool_set": null }); assert_eq!(serialized, expected); @@ -839,6 +874,9 @@ mod tests { ], tools: None, oauth: None, + runner: RunnerType::Any, + operating_system: vec![OperatingSystem::Linux, OperatingSystem::MacOS], + tool_set: Some("some cool set".to_string()), }; let serialized = serde_json::to_value(&metadata).unwrap(); @@ -885,7 +923,10 @@ mod tests { } ], "tools": null, - "oauth": null + "oauth": null, + "runner": "any", + "operating_system": ["linux", "macos"], + "tool_set": "some cool set" }); assert_eq!(serialized, expected); diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/tool_types.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/tool_types.rs new file mode 100644 index 000000000..befef229f --- /dev/null +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/tool_types.rs @@ -0,0 +1,309 @@ +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_json::Value as JsonValue; + +#[derive(Copy, Debug, Clone, PartialEq)] +pub enum RunnerType { + Any, + OnlyHost, + OnlyDocker, +} + +impl Default for RunnerType { + fn default() -> Self { + RunnerType::Any + } +} + +impl RunnerType { + fn as_str(&self) -> &'static str { + match self { + RunnerType::Any => "any", + RunnerType::OnlyHost => "only_host", + RunnerType::OnlyDocker => "only_docker", + } + } + + fn from_str(s: &str) -> Result { + match s { + "any" => Ok(RunnerType::Any), + "only_host" => Ok(RunnerType::OnlyHost), + "only_docker" => Ok(RunnerType::OnlyDocker), + _ => Err(format!("Invalid runner type: {}", s)), + } + } +} + +impl Serialize for RunnerType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> Deserialize<'de> for RunnerType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + RunnerType::from_str(&s).map_err(serde::de::Error::custom) + } +} + +#[derive(Copy, Debug, Clone, PartialEq)] +pub enum OperatingSystem { + Linux, + MacOS, + Windows, +} + +impl OperatingSystem { + fn as_str(&self) -> &'static str { + match self { + OperatingSystem::Linux => "linux", + OperatingSystem::MacOS => "macos", + OperatingSystem::Windows => "windows", + } + } + + fn from_str(s: &str) -> Result { + match s { + "linux" => Ok(OperatingSystem::Linux), + "macos" => Ok(OperatingSystem::MacOS), + "windows" => Ok(OperatingSystem::Windows), + _ => Err(format!("Invalid operating system: {}", s)), + } + } +} + +impl Serialize for OperatingSystem { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(self.as_str()) + } +} + +impl<'de> Deserialize<'de> for OperatingSystem { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + OperatingSystem::from_str(&s).map_err(serde::de::Error::custom) + } +} + +#[derive(Debug, Clone, PartialEq)] +pub struct ToolResult { + pub r#type: String, + pub properties: serde_json::Value, + pub required: Vec, +} + +impl Serialize for ToolResult { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let helper = Helper { + result_type: self.r#type.clone(), + properties: self.properties.clone(), + required: self.required.clone(), + }; + + helper.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for ToolResult { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let helper = Helper::deserialize(deserializer)?; + + Ok(ToolResult { + r#type: helper.result_type, + properties: helper.properties, + required: helper.required, + }) + } +} + +#[derive(Serialize, Deserialize)] +struct Helper { + #[serde(rename = "type", alias = "result_type")] + result_type: String, + properties: JsonValue, + required: Vec, +} + +impl ToolResult { + pub fn new(result_type: String, properties: serde_json::Value, required: Vec) -> Self { + ToolResult { + r#type: result_type, + properties, + required, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + + #[test] + fn test_runner_type_serialization() { + let runner_types = vec![RunnerType::Any, RunnerType::OnlyHost, RunnerType::OnlyDocker]; + + for runner_type in runner_types { + let serialized = serde_json::to_string(&runner_type).unwrap(); + let deserialized: RunnerType = serde_json::from_str(&serialized).unwrap(); + assert_eq!(runner_type, deserialized); + } + } + + #[test] + fn test_operating_system_serialization() { + let operating_systems = vec![OperatingSystem::Linux, OperatingSystem::MacOS, OperatingSystem::Windows]; + + for os in operating_systems { + let serialized = serde_json::to_string(&os).unwrap(); + let deserialized: OperatingSystem = serde_json::from_str(&serialized).unwrap(); + assert_eq!(os, deserialized); + } + } + + #[test] + fn test_tool_result_serialization() { + let tool_result = ToolResult { + r#type: "test_type".to_string(), + properties: json!({ + "key": "value", + "number": 42 + }), + required: vec!["key".to_string()], + }; + + let serialized = serde_json::to_string(&tool_result).unwrap(); + let deserialized: ToolResult = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(tool_result.r#type, deserialized.r#type); + assert_eq!(tool_result.properties, deserialized.properties); + assert_eq!(tool_result.required, deserialized.required); + } + + #[test] + fn test_invalid_runner_type() { + let result = RunnerType::from_str("invalid"); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "Invalid runner type: invalid"); + } + + #[test] + fn test_invalid_operating_system() { + let result = OperatingSystem::from_str("invalid"); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "Invalid operating system: invalid"); + } + + #[test] + fn test_helper_serialization() { + let helper = Helper { + result_type: "test_type".to_string(), + properties: json!({ + "key": "value", + "number": 42 + }), + required: vec!["key".to_string()], + }; + + let serialized = serde_json::to_string(&helper).unwrap(); + let deserialized: Helper = serde_json::from_str(&serialized).unwrap(); + + assert_eq!(helper.result_type, deserialized.result_type); + assert_eq!(helper.properties, deserialized.properties); + assert_eq!(helper.required, deserialized.required); + } + + #[test] + fn test_runner_type_from_json_string() { + let json_str = r#""any""#; + let deserialized: RunnerType = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized, RunnerType::Any); + + let json_str = r#""only_host""#; + let deserialized: RunnerType = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized, RunnerType::OnlyHost); + + let json_str = r#""only_docker""#; + let deserialized: RunnerType = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized, RunnerType::OnlyDocker); + } + + #[test] + fn test_operating_system_from_json_string() { + let json_str = r#""linux""#; + let deserialized: OperatingSystem = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized, OperatingSystem::Linux); + + let json_str = r#""macos""#; + let deserialized: OperatingSystem = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized, OperatingSystem::MacOS); + + let json_str = r#""windows""#; + let deserialized: OperatingSystem = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized, OperatingSystem::Windows); + } + + #[test] + fn test_tool_result_from_json_string() { + let json_str = r#"{ + "type": "test_type", + "properties": { + "key": "value", + "number": 42 + }, + "required": ["key"] + }"#; + + let deserialized: ToolResult = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized.r#type, "test_type"); + assert_eq!( + deserialized.properties, + json!({ + "key": "value", + "number": 42 + }) + ); + assert_eq!(deserialized.required, vec!["key"]); + } + + #[test] + fn test_helper_from_json_string() { + let json_str = r#"{ + "type": "test_type", + "properties": { + "key": "value", + "number": 42 + }, + "required": ["key"] + }"#; + + let deserialized: Helper = serde_json::from_str(json_str).unwrap(); + assert_eq!(deserialized.result_type, "test_type"); + assert_eq!( + deserialized.properties, + json!({ + "key": "value", + "number": 42 + }) + ); + assert_eq!(deserialized.required, vec!["key"]); + } +} From 3b023aa9fa5390602faf135587692165c5b82648 Mon Sep 17 00:00:00 2001 From: Eddie Date: Tue, 4 Feb 2025 22:04:33 -0300 Subject: [PATCH 2/4] more time to complete --- shinkai-bin/shinkai-node/tests/it/native_tool_tests.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shinkai-bin/shinkai-node/tests/it/native_tool_tests.rs b/shinkai-bin/shinkai-node/tests/it/native_tool_tests.rs index f4a26fc9d..dedb1d27e 100644 --- a/shinkai-bin/shinkai-node/tests/it/native_tool_tests.rs +++ b/shinkai-bin/shinkai-node/tests/it/native_tool_tests.rs @@ -177,9 +177,9 @@ fn native_tool_test_knowledge() { { // Check that Rust tools are installed, retry up to 10 times let mut retry_count = 0; - let max_retries = 20; + let max_retries = 40; let retry_delay = Duration::from_millis(500); - + loop { tokio::time::sleep(retry_delay).await; @@ -188,7 +188,7 @@ fn native_tool_test_knowledge() { .send(NodeCommand::InternalCheckRustToolsInstallation { res: res_sender }) .await .unwrap(); - + match res_receiver.recv().await { Ok(result) => { match result { From 1df250c9374311a195455b2a88677c68fc832f58 Mon Sep 17 00:00:00 2001 From: Nico Arqueros Date: Tue, 4 Feb 2025 19:26:11 -0600 Subject: [PATCH 3/4] fix --- .../src/tools/shinkai_tool.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs index fd124b293..ff3fc15ce 100644 --- a/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/shinkai_tool.rs @@ -565,7 +565,7 @@ mod tests { "Markdown".to_string(), "HTML to Markdown".to_string(), ], - code: Some("import { getHomePath } from './shinkai-local-support.ts';\n\n...".to_string()), // Truncated for brevity + code: Some("import { getHomePath } from './shinkai-local-support.ts';\n\n...".to_string()), /* Truncated for brevity */ embedding_metadata: None, }; @@ -668,7 +668,11 @@ mod tests { "json": "" }, "name": "Shinkai: Coinbase My Address Getter", - "js_code": "import { Coinbase, CoinbaseOptions } from 'npm:@coinbase/coinbase-sdk@0.0.16';\\n\\ntype Configurations = {\\n name: string;\\n privateKey: string;\\n walletId?: string;\\n useServerSigner?: string;\\n};\\ntype Parameters = {\\n walletId?: string;\\n};\\ntype Result = {\\n address: string;\\n};\\nexport type Run, I extends Record, R extends Record> = (config: C, inputs: I) => Promise;\\n\\nexport const run: Run = async (\\n configurations: Configurations,\\n params: Parameters,\\n): Promise => {\\n const coinbaseOptions: CoinbaseOptions = {\\n apiKeyName: configurations.name,\\n privateKey: configurations.privateKey,\\n useServerSigner: configurations.useServerSigner === 'true',\\n };\\n const coinbase = new Coinbase(coinbaseOptions);\\n const user = await coinbase.getDefaultUser();\\n\\n // Prioritize walletId from Params over Config\\n const walletId = params.walletId || configurations.walletId;\\n\\n // Throw an error if walletId is not defined\\n if (!walletId) {\\n throw new Error('walletId must be defined in either params or config');\\n }\\n\\n const wallet = await user.getWallet(walletId);\\n console.log(`Wallet retrieved: `, wallet.toString());\\n\\n // Retrieve the list of balances for the wallet\\n const address = await wallet.getDefaultAddress();\\n console.log(`Default Address: `, address);\\n\\n return {\\n address: address?.getId() || '',\\n };\\n};" + "js_code": "import { Coinbase, CoinbaseOptions } from 'npm:@coinbase/coinbase-sdk@0.0.16';\\n\\ntype Configurations = {\\n name: string;\\n privateKey: string;\\n walletId?: string;\\n useServerSigner?: string;\\n};\\ntype Parameters = {\\n walletId?: string;\\n};\\ntype Result = {\\n address: string;\\n};\\nexport type Run, I extends Record, R extends Record> = (config: C, inputs: I) => Promise;\\n\\nexport const run: Run = async (\\n configurations: Configurations,\\n params: Parameters,\\n): Promise => {\\n const coinbaseOptions: CoinbaseOptions = {\\n apiKeyName: configurations.name,\\n privateKey: configurations.privateKey,\\n useServerSigner: configurations.useServerSigner === 'true',\\n };\\n const coinbase = new Coinbase(coinbaseOptions);\\n const user = await coinbase.getDefaultUser();\\n\\n // Prioritize walletId from Params over Config\\n const walletId = params.walletId || configurations.walletId;\\n\\n // Throw an error if walletId is not defined\\n if (!walletId) {\\n throw new Error('walletId must be defined in either params or config');\\n }\\n\\n const wallet = await user.getWallet(walletId);\\n console.log(`Wallet retrieved: `, wallet.toString());\\n\\n // Retrieve the list of balances for the wallet\\n const address = await wallet.getDefaultAddress();\\n console.log(`Default Address: `, address);\\n\\n return {\\n address: address?.getId() || '',\\n };\\n};", + "homepage": null, + "runner": "any", + "operating_system": ["linux"], + "tool_set": null }, false ] @@ -679,5 +683,15 @@ mod tests { eprintln!("deserialized_tool: {:?}", deserialized_tool); assert!(deserialized_tool.is_ok(), "Failed to deserialize ShinkaiTool"); + + if let Ok(ShinkaiTool::Deno(deno_tool, _)) = deserialized_tool { + assert_eq!(deno_tool.name, "Shinkai: Coinbase My Address Getter"); + assert_eq!(deno_tool.author, "Shinkai"); + assert_eq!(deno_tool.version, "1.0.0"); + assert_eq!(deno_tool.runner, RunnerType::Any); + assert_eq!(deno_tool.operating_system, vec![OperatingSystem::Linux]); + } else { + panic!("Expected Deno tool variant"); + } } } From 4521b90a69502bc467d1566afdb261b4a7f535d5 Mon Sep 17 00:00:00 2001 From: Nico Arqueros Date: Tue, 4 Feb 2025 19:28:59 -0600 Subject: [PATCH 4/4] fix --- .../src/tools/deno_tools.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs b/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs index 0dde57a33..43be25609 100644 --- a/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs +++ b/shinkai-libs/shinkai-tools-primitives/src/tools/deno_tools.rs @@ -576,13 +576,15 @@ mod tests { fn test_deserialize_deno_tool() { let json_data = r#"{ "author": "Shinkai", + "homepage": "http://example.com", "config": [ { "BasicConfig": { "description": "", "key_name": "name", "key_value": null, - "required": true + "required": true, + "type_name": null } }, { @@ -590,7 +592,8 @@ mod tests { "description": "", "key_name": "privateKey", "key_value": null, - "required": true + "required": true, + "type_name": null } }, { @@ -598,7 +601,8 @@ mod tests { "description": "", "key_name": "useServerSigner", "key_value": null, - "required": false + "required": false, + "type_name": null } } ], @@ -616,6 +620,10 @@ mod tests { "js_code": "", "keywords": [], "activated": false, + "tools": [], + "runner": "any", + "tool_set": null, + "operating_system": [], "result": { "type": "object", "properties": {}, @@ -629,6 +637,9 @@ mod tests { assert_eq!(deserialized.name, "Coinbase Wallet Creator"); assert_eq!(deserialized.version, "1.0.0"); assert_eq!(deserialized.description, "Tool for creating a Coinbase wallet"); + assert_eq!(deserialized.homepage, Some("http://example.com".to_string())); + assert_eq!(deserialized.runner, RunnerType::Any); + assert_eq!(deserialized.tool_set, None); // Verify config entries assert_eq!(deserialized.config.len(), 3);