use super::args::{EnrichArgs, EnrichOperation, ReEmbedTarget};
use crate::errors::AppError;
use rusqlite::Connection;
mod chunks;
mod entities;
mod memories;
mod name_filter;
mod relationships;
pub(in crate::commands::enrich) mod sql;
mod stream;
pub(in crate::commands::enrich) use stream::scan_operation_for_each;
pub(super) use super::quality_sample::*;
pub(super) use super::scan_ec::*;
pub(super) use chunks::*;
pub(super) use entities::*;
pub(super) use memories::*;
pub(super) use name_filter::*;
pub(super) use relationships::*;
#[cfg(test)]
#[path = "../scan_backlog_tests.rs"]
mod backlog_tests;
#[cfg(test)]
#[path = "../scan_candidate_tests.rs"]
mod candidate_tests;
#[cfg(test)]
#[path = "../scan_entity_pair_tests.rs"]
mod entity_pair_tests;
#[cfg(test)]
#[path = "../scan_reembed_target_tests.rs"]
mod reembed_target_tests;
#[cfg(test)]
#[path = "../scan_rss_tests.rs"]
mod rss_tests;
#[cfg(test)]
#[path = "../scan_test_fixtures.rs"]
mod test_fixtures;
pub(super) fn scan_operation(
conn: &Connection,
namespace: &str,
args: &EnrichArgs,
) -> Result<Vec<String>, AppError> {
let name_filter = resolve_name_filter(args)?;
let page_size = args.scan_page_size();
match args.operation() {
EnrichOperation::MemoryBindings => {
let rows = scan_unbound_memories(conn, namespace, args.limit, &name_filter, page_size)?;
Ok(rows.into_iter().map(|(_, name)| name).collect())
}
EnrichOperation::AugmentBindings => {
scan_bound_memories_for_augment(conn, namespace, args.limit, &name_filter)
}
EnrichOperation::EntityDescriptions => {
let rows = scan_entities_without_description(
conn,
namespace,
args.limit,
&name_filter,
args.force_redescribe,
)?;
Ok(rows.into_iter().map(|(_, name, _)| name).collect())
}
EnrichOperation::BodyEnrich => {
let rows = scan_short_body_memories(
conn,
namespace,
args.min_output_chars,
args.limit,
&name_filter,
page_size,
)?;
Ok(rows.into_iter().map(|(_, name)| name).collect())
}
EnrichOperation::ReEmbed => {
let mut keys: Vec<String> = Vec::new();
if matches!(args.target, ReEmbedTarget::Memories | ReEmbedTarget::All) {
let rows = scan_memories_without_embeddings(
conn,
namespace,
args.limit,
&name_filter,
page_size,
)?;
keys.extend(rows.into_iter().map(|(_, name)| name));
}
if matches!(args.target, ReEmbedTarget::Entities | ReEmbedTarget::All) {
let rows = scan_entities_missing_embeddings(
conn,
namespace,
args.limit,
&name_filter,
page_size,
)?;
keys.extend(rows.into_iter().map(|(_, name)| format!("entity:{name}")));
}
if matches!(args.target, ReEmbedTarget::Chunks | ReEmbedTarget::All) {
let ids = scan_chunks_missing_embeddings(
conn,
namespace,
args.limit,
&name_filter,
page_size,
)?;
keys.extend(ids.into_iter().map(|id| format!("chunk:{id}")));
}
Ok(keys)
}
EnrichOperation::WeightCalibrate => {
let rows = scan_weight_candidates(conn, namespace, args.limit)?;
Ok(rows
.into_iter()
.map(|(id, _, _, _, _)| id.to_string())
.collect())
}
EnrichOperation::RelationReclassify => {
let rows = scan_generic_relations(conn, namespace, args.limit)?;
Ok(rows
.into_iter()
.map(|(id, _, _, _)| id.to_string())
.collect())
}
EnrichOperation::EntityConnect | EnrichOperation::CrossDomainBridges => {
let pairs = scan_isolated_entity_pairs(conn, namespace, args.limit)?;
Ok(pairs
.into_iter()
.map(|(id1, _, id2, _)| format_pair_key(id1, id2))
.collect())
}
EnrichOperation::EntityTypeValidate => {
let rows = scan_entities_for_type_validation(conn, namespace, args.limit)?;
Ok(rows.into_iter().map(|(_, name, _)| name).collect())
}
EnrichOperation::DescriptionEnrich => {
let rows = scan_generic_descriptions(conn, namespace, args.limit)?;
Ok(rows.into_iter().map(|(_, name, _)| name).collect())
}
EnrichOperation::DomainClassify
| EnrichOperation::GraphAudit
| EnrichOperation::DeepResearchSynth
| EnrichOperation::BodyExtract => {
scan_all_memory_names(conn, namespace, args.limit, &name_filter, page_size)
}
}
}