use crate::functions;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
#[derive(
Debug,
Clone,
PartialEq,
Serialize,
Deserialize,
JsonSchema,
arbitrary::Arbitrary,
)]
#[schemars(rename = "functions.inventions.state.AlphaVectorLeafState")]
pub struct AlphaVectorLeafState {
#[serde(flatten)]
pub params: super::Params,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(extend("omitempty" = true))]
pub essay: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(extend("omitempty" = true))]
pub input_schema:
Option<functions::alpha_vector::expression::VectorFunctionInputSchema>,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(extend("omitempty" = true))]
pub essay_tasks: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(extend("omitempty" = true))]
pub tasks: Option<Vec<functions::alpha_vector::LeafTaskExpression>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(extend("omitempty" = true))]
#[arbitrary(with = crate::arbitrary_util::arbitrary_option_u64)]
pub tasks_length: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(extend("omitempty" = true))]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(extend("omitempty" = true))]
pub readme: Option<String>,
#[serde(skip_serializing, default)]
#[schemars(skip)]
#[arbitrary(with = crate::arbitrary_util::arbitrary_option_i64)]
pub checker_seed: Option<i64>,
}
impl AlphaVectorLeafState {
pub fn validate_initial_state(&self) -> Result<(), String> {
if let Some(ref input_schema) = self.input_schema {
let transpiled = input_schema.clone().transpile();
functions::check::check_input_schema(&transpiled)?;
}
if let (Some(input_schema), Some(tasks)) =
(&self.input_schema, &self.tasks)
{
let function = functions::alpha_vector::RemoteFunction::Leaf {
description: "placeholder".to_string(),
input_schema: input_schema.clone(),
tasks: tasks.clone(),
};
functions::alpha_vector::check::check_alpha_leaf_vector_function(
&function,
self.checker_seed,
)?;
}
Ok(())
}
pub fn read_spec_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("ReadSpec", "Read Spec", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
Ok(state.params.spec.clone())
}
})
}
pub fn read_essay_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("ReadEssay", "Read Essay", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
match &state.essay {
Some(essay) => Ok(essay.clone()),
None => Err("Essay has not been written".to_string()),
}
}
})
}
pub fn write_essay_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::schema::EssayObject,
>("WriteEssay", "Write Essay", {
let state = Arc::clone(this);
move |args| {
let args_str = match serde_json::to_string(&args) {
Ok(s) => s,
Err(e) => {
return Err(format!("Invalid argument: {}", e));
}
};
let parsed = match serde_path_to_error::deserialize::<
_,
crate::functions::inventions::schema::EssayObject,
>(
&mut serde_json::Deserializer::from_str(&args_str),
) {
Ok(o) => o,
Err(e) => {
return Err(format!("Invalid argument: {}", e,));
}
};
if parsed.essay.trim().len() == 0 {
return Err("Essay cannot be empty".to_string());
}
let mut state = state.lock().unwrap();
state.essay = Some(parsed.essay);
Ok("Ok".to_string())
}
})
}
pub fn validate_essay(this: &Arc<Mutex<Self>>) -> Result<(), String> {
let state = this.lock().unwrap();
match &state.essay {
Some(essay) => {
if essay.trim().len() == 0 {
Err("Essay cannot be empty".to_string())
} else {
Ok(())
}
}
None => Err("Essay has not been written".to_string()),
}
}
pub fn read_input_schema_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("ReadInputSchema", "Read Input Schema", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
match &state.input_schema {
Some(input_schema) => {
Ok(serde_json::to_string(input_schema).unwrap())
}
None => {
Err("Input schema has not been written".to_string())
}
}
}
})
}
pub fn write_input_schema_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::VectorInputSchemaObject,
>("WriteInputSchema", "Write Input Schema", {
let state = Arc::clone(this);
move |args| {
let wrapper: crate::functions::inventions::VectorInputSchemaObject =
serde_json::from_value(args).map_err(|e| format!("Invalid argument: {}", e))?;
let mut de =
serde_json::Deserializer::from_str(&wrapper.schema);
let input_schema = match serde_path_to_error::deserialize::<
_,
functions::alpha_vector::expression::VectorFunctionInputSchema,
>(&mut de) {
Ok(s) => s,
Err(e) => {
return Err(format!(
"Invalid input schema: {}",
e,
));
}
};
let transpiled = input_schema.clone().transpile();
match functions::check::check_input_schema(&transpiled) {
Ok(_) => (),
Err(e) => {
return Err(format!("Invalid input schema: {}", e,));
}
}
let mut state = state.lock().unwrap();
state.input_schema = Some(input_schema);
Ok("Ok".to_string())
}
})
}
pub fn validate_input_schema(
this: &Arc<Mutex<Self>>,
) -> Result<(), String> {
let state = this.lock().unwrap();
match &state.input_schema {
Some(input_schema) => {
let transpiled = input_schema.clone().transpile();
functions::check::check_input_schema(&transpiled)
}
None => Err("Input schema has not been written".to_string()),
}
}
pub fn read_essay_tasks_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("ReadEssayTasks", "Read Essay Tasks", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
match &state.essay_tasks {
Some(essay_tasks) => Ok(essay_tasks.clone()),
None => Err("Essay tasks has not been written".to_string()),
}
}
})
}
pub fn write_essay_tasks_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::schema::EssayTasksObject,
>("WriteEssayTasks", "Write Essay Tasks", {
let state = Arc::clone(this);
move |args| {
let args_str = match serde_json::to_string(&args) {
Ok(s) => s,
Err(e) => {
return Err(format!("Invalid argument: {}", e));
}
};
let parsed = match serde_path_to_error::deserialize::<
_,
crate::functions::inventions::schema::EssayTasksObject,
>(
&mut serde_json::Deserializer::from_str(&args_str),
) {
Ok(o) => o,
Err(e) => {
return Err(format!("Invalid argument: {}", e,));
}
};
if parsed.essay_tasks.trim().len() == 0 {
return Err("Essay tasks cannot be empty".to_string());
}
let mut state = state.lock().unwrap();
state.essay_tasks = Some(parsed.essay_tasks);
Ok("Ok".to_string())
}
})
}
pub fn validate_essay_tasks(this: &Arc<Mutex<Self>>) -> Result<(), String> {
let state = this.lock().unwrap();
match &state.essay_tasks {
Some(essay_tasks) => {
if essay_tasks.trim().len() == 0 {
Err("Essay tasks cannot be empty".to_string())
} else {
Ok(())
}
}
None => Err("Essay tasks has not been written".to_string()),
}
}
pub fn read_tasks_length_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("ReadTasksLength", "Read Tasks Length", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
match &state.tasks {
Some(tasks) => Ok(tasks.len().to_string()),
None => Ok("0".to_string()),
}
}
})
}
pub fn read_task_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::schema::IndexObject,
>("ReadTask", "Read Task by index", {
let state = Arc::clone(this);
move |args| {
let args_str = match serde_json::to_string(&args) {
Ok(s) => s,
Err(e) => {
return Err(format!("Invalid argument: {}", e));
}
};
let parsed = match serde_path_to_error::deserialize::<
_,
crate::functions::inventions::schema::IndexObject,
>(
&mut serde_json::Deserializer::from_str(&args_str),
) {
Ok(o) => o,
Err(e) => {
return Err(format!("Invalid argument: {}", e,));
}
};
let index = parsed.index as usize;
let state = state.lock().unwrap();
match &state.tasks {
Some(tasks) => {
if index < tasks.len() {
Ok(serde_json::to_string(&tasks[index]).unwrap())
} else {
Err("Index out of bounds".to_string())
}
}
None => Err("Tasks have not been written".to_string()),
}
}
})
}
pub fn delete_task_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::schema::IndexObject,
>("DeleteTask", "Delete Task by index", {
let state = Arc::clone(this);
move |args| {
let args_str = match serde_json::to_string(&args) {
Ok(s) => s,
Err(e) => {
return Err(format!("Invalid argument: {}", e));
}
};
let parsed = match serde_path_to_error::deserialize::<
_,
crate::functions::inventions::schema::IndexObject,
>(
&mut serde_json::Deserializer::from_str(&args_str),
) {
Ok(o) => o,
Err(e) => {
return Err(format!("Invalid argument: {}", e,));
}
};
let index = parsed.index as usize;
let mut state = state.lock().unwrap();
match &mut state.tasks {
Some(tasks) => {
if index < tasks.len() {
tasks.remove(index);
Ok(tasks.len().to_string())
} else {
Err("Index out of bounds".to_string())
}
}
None => Err("Tasks have not been written".to_string()),
}
}
})
}
pub fn append_task_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::VectorLeafTaskObject,
>("AppendTask", "Append Task", {
let state = Arc::clone(this);
move |args| {
let wrapper: crate::functions::inventions::VectorLeafTaskObject =
serde_json::from_value(args).map_err(|e| format!("Invalid argument: {}", e))?;
let task = match serde_path_to_error::deserialize::<
_,
functions::alpha_vector::LeafTaskExpression,
>(
&mut serde_json::Deserializer::from_str(&wrapper.task),
) {
Ok(t) => t,
Err(e) => {
return Err(format!("Invalid task expression: {}", e,));
}
};
let mut state = state.lock().unwrap();
match &mut state.tasks {
Some(tasks) => tasks.push(task),
None => state.tasks = Some(vec![task]),
}
Ok(state.tasks.as_ref().unwrap().len().to_string())
}
})
}
pub fn check_function_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("CheckFunction", "Check if function is valid", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
let function = functions::alpha_vector::RemoteFunction::Leaf {
description: "placeholder".to_string(),
input_schema: state.input_schema.clone().ok_or_else(
|| "Input schema has not been written".to_string(),
)?,
tasks: state.tasks.clone().ok_or_else(|| {
"Tasks have not been written".to_string()
})?,
};
match functions::alpha_vector::check::check_alpha_leaf_vector_function(
&function, state.checker_seed,
) {
Ok(_) => Ok("Function is valid".to_string()),
Err(e) => Err(format!("Function is invalid: {}", e)),
}
}
})
}
pub fn read_predicted_tasks_length_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("ReadPredictedTasksLength", "Read Predicted Tasks Length", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
match state.tasks_length {
Some(n) => Ok(n.to_string()),
None => {
Err("Predicted tasks length has not been set"
.to_string())
}
}
}
})
}
pub fn edit_predicted_tasks_length_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::schema::TasksLengthObject,
>("EditPredictedTasksLength", "Edit Predicted Tasks Length", {
let state = Arc::clone(this);
move |args| {
let args_str = match serde_json::to_string(&args) {
Ok(s) => s,
Err(e) => {
return Err(format!("Invalid argument: {}", e));
}
};
let parsed = match serde_path_to_error::deserialize::<
_,
crate::functions::inventions::schema::TasksLengthObject,
>(
&mut serde_json::Deserializer::from_str(&args_str),
) {
Ok(o) => o,
Err(e) => {
return Err(format!("Invalid argument: {}", e,));
}
};
let mut guard = state.lock().unwrap();
let min = guard.params.min_leaf_width;
let max = guard.params.max_leaf_width;
if parsed.tasks_length < min || parsed.tasks_length > max {
return Err(format!(
"Tasks length {} is outside allowed range [{}, {}]",
parsed.tasks_length, min, max,
));
}
guard.tasks_length = Some(parsed.tasks_length);
Ok("Ok".to_string())
}
})
}
pub fn validate_function(this: &Arc<Mutex<Self>>) -> Result<(), String> {
let state = this.lock().unwrap();
let tasks_length = state
.tasks_length
.ok_or_else(|| "Tasks length has not been set".to_string())?;
let actual_len =
state.tasks.as_ref().map(|t| t.len()).unwrap_or(0) as u64;
if tasks_length != actual_len {
return Err(format!(
"Tasks length {} does not match actual tasks length {}",
tasks_length, actual_len,
));
}
let function = functions::alpha_vector::RemoteFunction::Leaf {
description: "placeholder".to_string(),
input_schema: state.input_schema.clone().ok_or_else(|| {
"Input schema has not been written".to_string()
})?,
tasks: state
.tasks
.clone()
.ok_or_else(|| "Tasks have not been written".to_string())?,
};
functions::alpha_vector::check::check_alpha_leaf_vector_function(
&function,
state.checker_seed,
)
}
pub fn read_description_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::EmptyObjectJsonSchema,
>("ReadDescription", "Read Description", {
let state = Arc::clone(this);
move |_| {
let state = state.lock().unwrap();
match &state.description {
Some(description) => Ok(description.clone()),
None => Err("Description has not been written".to_string()),
}
}
})
}
pub fn write_description_tool(
this: &Arc<Mutex<Self>>,
) -> crate::functions::inventions::InventionTool {
crate::functions::inventions::InventionTool::new_sync::<
crate::functions::inventions::schema::DescriptionObject,
>("WriteDescription", "Write Description", {
let state = Arc::clone(this);
move |args| {
let args_str = match serde_json::to_string(&args) {
Ok(s) => s,
Err(e) => {
return Err(format!("Invalid argument: {}", e));
}
};
let parsed = match serde_path_to_error::deserialize::<
_,
crate::functions::inventions::schema::DescriptionObject,
>(
&mut serde_json::Deserializer::from_str(&args_str),
) {
Ok(o) => o,
Err(e) => {
return Err(format!("Invalid argument: {}", e,));
}
};
if parsed.description.trim().len() == 0 {
return Err("Description cannot be empty".to_string());
} else if parsed.description.len() > 350 {
return Err(format!(
"Description is {} bytes, exceeds maximum of 350 bytes",
parsed.description.len(),
));
}
let mut state = state.lock().unwrap();
state.description = Some(parsed.description);
Ok("Ok".to_string())
}
})
}
pub fn validate_description(this: &Arc<Mutex<Self>>) -> Result<(), String> {
let state = this.lock().unwrap();
match &state.description {
Some(description) => {
if description.trim().len() == 0 {
Err("Description cannot be empty".to_string())
} else if description.len() > 350 {
Err(format!(
"Description is {} bytes, exceeds maximum of 350 bytes",
description.len(),
))
} else {
Ok(())
}
}
None => Err("Description has not been written".to_string()),
}
}
pub fn write_readme(&mut self) {
let description = match self.description.as_deref() {
Some(description) => description,
None => return,
};
self.readme = Some(super::readme::readme(
&self.params.name,
description,
Vec::new(),
));
}
pub fn replace_placeholders(&mut self, _paths: &[crate::RemotePath]) {}
pub fn build_function(
&self,
) -> Option<crate::functions::FullRemoteFunction> {
Some(crate::functions::FullRemoteFunction::Alpha(
crate::functions::AlphaRemoteFunction::Vector(
crate::functions::alpha_vector::RemoteFunction::Leaf {
description: self.description.clone()?,
input_schema: self.input_schema.clone()?,
tasks: self.tasks.clone()?,
},
),
))
}
}
impl AlphaVectorLeafState {
pub(super) fn serialize_into_files(&self) -> super::files::Files {
super::files::Files {
parameters_json: serde_json::to_string_pretty(&self.params)
.unwrap_or_default(),
function_json: self
.build_function()
.map(|f| serde_json::to_string_pretty(&f).unwrap_or_default()),
input_schema_json: self.input_schema.as_ref().map(|s| {
serde_json::to_string_pretty(&super::InputSchema::Vector {
schema: s.clone(),
})
.unwrap_or_default()
}),
essay_md: self.essay.clone(),
essay_tasks_md: self.essay_tasks.clone(),
readme_md: self.readme.clone(),
}
}
pub(super) fn deserialize_from_files(
function: Option<functions::alpha_vector::RemoteFunction>,
files: &super::files::Files,
) -> Result<Self, super::error::Error> {
let params: super::Params = {
let mut de =
serde_json::Deserializer::from_str(&files.parameters_json);
serde_path_to_error::deserialize(&mut de).map_err(|e| {
super::error::Error::Deserialize {
file: super::files::Files::PARAMETERS_JSON,
source: e,
}
})?
};
let (input_schema, tasks, description) = match function {
Some(functions::alpha_vector::RemoteFunction::Leaf {
description,
input_schema,
tasks,
}) => (Some(input_schema), Some(tasks), Some(description)),
_ => (None, None, None),
};
Ok(Self {
params,
essay: files.essay_md.clone(),
input_schema,
essay_tasks: files.essay_tasks_md.clone(),
tasks_length: tasks.as_ref().map(|t| t.len() as u64),
tasks,
description,
readme: files.readme_md.clone(),
checker_seed: None,
})
}
}
impl super::InventionState for AlphaVectorLeafState {
fn params(this: &Arc<Mutex<Self>>) -> super::Params {
this.lock().unwrap().params.clone()
}
fn is_scalar() -> bool {
false
}
fn prompt_type() -> crate::functions::inventions::prompts::StepPromptType {
crate::functions::inventions::prompts::StepPromptType::AlphaVectorLeafFunction
}
fn object() -> crate::functions::inventions::response::streaming::Object {
crate::functions::inventions::response::streaming::Object::AlphaVectorFunctionInventionChunk
}
fn into_state(self) -> super::State {
super::State::AlphaVectorLeaf(self)
}
fn set_tasks_length(this: &Arc<Mutex<Self>>, len: u64) {
this.lock().unwrap().tasks_length = Some(len);
}
fn input_schema_json(this: &Arc<Mutex<Self>>) -> Option<String> {
this.lock()
.unwrap()
.input_schema
.as_ref()
.map(|s| serde_json::to_string(s).unwrap())
}
fn essay_tools(
this: &Arc<Mutex<Self>>,
) -> Vec<crate::functions::inventions::InventionTool> {
vec![Self::read_spec_tool(this), Self::write_essay_tool(this)]
}
fn validate_essay(this: &Arc<Mutex<Self>>) -> Result<(), String> {
AlphaVectorLeafState::validate_essay(this)
}
fn input_schema_tools(
this: &Arc<Mutex<Self>>,
) -> Vec<crate::functions::inventions::InventionTool> {
let mut tools = vec![
Self::read_spec_tool(this),
Self::read_essay_tool(this),
Self::write_input_schema_tool(this),
];
tools.extend(crate::functions::inventions::schema_tools(&[
"functions.alpha_vector.expression.VectorFunctionInputSchema",
]));
tools
}
fn validate_input_schema(this: &Arc<Mutex<Self>>) -> Result<(), String> {
AlphaVectorLeafState::validate_input_schema(this)
}
fn essay_tasks_tools(
this: &Arc<Mutex<Self>>,
) -> Vec<crate::functions::inventions::InventionTool> {
vec![
Self::read_spec_tool(this),
Self::read_essay_tool(this),
Self::read_input_schema_tool(this),
Self::write_essay_tasks_tool(this),
]
}
fn validate_essay_tasks(this: &Arc<Mutex<Self>>) -> Result<(), String> {
AlphaVectorLeafState::validate_essay_tasks(this)
}
fn tasks_tools(
this: &Arc<Mutex<Self>>,
) -> Vec<crate::functions::inventions::InventionTool> {
let mut tools = vec![
Self::read_spec_tool(this),
Self::read_essay_tool(this),
Self::read_input_schema_tool(this),
Self::read_essay_tasks_tool(this),
Self::append_task_tool(this),
Self::delete_task_tool(this),
Self::read_task_tool(this),
Self::read_tasks_length_tool(this),
Self::check_function_tool(this),
Self::read_predicted_tasks_length_tool(this),
Self::edit_predicted_tasks_length_tool(this),
];
tools.extend(crate::functions::inventions::schema_tools(&[
"functions.alpha_vector.VectorCompletionTaskExpression",
"agent.completions.message.MessageExpression",
"vector.completions.VectorResponses",
]));
tools
}
fn validate_function(this: &Arc<Mutex<Self>>) -> Result<(), String> {
AlphaVectorLeafState::validate_function(this)
}
fn build_function(
this: &Arc<Mutex<Self>>,
) -> Option<crate::functions::FullRemoteFunction> {
this.lock().unwrap().build_function()
}
fn description_tools(
this: &Arc<Mutex<Self>>,
) -> Vec<crate::functions::inventions::InventionTool> {
vec![
Self::read_spec_tool(this),
Self::read_essay_tool(this),
Self::read_input_schema_tool(this),
Self::read_essay_tasks_tool(this),
Self::read_task_tool(this),
Self::read_tasks_length_tool(this),
Self::write_description_tool(this),
]
}
fn validate_description(this: &Arc<Mutex<Self>>) -> Result<(), String> {
AlphaVectorLeafState::validate_description(this)
}
fn write_readme(this: &Arc<Mutex<Self>>) {
this.lock().unwrap().write_readme();
}
fn replace_placeholders(
this: &Arc<Mutex<Self>>,
paths: &[crate::RemotePath],
) {
this.lock().unwrap().replace_placeholders(paths);
}
}