daat-locus 0.1.0

A long-running local agent runtime with memory, workflows, apps, and sleep-time self-improvement.
use super::sleep_driver::{SleepTrigger, start_background_sleep};
use super::*;

pub(crate) async fn handle_dashboard_control_command(
    context: &mut Context,
    tx: &tokio::sync::watch::Sender<DashboardState>,
    sleep_result_tx: &tokio::sync::mpsc::UnboundedSender<SleepTaskResult>,
    sleep_running: &mut bool,
    sleep_status: &mut SleepStatusSnapshot,
    command: DashboardControlCommand,
) {
    match command {
        DashboardControlCommand::RunSleep => {
            if *sleep_running {
                set_runtime_status(
                    Some(tx),
                    RuntimeStatusLevel::Info,
                    "sleep is already running in the background",
                );
                sync_dashboard_state(context, tx, sleep_status, None);
                return;
            }
            start_background_sleep(
                context,
                tx,
                sleep_result_tx,
                sleep_running,
                sleep_status,
                SleepTrigger::Manual,
                "running sleep in the background",
            )
            .await;
        }
        DashboardControlCommand::ClearConversation => {
            let cleared_events = match context.events.clear_all() {
                Ok(count) => count,
                Err(err) => {
                    tracing::error!("failed to clear events during /clear: {err:?}");
                    0
                }
            };
            let cleared_event_work = match context.pending_work.clear_events() {
                Ok(count) => count,
                Err(err) => {
                    tracing::error!("failed to clear event pending work during /clear: {err:?}");
                    0
                }
            };
            let cleared_outbound = match context.telegram.clear_outbox() {
                Ok(count) => count,
                Err(err) => {
                    tracing::error!("failed to clear telegram outbox during /clear: {err:?}");
                    0
                }
            };
            let cleared_live_drafts = {
                let mut live_drafts = context.telegram_live_drafts.lock();
                let count = live_drafts.len();
                live_drafts.clear();
                count
            };
            if let Some(session) = context.active_workflow_run.as_mut() {
                session.final_summary = "abandoned by dashboard /clear".to_string();
            }
            context.queue_active_workflow_run_for_flush(
                crate::workflow::WorkflowRunOutcome::Abandoned,
            );
            context.bound_workflow_id = None;
            context.install_live_progress(None);
            context.claimed_event_ids.clear();
            context.active_runtime_turn = false;
            context.set_runtime_phase(None);
            context.runtime_turn_started_at = None;
            context.current_work_origin = None;
            context.workflow_step_started_bound_id = None;
            let retain_plan = context.memory.clear_runtime_conversation().await;
            if context.plan.clear()
                && let Err(err) = context.plan.sync_to_disk().await
            {
                tracing::error!("failed to persist cleared plan: {err}");
            }
            for job in retain_plan.jobs {
                if let Err(err) = context.hindsight_retain.enqueue(job) {
                    tracing::error!("failed to enqueue hindsight retain job during clear: {err:?}");
                }
            }
            if retain_plan.must_flush_before_continue || context.memory.handoff_backlog_count() > 0
            {
                match context.hindsight_retain.flush().await {
                    Ok(submitted_handoffs) => {
                        context
                            .memory
                            .mark_handoffs_submitted(&submitted_handoffs)
                            .await;
                    }
                    Err(err) => {
                        tracing::error!(
                            "failed to flush hindsight handoff queue during clear: {err:?}"
                        );
                    }
                }
            }
            set_runtime_status(
                Some(tx),
                RuntimeStatusLevel::Info,
                format!(
                    "current conversation moved to hindsight; runtime conversation, current plan, and events cleared (events={cleared_events}, event_work={cleared_event_work}, telegram_outbox={cleared_outbound}, live_drafts={cleared_live_drafts})"
                ),
            );
            sync_dashboard_state(context, tx, sleep_status, None);
        }
    }
}