Skip to main content

zagens_core/engine/
op.rs

1//! Operations submitted by the UI/runtime layer to the engine (M1 → `zagens-core`).
2//!
3//! These operations flow from the TUI/HTTP runtime to the engine via a
4//! channel, allowing the shell to stay responsive while the engine processes
5//! requests. Behavior is unchanged from the prior `crates/tui/src/core/ops.rs`
6//! definition; only two surface tweaks were made for the move:
7//!
8//! - `Op::SendMessage.mode` / `Op::ChangeMode.mode` are now [`TurnLoopMode`]
9//!   instead of `tui::AppMode`. The two enums are isomorphic
10//!   (Agent / Yolo / Plan). Producers wrap via `app_mode_to_turn_loop(...)`;
11//!   the tui-side dispatch loop unwraps via `turn_loop_to_app_mode(...)`.
12//! - `Op::QueryContext.reply` now carries the core-side
13//!   [`ThreadContextSnapshot`].
14
15use std::path::PathBuf;
16
17use tokio::sync::oneshot;
18
19use crate::approval::ApprovalMode;
20use crate::chat::{Message, SystemPrompt};
21use crate::compaction::CompactionConfig;
22use crate::engine::context_snapshot::ThreadContextSnapshot;
23use crate::turn::TurnLoopMode;
24
25/// Operations that can be submitted to the engine.
26#[derive(Debug)]
27pub enum Op {
28    /// Send a message to the AI.
29    SendMessage {
30        content: String,
31        mode: TurnLoopMode,
32        model: String,
33        goal_objective: Option<String>,
34        /// Reasoning-effort tier: `"off" | "low" | "medium" | "high" | "max"`.
35        /// `None` lets the provider apply its default.
36        reasoning_effort: Option<String>,
37        /// True when the user selected auto thinking, even though the UI sends
38        /// a concrete per-turn value to the model API.
39        reasoning_effort_auto: bool,
40        /// True when the user selected auto model routing.
41        auto_model: bool,
42        allow_shell: bool,
43        trust_mode: bool,
44        auto_approve: bool,
45        approval_mode: ApprovalMode,
46        temperature: Option<f32>,
47        top_p: Option<f32>,
48        max_output_tokens: Option<u32>,
49    },
50
51    /// Cancel the current request.
52    #[allow(dead_code)]
53    CancelRequest,
54
55    /// Approve a tool call that requires permission.
56    #[allow(dead_code)]
57    ApproveToolCall { id: String },
58
59    /// Deny a tool call that requires permission.
60    #[allow(dead_code)]
61    DenyToolCall { id: String },
62
63    /// Spawn a sub-agent.
64    #[allow(dead_code)]
65    SpawnSubAgent { prompt: String },
66
67    /// List current sub-agents and their status.
68    ListSubAgents,
69
70    /// Change the operating mode.
71    #[allow(dead_code)]
72    ChangeMode { mode: TurnLoopMode },
73
74    /// Update the model being used.
75    #[allow(dead_code)]
76    SetModel { model: String },
77
78    /// Update auto-compaction settings.
79    SetCompaction { config: CompactionConfig },
80
81    /// Sync engine session state (used for resume/load).
82    SyncSession {
83        messages: Vec<Message>,
84        system_prompt: Option<SystemPrompt>,
85        model: String,
86        workspace: PathBuf,
87    },
88
89    /// Restore kernel turn frame from persisted event-log projection (Phase 3b 6e).
90    ApplyKernelResume {
91        hints: crate::engine::turn_machine::KernelResumeHints,
92    },
93
94    /// Run context compaction immediately.
95    CompactContext,
96
97    /// Run a Recursive Language Model (RLM) turn per Algorithm 1 of
98    /// Zhang et al. (arXiv:2512.24601). The prompt is stored in the REPL
99    /// as `context`; the root LLM only sees metadata.
100    Rlm {
101        /// The user's prompt — stored in REPL, NOT in the LLM context.
102        content: String,
103        /// The model to use for root LLM calls.
104        model: String,
105        /// The model to use for sub-LLM (llm_query) calls.
106        child_model: String,
107        /// Recursion budget for `sub_rlm()` calls. Paper experiments use
108        /// depth=1; defaults set by the `/rlm` command.
109        max_depth: u32,
110    },
111
112    /// Edit the last user message: remove the last user+assistant exchange
113    /// from the session, then re-send with the new content.
114    EditLastTurn { new_message: String },
115
116    /// Drop the last user message and everything after it (#383 `/edit`, F4 HTTP).
117    TruncateBeforeLastUserMessage { reply: oneshot::Sender<bool> },
118
119    /// Return a TUI-aligned context usage snapshot (Zagens / runtime API).
120    QueryContext {
121        reply: oneshot::Sender<ThreadContextSnapshot>,
122    },
123
124    /// Return derived LHT task graph JSON (`GET …/harness/task-graph`).
125    QueryHarnessTaskGraph {
126        reply: oneshot::Sender<serde_json::Value>,
127    },
128
129    /// Return cycle briefings + archive summaries (`GET …/harness/cycles`).
130    QueryHarnessCycles {
131        reply: oneshot::Sender<serde_json::Value>,
132    },
133
134    /// Shutdown the engine.
135    Shutdown,
136}