use crate::agent::agreement::{Agreement, AgreementOptions};
use crate::error::JacsError;
use crate::schema::utils::ValueExt;
use crate::simple::SimpleAgent;
use crate::simple::types::*;
use tracing::{debug, info};
#[must_use = "agreement document must be used or stored"]
pub fn create(
agent: &SimpleAgent,
document: &str,
agent_ids: &[String],
question: Option<&str>,
context: Option<&str>,
) -> Result<SignedDocument, JacsError> {
create_with_options(agent, document, agent_ids, question, context, None)
}
pub fn create_with_options(
agent: &SimpleAgent,
document: &str,
agent_ids: &[String],
question: Option<&str>,
context: Option<&str>,
options: Option<&AgreementOptions>,
) -> Result<SignedDocument, JacsError> {
use crate::agent::document::DocumentTraits;
use crate::schema::utils::check_document_size;
debug!(
"create_with_options() called with {} signers",
agent_ids.len()
);
check_document_size(document)?;
let default_opts = AgreementOptions::default();
let opts = options.unwrap_or(&default_opts);
let mut inner = agent.agent.lock().map_err(|e| JacsError::Internal {
message: format!("Failed to acquire agent lock: {}", e),
})?;
let jacs_doc = inner
.create_document_and_load(document, None, None)
.map_err(|e| JacsError::SigningFailed {
reason: format!("Failed to create base document: {}", e),
})?;
let agreement_doc = inner
.create_agreement_with_options(&jacs_doc.getkey(), agent_ids, question, context, None, opts)
.map_err(|e| JacsError::Internal {
message: format!("Failed to create agreement: {}", e),
})?;
info!("Agreement created: document_id={}", agreement_doc.id);
SignedDocument::from_jacs_document(agreement_doc, "agreement")
}
#[must_use = "signed agreement must be used or stored"]
pub fn sign(agent: &SimpleAgent, document: &str) -> Result<SignedDocument, JacsError> {
use crate::agent::document::DocumentTraits;
use crate::schema::utils::check_document_size;
check_document_size(document)?;
let mut inner = agent.agent.lock().map_err(|e| JacsError::Internal {
message: format!("Failed to acquire agent lock: {}", e),
})?;
let jacs_doc = inner
.load_document(document)
.map_err(|e| JacsError::DocumentMalformed {
field: "document".to_string(),
reason: e.to_string(),
})?;
let signed_doc = inner
.sign_agreement(&jacs_doc.getkey(), None)
.map_err(|e| JacsError::SigningFailed {
reason: format!("Failed to sign agreement: {}", e),
})?;
SignedDocument::from_jacs_document(signed_doc, "signed agreement")
}
#[must_use = "agreement status must be checked"]
pub fn check(agent: &SimpleAgent, document: &str) -> Result<AgreementStatus, JacsError> {
use crate::agent::document::DocumentTraits;
use crate::schema::utils::check_document_size;
check_document_size(document)?;
let mut inner = agent.agent.lock().map_err(|e| JacsError::Internal {
message: format!("Failed to acquire agent lock: {}", e),
})?;
let jacs_doc = inner
.load_document(document)
.map_err(|e| JacsError::DocumentMalformed {
field: "document".to_string(),
reason: e.to_string(),
})?;
let unsigned = jacs_doc
.agreement_unsigned_agents(None)
.map_err(|e| JacsError::Internal {
message: format!("Failed to check unsigned agents: {}", e),
})?;
let all_agents =
jacs_doc
.agreement_requested_agents(None)
.map_err(|e| JacsError::Internal {
message: format!("Failed to get agreement agents: {}", e),
})?;
let mut signers = Vec::new();
let unsigned_set: std::collections::HashSet<&String> = unsigned.iter().collect();
for agent_id in &all_agents {
let signed = !unsigned_set.contains(agent_id);
signers.push(SignerStatus {
agent_id: agent_id.clone(),
signed,
signed_at: if signed {
Some(
jacs_doc
.value
.get_path_str_or(&["jacsSignature", "date"], "")
.to_string(),
)
} else {
None
},
});
}
Ok(AgreementStatus {
complete: unsigned.is_empty(),
signers,
pending: unsigned,
})
}