tala-daemon

The top-level orchestrator tying all TALA subsystems together. Provides the Daemon facade with four primary operations -- ingest, query, replay, and insights -- backed by an IngestPipeline that coordinates intent extraction, storage, and graph edge formation. A DaemonBuilder configures and constructs Daemon instances for both in-memory and persistent modes.

This is a library crate. The binary wrapper, Unix socket listener, and TCP server are future work.

Key Types

TypeDescription
DaemonTop-level facade: ingest, query, replay, insights
DaemonBuilderBuilder pattern for configuring and constructing a Daemon
DaemonMetricsPer-phase timing metrics for the daemon pipeline

Daemon

The unified interface to all TALA subsystems. Internally owns an IngestPipeline (which in turn owns the IntentPipeline, StorageEngine, and NarrativeGraph) and provides four public operations.

#![allow(unused)]
fn main() {
pub struct Daemon { /* private */ }
}

ingest

#![allow(unused)]
fn main() {
impl Daemon {
    /// Ingest a raw command string with execution context.
    ///
    /// Pipeline:
    /// 1. Extract intent via IntentPipeline (tokenize, embed, classify)
    /// 2. Insert into StorageEngine (WAL, HNSW index, hot buffer)
    /// 3. Semantic search for edge candidates (top-5 nearest neighbors)
    /// 4. Form edges in the NarrativeGraph
    ///
    /// Returns the IntentId assigned to the new intent.
    pub fn ingest(&self, raw: &str, context: &Context) -> Result<IntentId, TalaError>;
}
}

query

#![allow(unused)]
fn main() {
impl Daemon {
    /// Semantic search: find the `k` intents most similar to `embedding`.
    ///
    /// Delegates to StorageEngine::query_semantic. Returns
    /// (IntentId, cosine_similarity) pairs sorted by similarity descending.
    pub fn query(
        &self,
        embedding: &[f32],
        k: usize,
    ) -> Result<Vec<(IntentId, f32)>, TalaError>;
}
}

replay

#![allow(unused)]
fn main() {
impl Daemon {
    /// Build a replay plan rooted at `root`, traversing up to `depth` hops
    /// forward in the narrative graph.
    ///
    /// Steps:
    /// 1. BFS forward from root to discover the reachable subgraph
    /// 2. Fetch commands from the store for each reachable node
    /// 3. Topologically sort via tala_weave::build_plan
    ///
    /// Returns TalaError::NodeNotFound if root is not in the graph.
    pub fn replay(
        &self,
        root: IntentId,
        depth: usize,
    ) -> Result<Vec<ReplayStep>, TalaError>;
}
}

insights

#![allow(unused)]
fn main() {
impl Daemon {
    /// Generate insights from the current intent corpus.
    ///
    /// Analysis:
    /// 1. Collect all intents from the store, sorted by timestamp
    /// 2. Run pattern detection (n-gram frequency via InsightEngine)
    /// 3. Produce a narrative summary
    /// 4. Run k-means clustering with `k_clusters` clusters
    ///
    /// Returns a mix of RecurringPattern, Summary, and FailureCluster insights.
    pub fn insights(
        &self,
        k_clusters: usize,
    ) -> Result<Vec<Insight>, TalaError>;
}
}

Accessors

#![allow(unused)]
fn main() {
impl Daemon {
    /// Access the underlying storage engine for direct queries.
    pub fn store(&self) -> &StorageEngine;

    /// Access the daemon-level metrics.
    pub fn daemon_metrics(&self) -> &Arc<DaemonMetrics>;
}
}

DaemonBuilder

Builder for configuring and constructing a Daemon. Supports both in-memory and persistent modes.

#![allow(unused)]
fn main() {
pub struct DaemonBuilder { /* private */ }

impl DaemonBuilder {
    /// Create a new builder with default settings:
    /// - dim: 384
    /// - hot_capacity: 10,000
    pub fn new() -> Self;

    /// Set the embedding dimension.
    pub fn dim(self, dim: usize) -> Self;

    /// Set the hot buffer capacity (number of intents before segment flush).
    pub fn hot_capacity(self, hot_capacity: usize) -> Self;

    /// Build an in-memory daemon (no WAL, no persistence).
    pub fn build_in_memory(self) -> Daemon;

    /// Build a persistent daemon backed by the given directory.
    /// Creates WAL and segment files in `dir`.
    pub fn build(self, dir: impl AsRef<Path>) -> Result<Daemon, TalaError>;
}

impl Default for DaemonBuilder {
    fn default() -> Self { Self::new() }
}
}

Example: In-Memory Daemon

#![allow(unused)]
fn main() {
use tala_core::Context;
use tala_daemon::DaemonBuilder;

let daemon = DaemonBuilder::new()
    .dim(384)
    .hot_capacity(1000)
    .build_in_memory();

let ctx = Context {
    cwd: "/home/user/project".to_string(),
    env_hash: 42,
    session_id: 1,
    shell: "zsh".to_string(),
    user: "ops".to_string(),
};

// Ingest
let id = daemon.ingest("cargo build --release", &ctx).unwrap();
assert!(daemon.store().get(id).unwrap().is_some());

// Query
let pipeline = tala_intent::IntentPipeline::new();
let query_emb = pipeline.embed("cargo build");
let results = daemon.query(&query_emb, 5).unwrap();
assert!(!results.is_empty());

// Replay
let plan = daemon.replay(id, 3).unwrap();
assert_eq!(plan[0].intent_id, id);

// Insights
let insights = daemon.insights(2).unwrap();
assert!(!insights.is_empty());
}

Example: Persistent Daemon

#![allow(unused)]
fn main() {
use tala_daemon::DaemonBuilder;

let daemon = DaemonBuilder::new()
    .dim(384)
    .hot_capacity(100)
    .build("/tmp/tala-data")
    .unwrap();
}

DaemonMetrics

Per-phase timing metrics for the daemon pipeline. All fields are AtomicU64 with cumulative nanosecond timing and per-operation counts.

#![allow(unused)]
fn main() {
pub struct DaemonMetrics {
    /// Intent extraction time (cumulative nanoseconds).
    pub extract_ns: AtomicU64,
    pub extract_count: AtomicU64,

    /// Storage engine insert time (cumulative nanoseconds).
    pub store_insert_ns: AtomicU64,
    pub store_insert_count: AtomicU64,

    /// Edge formation time: semantic search + graph mutation (cumulative nanoseconds).
    pub edge_formation_ns: AtomicU64,
    pub edge_formation_count: AtomicU64,

    /// Semantic query time (cumulative nanoseconds).
    pub query_ns: AtomicU64,
    pub query_count: AtomicU64,

    /// Replay plan building time (cumulative nanoseconds).
    pub replay_ns: AtomicU64,
    pub replay_count: AtomicU64,

    /// Insight generation time (cumulative nanoseconds).
    pub insight_ns: AtomicU64,
    pub insight_count: AtomicU64,
}

impl DaemonMetrics {
    pub fn new() -> Self;
}

impl Default for DaemonMetrics {
    fn default() -> Self { Self::new() }
}
}

The daemon records timing for each phase of every operation. Access metrics via daemon.daemon_metrics(). The underlying storage engine also provides its own detailed metrics via daemon.store().metrics().