embeddenator_cli/commands/
ingest.rs1use anyhow::Result;
4use embeddenator_fs::embrfs::EmbrFS;
5use embeddenator_vsa::ReversibleVSAConfig;
6use std::collections::HashMap;
7use std::env;
8use std::path::PathBuf;
9
10use crate::utils::logical_path_for_file_input;
11
12pub fn handle_ingest(
13 input: Vec<PathBuf>,
14 engram: PathBuf,
15 manifest: PathBuf,
16 verbose: bool,
17) -> Result<()> {
18 if verbose {
19 println!(
20 "Embeddenator v{} - Holographic Ingestion",
21 env!("CARGO_PKG_VERSION")
22 );
23 println!("=====================================");
24 }
25
26 let mut fs = EmbrFS::new();
27 let config = ReversibleVSAConfig::default();
28
29 if input.len() == 1 && input[0].is_dir() {
32 fs.ingest_directory(&input[0], verbose, &config)?;
33 } else {
34 let cwd = env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
35
36 let mut dir_prefix_counts: HashMap<String, usize> = HashMap::new();
38
39 for p in &input {
40 if !p.exists() {
41 anyhow::bail!("Input path does not exist: {}", p.display());
42 }
43
44 if p.is_dir() {
45 let base = p
46 .file_name()
47 .and_then(|s| s.to_str())
48 .filter(|s| !s.is_empty())
49 .unwrap_or("input")
50 .to_string();
51 let count = dir_prefix_counts.entry(base.clone()).or_insert(0);
52 *count += 1;
53 let prefix = if *count == 1 {
54 base
55 } else {
56 format!("{}_{}", base, count)
57 };
58
59 fs.ingest_directory_with_prefix(p, Some(&prefix), verbose, &config)?;
60 } else {
61 let logical = logical_path_for_file_input(p, &cwd);
62 fs.ingest_file(p, logical, verbose, &config)?;
63 }
64 }
65 }
66
67 fs.save_engram(&engram)?;
68 fs.save_manifest(&manifest)?;
69
70 if verbose {
71 println!("\nIngestion complete!");
72 println!(" Engram: {}", engram.display());
73 println!(" Manifest: {}", manifest.display());
74 println!(" Files: {}", fs.manifest.files.len());
75 println!(" Total chunks: {}", fs.manifest.total_chunks);
76 }
77
78 Ok(())
79}