use crate::agent::AGENT_AGREEMENT_FIELDNAME;
use crate::agent::Agent;
use crate::agent::document::DocumentTraits;
use crate::cli_utils::get_storage_default_for_cli;
use crate::cli_utils::set_file_list;
use crate::shared::document_add_agreement;
use crate::shared::document_check_agreement;
use crate::shared::document_create;
use crate::shared::document_load_and_save;
use crate::shared::document_sign_agreement;
use std::error::Error;
use std::process;
#[allow(clippy::too_many_arguments)]
pub fn create_documents(
agent: &mut Agent,
filename: Option<&String>,
directory: Option<&String>,
outputfilename: Option<&String>,
attachments: Option<&str>,
embed: Option<bool>,
no_save: bool,
schema: Option<&String>,
) -> Result<(), Box<dyn Error>> {
let storage = get_storage_default_for_cli();
if outputfilename.is_some() && directory.is_some() {
eprintln!(
"Error: if there is a directory you can't name the file the same for multiple files."
);
process::exit(1);
}
if filename.is_none() && directory.is_none() && attachments.is_none() {
return Err(
"You must specify either a filename (-f), directory (-d), or attachments (--attach)."
.into(),
);
}
let files: Vec<String> =
set_file_list(storage.as_ref().unwrap(), filename, directory, attachments)
.expect("Failed to determine file list");
let files_to_process = if files.is_empty() && attachments.is_some() {
println!("DEBUG: Attachment-only mode detected, creating empty document");
vec![String::new()] } else {
println!("DEBUG: Using files list: {:?}", files);
files
};
println!("DEBUG: Processing {} files", files_to_process.len());
for file in &files_to_process {
println!("DEBUG: Processing file: '{}'", file);
let document_string: String =
if filename.is_none() && directory.is_none() && attachments.is_some() {
println!("DEBUG: Creating empty document string");
"{}".to_string()
} else if !file.is_empty() {
println!("DEBUG: Reading document file: {}", file);
let content_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(file, None)
.unwrap_or_else(|_| panic!("Failed to load document file: {}", file));
String::from_utf8(content_bytes)
.unwrap_or_else(|_| panic!("Document file {} is not valid UTF-8", file))
} else {
eprintln!("Warning: Empty file path encountered in loop.");
"{}".to_string()
};
println!("DEBUG: Document string: {}", document_string);
println!(
"DEBUG: Calling document_create with attachments: {:?}",
attachments
);
let result = document_create(
agent,
&document_string,
schema.cloned(),
outputfilename.cloned(),
no_save,
attachments,
embed,
)
.expect("document_create");
println!(
"DEBUG: document_create succeeded, result length: {}",
result.len()
);
if no_save {
println!("{}", result);
} else {
println!("DEBUG: Document saved (no_save=false)");
}
}
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub fn update_documents(
agent: &mut Agent,
new_filename: &String,
original_filename: &String,
outputfilename: Option<&String>,
attachment_links: Option<Vec<String>>,
embed: Option<bool>,
no_save: bool,
schema: Option<&String>,
) -> Result<(), Box<dyn Error>> {
let storage = get_storage_default_for_cli();
if let Some(schema_file) = schema {
let schema_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(schema_file, None)
.unwrap_or_else(|_| panic!("Failed to load schema file: {}", schema_file));
let _schemastring = String::from_utf8(schema_bytes)
.unwrap_or_else(|_| panic!("Schema file {} is not valid UTF-8", schema_file));
let schemas = [schema_file.clone()]; agent.load_custom_schemas(&schemas)?;
}
let new_doc_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(new_filename, None)
.unwrap_or_else(|_| panic!("Failed to load new document file: {}", new_filename));
let new_document_string = String::from_utf8(new_doc_bytes)
.unwrap_or_else(|_| panic!("New document file {} is not valid UTF-8", new_filename));
let original_doc_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(original_filename, None)
.unwrap_or_else(|_| {
panic!(
"Failed to load original document file: {}",
original_filename
)
});
let original_document_string = String::from_utf8(original_doc_bytes).unwrap_or_else(|_| {
panic!(
"Original document file {} is not valid UTF-8",
original_filename
)
});
let original_doc = agent
.load_document(&original_document_string)
.expect("document parse of original");
let original_doc_key = original_doc.getkey();
let updated_document = agent
.update_document(
&original_doc_key,
&new_document_string,
attachment_links.clone(),
embed,
)
.expect("update document");
let new_document_key = updated_document.getkey();
let new_document_filename = format!("{}.json", new_document_key.clone());
let intermediate_filename = match outputfilename {
Some(filename) => filename,
None => &new_document_filename,
};
if let Some(schema_file) = schema {
let validate_result =
agent.validate_document_with_custom_schema(schema_file, updated_document.getvalue());
match validate_result {
Ok(_doc) => {
println!("document specialised schema {} validated", new_document_key);
}
Err(e) => {
eprintln!(
"document specialised schema {} validation failed {}",
new_document_key, e
);
}
}
}
if no_save {
println!("{}", &updated_document.getvalue());
} else {
agent
.save_document(
&new_document_key,
intermediate_filename.to_string().into(),
None,
None,
)
.expect("save document");
println!("created doc {}", intermediate_filename);
}
Ok(())
}
pub fn extract_documents(
agent: &mut Agent,
schema: Option<&String>,
filename: Option<&String>,
directory: Option<&String>,
) -> Result<(), Box<dyn Error>> {
let storage = get_storage_default_for_cli();
let files: Vec<String> = set_file_list(storage.as_ref().unwrap(), filename, directory, None)
.expect("Failed to determine file list");
let load_only = false;
for file in &files {
let content_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(file, None)
.unwrap_or_else(|_| panic!("Failed to load document file: {}", file));
let document_string = String::from_utf8(content_bytes)
.unwrap_or_else(|_| panic!("Document file {} is not valid UTF-8", file));
let result = document_load_and_save(
agent,
&document_string,
schema.cloned(),
None,
Some(true),
Some(true),
load_only,
)
.expect("reason");
println!("{}", result);
}
Ok(())
}
pub fn verify_documents(
agent: &mut Agent,
schema: Option<&String>,
filename: Option<&String>,
directory: Option<&String>,
) -> Result<(), Box<dyn Error>> {
let storage = get_storage_default_for_cli();
let files: Vec<String> = set_file_list(storage.as_ref().unwrap(), filename, directory, None)
.expect("Failed to determine file list");
for file in &files {
let load_only = true;
let content_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(file, None)
.unwrap_or_else(|_| panic!("Failed to load document file: {}", file));
let document_string = String::from_utf8(content_bytes)
.unwrap_or_else(|_| panic!("Document file {} is not valid UTF-8", file));
let result = document_load_and_save(
agent,
&document_string,
schema.cloned(),
None,
None,
None,
load_only,
)
.expect("reason");
println!("{}", result);
}
Ok(())
}
pub fn sign_documents(
agent: &mut Agent,
schema: Option<&String>,
filename: Option<&String>,
directory: Option<&String>,
) -> Result<(), Box<dyn Error>> {
let storage = get_storage_default_for_cli();
let files: Vec<String> = set_file_list(storage.as_ref().unwrap(), filename, directory, None)
.expect("Failed to determine file list");
let no_save = false;
for file in &files {
let content_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(file, None)
.unwrap_or_else(|_| panic!("Failed to load document file: {}", file));
let document_string = String::from_utf8(content_bytes)
.unwrap_or_else(|_| panic!("Document file {} is not valid UTF-8", file));
let result = document_sign_agreement(
agent,
&document_string,
schema.cloned(),
None,
None,
None,
no_save,
Some(AGENT_AGREEMENT_FIELDNAME.to_string()),
)
.expect("reason");
println!("{}", result);
}
Ok(())
}
pub fn create_agreement(
agent: &mut Agent,
agentids: Vec<String>,
filename: Option<&String>,
schema: Option<&String>,
no_save: bool,
directory: Option<&String>,
) -> Result<(), Box<dyn Error>> {
let storage = get_storage_default_for_cli();
let files: Vec<String> = set_file_list(storage.as_ref().unwrap(), filename, directory, None)
.expect("Failed to determine file list");
for file in &files {
let content_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(file, None)
.unwrap_or_else(|_| panic!("Failed to load document file: {}", file));
let document_string = String::from_utf8(content_bytes)
.unwrap_or_else(|_| panic!("Document file {} is not valid UTF-8", file));
let result = document_add_agreement(
agent,
&document_string,
agentids.clone(),
schema.cloned(),
None,
None,
None,
None,
None,
no_save,
Some(AGENT_AGREEMENT_FIELDNAME.to_string()),
)
.expect("reason");
println!("{}", result);
}
Ok(())
}
pub fn check_agreement(
agent: &mut Agent,
schema: Option<&String>,
filename: Option<&String>,
directory: Option<&String>,
) -> Result<(), Box<dyn Error>> {
let storage = get_storage_default_for_cli();
let files: Vec<String> = set_file_list(storage.as_ref().unwrap(), filename, directory, None)
.expect("Failed to determine file list");
for file in &files {
let content_bytes = storage
.as_ref()
.expect("Storage must be initialized for this command")
.get_file(file, None)
.unwrap_or_else(|_| panic!("Failed to load document file: {}", file));
let document_string = String::from_utf8(content_bytes)
.unwrap_or_else(|_| panic!("Document file {} is not valid UTF-8", file));
let result = document_check_agreement(
agent,
&document_string,
schema.cloned(),
Some(AGENT_AGREEMENT_FIELDNAME.to_string()),
)
.expect("reason");
println!("{}", result);
}
Ok(())
}