Skip to content

Commit

Permalink
- feature: added python runner (#76)
Browse files Browse the repository at this point in the history
* - feature: added python runner

* - ci: update version
  • Loading branch information
agallardol authored Dec 6, 2024
1 parent 6ce1593 commit 32055cd
Show file tree
Hide file tree
Showing 18 changed files with 2,259 additions and 770 deletions.
12 changes: 12 additions & 0 deletions docker-images/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@

FROM denoland/deno:debian-2.1.1

SHELL ["/bin/bash", "-c"]

# Add chromium
RUN apt-get update && apt-get install -y chromium
ENV CHROME_PATH=/usr/bin/chromium

# Add python 3
RUN apt-get install -y python3 python3-pip python3-venv

WORKDIR /app
RUN python3 -m venv cache/python-venv && source cache/python-venv/bin/activate && pip install pipreqs

ENTRYPOINT ["/tini", "--"]
40 changes: 20 additions & 20 deletions libs/shinkai-tools-runner/src/lib.test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ use std::collections::HashMap;
use std::env;
use std::time::Duration;

use rstest::rstest;
use serde_json::json;

use crate::built_in_tools::get_tool;
use crate::tools::code_files::CodeFiles;
use crate::tools::deno_runner::DenoRunner;
use crate::tools::deno_runner_options::DenoRunnerOptions;
use crate::tools::deno_runner_options::RunnerType;
use crate::tools::tool::Tool;
use crate::tools::runner_type::RunnerType;

use rstest::rstest;
use serde_json::json;

#[rstest]
#[case::host(RunnerType::Host)]
Expand All @@ -25,7 +25,7 @@ async fn shinkai_tool_echo(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -54,7 +54,7 @@ async fn shinkai_tool_weather_by_city(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::json!({ "apiKey": "63d35ff6068c3103ccd1227526935675" }),
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -86,7 +86,7 @@ async fn shinkai_tool_inline(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), js_code.to_string())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -119,7 +119,7 @@ async fn shinkai_tool_inline_non_json_return(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), js_code.to_string())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand All @@ -145,7 +145,7 @@ async fn shinkai_tool_web3_eth_balance(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -178,7 +178,7 @@ async fn shinkai_tool_web3_eth_uniswap(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -217,7 +217,7 @@ async fn shinkai_tool_download_page(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -267,7 +267,7 @@ async fn max_execution_time(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), js_code.to_string())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -309,7 +309,7 @@ async fn shinkai_tool_download_page_stack_overflow(#[case] runner_type: RunnerTy
)]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -348,7 +348,7 @@ async fn shinkai_tool_leiden(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -466,7 +466,7 @@ async fn shinkai_tool_duckduckgo_search(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::Value::Null,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -512,7 +512,7 @@ async fn shinkai_tool_playwright_example(#[case] runner_type: RunnerType) {
entrypoint: "main.ts".to_string(),
};

let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
if matches!(runner_type, RunnerType::Docker) && std::env::var("CI").is_ok() {
serde_json::json!({})
Expand Down Expand Up @@ -561,7 +561,7 @@ async fn shinkai_tool_defillama_lending_tvl_rankings(#[case] runner_type: Runner
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
if matches!(runner_type, RunnerType::Docker) && std::env::var("CI").is_ok() {
serde_json::json!({})
Expand Down Expand Up @@ -616,7 +616,7 @@ async fn shinkai_tool_youtube_summary(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
configurations,
Some(DenoRunnerOptions {
Expand Down Expand Up @@ -652,7 +652,7 @@ async fn shinkai_tool_json_to_md(#[case] runner_type: RunnerType) {
files: HashMap::from([("main.ts".to_string(), tool_definition.code.clone().unwrap())]),
entrypoint: "main.ts".to_string(),
};
let tool = Tool::new(
let tool = DenoRunner::new(
code_files,
serde_json::json!({
"only_system": false
Expand Down
179 changes: 12 additions & 167 deletions libs/shinkai-tools-runner/src/tools/deno_execution_storage.rs
Original file line number Diff line number Diff line change
@@ -1,181 +1,26 @@
use std::{
io::Write,
path::{self, PathBuf},
};
use super::execution_storage::ExecutionStorage;

use super::{code_files::CodeFiles, path_buf_ext::PathBufExt};
use super::{execution_context::ExecutionContext, file_name_utils::sanitize_for_file_name};
use nanoid::nanoid;

#[derive(Default, Clone)]
pub struct DenoExecutionStorage {
pub code_files: CodeFiles,
pub context: ExecutionContext,
pub code_id: String,
pub root_folder_path: PathBuf,
pub root_code_folder_path: PathBuf,
pub code_folder_path: PathBuf,
pub code_entrypoint_file_path: PathBuf,
pub deno_cache_folder_path: PathBuf,
pub logs_folder_path: PathBuf,
pub log_file_path: PathBuf,
pub home_folder_path: PathBuf,
pub assets_folder_path: PathBuf,
pub mount_folder_path: PathBuf,
}

impl DenoExecutionStorage {
pub fn new(code: CodeFiles, context: ExecutionContext) -> Self {
let code_id = format!("{}-{}", context.code_id, nanoid!());
let root_folder_path = path::absolute(
context
.storage
.join(sanitize_for_file_name(context.context_id.clone()))
.clone(),
)
.unwrap();
let root_code_folder_path = path::absolute(root_folder_path.join("code")).unwrap();
let code_folder_path = path::absolute(root_code_folder_path.join(code_id.clone())).unwrap();
let logs_folder_path = path::absolute(root_folder_path.join("logs")).unwrap();
let log_file_path = path::absolute(logs_folder_path.join(format!(
"log_{}_{}.log",
sanitize_for_file_name(context.context_id.clone()),
sanitize_for_file_name(context.execution_id.clone())
)))
.unwrap();
let deno_cache_folder_path = path::absolute(root_folder_path.join("deno-cache")).unwrap();
let code_entrypoint_file_path = code_folder_path.join(&code.entrypoint);
Self {
code_files: code,
context,
code_folder_path,
code_id: code_id.clone(),
root_folder_path: root_folder_path.clone(),
root_code_folder_path,
code_entrypoint_file_path,
deno_cache_folder_path,
logs_folder_path: logs_folder_path.clone(),
log_file_path,
home_folder_path: root_folder_path.join("home"),
assets_folder_path: root_folder_path.join("assets"),
mount_folder_path: root_folder_path.join("mount"),
}
impl ExecutionStorage {
pub fn deno_cache_folder_path(&self) -> std::path::PathBuf {
self.cache_folder_path.join("deno")
}
pub fn init_for_deno(&self, pristine_cache: Option<bool>) -> anyhow::Result<()> {
self.init(pristine_cache)?;

pub fn init(&self, pristine_cache: Option<bool>) -> anyhow::Result<()> {
for dir in [
&self.root_folder_path,
&self.root_code_folder_path,
&self.code_folder_path,
&self.deno_cache_folder_path,
&self.logs_folder_path,
&self.home_folder_path,
&self.assets_folder_path,
&self.mount_folder_path,
] {
log::info!("creating directory: {}", dir.display());
std::fs::create_dir_all(dir).map_err(|e| {
log::error!("failed to create directory {}: {}", dir.display(), e);
e
})?;
}

log::info!(
"creating project files, entrypoint: {}",
self.code_files.entrypoint
);
log::info!("creating deno cache directory");
let deno_cache_dir = self.deno_cache_folder_path();
std::fs::create_dir_all(&deno_cache_dir).map_err(|e| {
log::error!("failed to create deno cache directory: {}", e);
e
})?;

for (path, content) in self.code_files.files.iter() {
let file_path = self.code_folder_path.join(path);
log::info!("writing file: {}", file_path.display());
if let Some(parent) = file_path.parent() {
std::fs::create_dir_all(parent).map_err(|e| {
log::error!(
"failed to create parent directory {}: {}",
parent.display(),
e
);
e
})?;
}
std::fs::write(&file_path, content).map_err(|e| {
log::error!("failed to write file {}: {}", file_path.display(), e);
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: {}",
self.log_file_path.display()
);
if !self.log_file_path.exists() {
std::fs::write(&self.log_file_path, "").map_err(|e| {
log::error!("failed to create log file: {}", e);
e
})?;
}

if pristine_cache.unwrap_or(false) {
std::fs::remove_dir_all(&self.deno_cache_folder_path)?;
std::fs::create_dir(&self.deno_cache_folder_path)?;
log::info!(
"cleared deno cache directory: {}",
self.deno_cache_folder_path.display()
);
}

Ok(())
}

pub fn append_log(&self, log: &str) -> anyhow::Result<()> {
let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S");
let log_line = format!(
"{},{},{},{},{}\n",
timestamp, self.context.context_id, self.context.execution_id, self.code_id, log,
);
let mut file = std::fs::OpenOptions::new()
.append(true)
.create(true) // Create the file if it doesn't exist
.open(self.log_file_path.clone())
.map_err(|e| {
log::error!("failed to open log file: {}", e);
e
})?;
file.write_all(log_line.as_bytes())?;
Ok(())
}

pub fn relative_to_root(&self, path: PathBuf) -> String {
let path = path.strip_prefix(&self.root_folder_path).unwrap();
path.to_path_buf().as_normalized_string()
}
}

// TODO: Validate if finally we are going to implement this feature
// We do best effort to remove ephemereal folders
// impl Drop for DenoExecutionStorage {
// fn drop(&mut self) {
// if let Err(e) = std::fs::remove_dir_all(&self.code_folder_path) {
// log::warn!(
// "failed to remove code directory {}: {}",
// self.code_folder_path.display(),
// e
// );
// } else {
// log::info!(
// "removed code directory: {}",
// self.code_folder_path.display()
// );
// }
// }
// }

#[cfg(test)]
#[path = "deno_execution_storage.test.rs"]
mod tests;
Loading

0 comments on commit 32055cd

Please sign in to comment.