Skip to main content

zagens_core/engine/
runtime_new.rs

1//! Engine construction (`Engine::with_hosts`, M7).
2
3use std::sync::{Arc, Mutex as StdMutex};
4
5use tokio::sync::{RwLock, mpsc};
6use tokio_util::sync::CancellationToken;
7
8use crate::coherence::CoherenceState;
9use crate::engine::config::EngineConfig;
10use crate::engine::handle::EngineHandle;
11use crate::engine::host_bundle::EngineHostBundle;
12use crate::engine::runtime::Engine;
13use crate::session::Session;
14
15impl<P, R> Engine<P, R>
16where
17    P: Send + Sync + 'static,
18    R: Send + Sync + 'static,
19{
20    /// Construct an engine from lean config + tui-wired host bundle.
21    ///
22    /// Creates the seven mpsc channel pairs core-side (spike R11) and
23    /// returns `(engine, handle)` for the tui builder to spawn the loop.
24    #[must_use]
25    pub fn with_hosts(
26        config: EngineConfig,
27        session: Session,
28        hosts: EngineHostBundle<P, R>,
29    ) -> (Self, EngineHandle<P, R>) {
30        let EngineHostBundle {
31            lsp,
32            shell,
33            sandbox,
34            seam,
35            workshop,
36            topic_memory,
37            capacity_controller,
38            deepseek_client,
39            deepseek_client_error,
40            api_key_env_only_recovery,
41            ext,
42            scratchpad_run_id,
43        } = hosts;
44
45        let (tx_op, rx_op) = mpsc::channel(32);
46        let (tx_event, rx_event) = mpsc::channel(256);
47        let (tx_approval, rx_approval) = mpsc::channel(64);
48        let (tx_user_input, rx_user_input) = mpsc::channel(32);
49        let (tx_steer, rx_steer) = mpsc::channel(64);
50        let cancel_token = CancellationToken::new();
51        let shared_cancel_token = Arc::new(StdMutex::new(cancel_token.clone()));
52        let tool_exec_lock = Arc::new(RwLock::new(()));
53
54        let engine = Self {
55            config,
56            ext: Some(ext),
57            deepseek_client,
58            deepseek_client_error,
59            api_key_env_only_recovery,
60            session,
61            shell,
62            rx_op,
63            tx_approval: tx_approval.clone(),
64            rx_approval,
65            rx_user_input,
66            rx_steer,
67            tx_event,
68            cancel_token,
69            shared_cancel_token: shared_cancel_token.clone(),
70            tool_exec_lock,
71            capacity_controller,
72            seam,
73            coherence_state: CoherenceState::default(),
74            turn_counter: 0,
75            lsp,
76            workshop,
77            sandbox,
78            pending_lsp_blocks: Vec::new(),
79            scratchpad_step: Default::default(),
80            scratchpad_run_id,
81            scratchpad_summary_injected_this_turn: false,
82            scratchpad_audit_continue_injected_this_turn: false,
83            long_horizon_continue_injected_this_turn: false,
84            long_horizon_auto_continue_rounds: 0,
85            topic_memory,
86            overflow_source_budget_cap: None,
87        };
88
89        let handle = EngineHandle::new(
90            tx_op,
91            Arc::new(RwLock::new(rx_event)),
92            shared_cancel_token,
93            tx_approval,
94            tx_user_input,
95            tx_steer,
96        );
97
98        (engine, handle)
99    }
100}