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}