use crate::repl;
use crate::utils;
use serde_json::Value;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LuaReplOptions {
pub max_output_len: usize,
}
#[derive(Clone)]
pub struct LuaRepl {
repl: Arc<repl::Repl>,
options: LuaReplOptions,
}
impl LuaRepl {
const DEFAULT_OPTIONS: LuaReplOptions = LuaReplOptions {
max_output_len: 50_000,
};
pub fn new(repl: repl::Repl) -> Self {
Self::new_with(repl, Self::DEFAULT_OPTIONS)
}
pub fn new_with(repl: repl::Repl, options: LuaReplOptions) -> Self {
Self {
repl: Arc::new(repl),
options,
}
}
pub fn tool(&self) -> aisdk::core::Tool {
use crate::tool_definition;
use aisdk::core::{Tool, tools::ToolExecute};
let repl = Arc::clone(&self.repl);
let options = self.options;
let execute_fn = Box::new(move |args: Value| -> Result<String, String> {
let source_code = match args.get("source_code") {
Some(Value::String(s)) => s.clone(),
_ => {
return Err("Missing or invalid 'source_code' parameter".to_string());
}
};
let eval_outcome = match repl.eval(&source_code) {
Ok(outcome) => outcome,
Err(err) => {
return Err(format!("REPL evaluation failed: {}", err));
}
};
let output = eval_outcome.output.join("");
let result = match eval_outcome.result {
Ok(values) => {
if values.is_empty() {
String::new()
} else {
values.join("\n")
}
}
Err(err) => format!("error: {}", err),
};
let truncated_output = utils::truncate_output(&output, options.max_output_len);
let truncated_result = utils::truncate_output(&result, options.max_output_len);
if truncated_output.is_empty() && truncated_result.is_empty() {
Ok("(no output or result)".to_string())
} else if truncated_output.is_empty() {
Ok(format!("Result: {}", truncated_result))
} else if truncated_result.is_empty() {
Ok(format!("Output: {}", truncated_output.trim_end()))
} else {
Ok(format!(
"Output: {}\nResult: {}",
truncated_output.trim_end(),
truncated_result
))
}
});
let schema_json = tool_definition::json_schema();
let input_schema: schemars::Schema = serde_json::from_value(schema_json)
.expect("Failed to convert JSON schema to schemars::Schema");
Tool {
name: tool_definition::NAME.to_string(),
description: tool_definition::DESCRIPTION.to_string(),
input_schema,
execute: ToolExecute::new(execute_fn),
}
}
}