refactor: replace Obsidian projector with standalone service (ppatlabs/obsidian)
This commit is contained in:
@@ -1,23 +1,39 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use sha2::{Digest, Sha256};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
MemoryNode, MemoryRecord, MemoryParent, Level, VectorKind, PgRepo, ObsidianProjector,
|
||||
ProjectorOpts,
|
||||
};
|
||||
use crate::{MemoryNode, Level, PgRepo};
|
||||
|
||||
/// Memory record from log (local copy for rebuild purposes)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct MemoryRecord {
|
||||
pub level: String,
|
||||
pub project: String,
|
||||
pub query_id: Option<String>,
|
||||
pub text: String,
|
||||
pub run_id: String,
|
||||
pub t: i32,
|
||||
pub source: Option<String>,
|
||||
pub parents: Vec<MemoryParent>,
|
||||
}
|
||||
|
||||
/// Parent reference for provenance
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct MemoryParent {
|
||||
pub source: String,
|
||||
pub t: i32,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
/// Rebuild options
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RebuildOpts {
|
||||
pub project: String,
|
||||
pub vault_only: bool, // Only rebuild vault, not database
|
||||
pub db_only: bool, // Only rebuild database, not vault
|
||||
pub allow_partial: bool, // Allow rebuilding from incomplete logs
|
||||
pub embedding_cache_dir: Option<PathBuf>,
|
||||
pub vault_dir: Option<PathBuf>,
|
||||
pub log_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@@ -32,7 +48,7 @@ pub struct RebuildStats {
|
||||
pub embeddings_cached: i64,
|
||||
}
|
||||
|
||||
/// Rebuild orchestrator: drop projections, rebuild from log
|
||||
/// Rebuild orchestrator: rebuild database from log (vault projection delegated to Obsidian service)
|
||||
pub struct RebuildEngine {
|
||||
repo: PgRepo,
|
||||
}
|
||||
@@ -44,12 +60,12 @@ impl RebuildEngine {
|
||||
Ok(Self { repo })
|
||||
}
|
||||
|
||||
/// Execute full rebuild: clear → insert nodes → insert edges → project vault
|
||||
/// Execute database rebuild: clear → insert nodes → insert edges
|
||||
///
|
||||
/// Order matters: nodes first (foreign key constraint), then edges, then vault projection
|
||||
/// Order matters: nodes first (foreign key constraint), then edges.
|
||||
/// Vault projection delegated to Obsidian service.
|
||||
pub async fn rebuild(&self, opts: RebuildOpts) -> Result<RebuildStats> {
|
||||
let log_dir = opts.log_dir.unwrap_or_else(|| PathBuf::from("log"));
|
||||
let vault_dir = opts.vault_dir.unwrap_or_else(|| PathBuf::from("vault"));
|
||||
let cache_dir = opts
|
||||
.embedding_cache_dir
|
||||
.clone()
|
||||
@@ -63,13 +79,11 @@ impl RebuildEngine {
|
||||
|
||||
let mut stats = RebuildStats::default();
|
||||
|
||||
// PASS 1: Clear project (if not vault-only)
|
||||
if !opts.vault_only {
|
||||
self.repo.clear_project(&opts.project).await?;
|
||||
}
|
||||
// PASS 1: Clear project
|
||||
self.repo.clear_project(&opts.project).await?;
|
||||
|
||||
// PASS 2: Insert all nodes (convert memories to nodes, batch embeddings)
|
||||
if !opts.vault_only {
|
||||
{
|
||||
let mut nodes_by_sha: HashMap<String, MemoryNode> = HashMap::new();
|
||||
let mut sha_to_level: HashMap<String, Level> = HashMap::new();
|
||||
let mut sha_to_parents: HashMap<String, Vec<String>> = HashMap::new();
|
||||
@@ -130,11 +144,6 @@ impl RebuildEngine {
|
||||
stats.embeddings_computed = 0;
|
||||
}
|
||||
|
||||
// PASS 4: Project vault (if not db-only)
|
||||
if !opts.db_only {
|
||||
ObsidianProjector::project(&log_dir, &vault_dir, ProjectorOpts::default()).await?;
|
||||
}
|
||||
|
||||
Ok(stats)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user