Skip to main content

algocline_core/
engine_api.rs

1use async_trait::async_trait;
2
3// ─── Parameter types (transport-independent) ─────────────────────
4
5/// A single query response in a batch feed.
6#[derive(Debug)]
7pub struct QueryResponse {
8    /// Query ID (e.g. "q-0", "q-1").
9    pub query_id: String,
10    /// The host LLM's response for this query.
11    pub response: String,
12    /// Token usage reported by the host for this query.
13    pub usage: Option<crate::TokenUsage>,
14}
15
16// ─── Engine API trait ────────────────────────────────────────────
17
18/// Transport-independent API for the algocline engine.
19///
20/// Abstracts the full public surface of AppService so that callers
21/// (MCP handler, future daemon client, etc.) can operate through
22/// `Arc<dyn EngineApi>` without depending on the concrete implementation.
23///
24/// All methods are async to support both local (in-process) and remote
25/// (socket/HTTP) implementations uniformly.
26#[async_trait]
27pub trait EngineApi: Send + Sync {
28    // ─── Core execution ──────────────────────────────────────
29
30    /// Execute Lua code with optional JSON context.
31    async fn run(
32        &self,
33        code: Option<String>,
34        code_file: Option<String>,
35        ctx: Option<serde_json::Value>,
36        project_root: Option<String>,
37    ) -> Result<String, String>;
38
39    /// Apply an installed strategy package. Task is optional.
40    async fn advice(
41        &self,
42        strategy: &str,
43        task: Option<String>,
44        opts: Option<serde_json::Value>,
45        project_root: Option<String>,
46    ) -> Result<String, String>;
47
48    /// Continue a paused execution — single response (with optional query_id).
49    async fn continue_single(
50        &self,
51        session_id: &str,
52        response: String,
53        query_id: Option<&str>,
54        usage: Option<crate::TokenUsage>,
55    ) -> Result<String, String>;
56
57    /// Continue a paused execution — batch feed.
58    async fn continue_batch(
59        &self,
60        session_id: &str,
61        responses: Vec<QueryResponse>,
62    ) -> Result<String, String>;
63
64    // ─── Session status ──────────────────────────────────────
65
66    /// Query active session status.
67    async fn status(&self, session_id: Option<&str>) -> Result<String, String>;
68
69    // ─── Evaluation ──────────────────────────────────────────
70
71    /// Run an evalframe evaluation suite.
72    async fn eval(
73        &self,
74        scenario: Option<String>,
75        scenario_file: Option<String>,
76        scenario_name: Option<String>,
77        strategy: &str,
78        strategy_opts: Option<serde_json::Value>,
79    ) -> Result<String, String>;
80
81    /// List eval history, optionally filtered by strategy.
82    async fn eval_history(&self, strategy: Option<&str>, limit: usize) -> Result<String, String>;
83
84    /// View a specific eval result by ID.
85    async fn eval_detail(&self, eval_id: &str) -> Result<String, String>;
86
87    /// Compare two eval results with statistical significance testing.
88    async fn eval_compare(&self, eval_id_a: &str, eval_id_b: &str) -> Result<String, String>;
89
90    // ─── Scenarios ───────────────────────────────────────────
91
92    /// List available scenarios.
93    async fn scenario_list(&self) -> Result<String, String>;
94
95    /// Show the content of a named scenario.
96    async fn scenario_show(&self, name: &str) -> Result<String, String>;
97
98    /// Install scenarios from a Git URL or local path.
99    async fn scenario_install(&self, url: String) -> Result<String, String>;
100
101    // ─── Packages ────────────────────────────────────────────
102
103    /// Link a local directory as a project-local package (symlink to cache).
104    ///
105    /// Phase 2 (subtask 5) will implement the full symlink logic.
106    async fn pkg_link(
107        &self,
108        path: String,
109        name: Option<String>,
110        force: Option<bool>,
111    ) -> Result<String, String>;
112
113    /// List installed packages with metadata.
114    ///
115    /// When `project_root` is provided, project-local packages from `alc.toml`/`alc.lock`
116    /// are included with `scope: "project"`. Global packages carry `scope: "global"`.
117    async fn pkg_list(&self, project_root: Option<String>) -> Result<String, String>;
118
119    /// Install a package from a Git URL or local path.
120    async fn pkg_install(&self, url: String, name: Option<String>) -> Result<String, String>;
121
122    /// Remove a symlinked package from `~/.algocline/packages/`.
123    ///
124    /// Only removes symlinks; for installed (copied) packages, use `pkg_remove`.
125    async fn pkg_unlink(&self, name: String) -> Result<String, String>;
126
127    /// Remove a package declaration from `alc.toml` and `alc.lock`.
128    ///
129    /// Requires an `alc.toml` to be found (via `project_root` or ancestor walk).
130    /// Does NOT delete physical files from `~/.algocline/packages/`.
131    async fn pkg_remove(
132        &self,
133        name: &str,
134        project_root: Option<String>,
135        version: Option<String>,
136    ) -> Result<String, String>;
137
138    // ─── Logging ─────────────────────────────────────────────
139
140    /// Append a note to a session's log file.
141    async fn add_note(
142        &self,
143        session_id: &str,
144        content: &str,
145        title: Option<&str>,
146    ) -> Result<String, String>;
147
148    /// View session logs.
149    async fn log_view(
150        &self,
151        session_id: Option<&str>,
152        limit: Option<usize>,
153        max_chars: Option<usize>,
154    ) -> Result<String, String>;
155
156    /// Aggregate stats across all logged sessions.
157    async fn stats(
158        &self,
159        strategy_filter: Option<&str>,
160        days: Option<u64>,
161    ) -> Result<String, String>;
162
163    // ─── Project lifecycle ────────────────────────────────────
164
165    /// Initialize `alc.toml` in the given project root.
166    ///
167    /// Creates a minimal `alc.toml` (`[packages]` section only).
168    /// Fails if `alc.toml` already exists (no overwrite).
169    async fn init(&self, project_root: Option<String>) -> Result<String, String>;
170
171    /// Re-resolve all `alc.toml` entries and rewrite `alc.lock`.
172    ///
173    /// Requires an `alc.toml` to be present. Returns resolved count and errors.
174    async fn update(&self, project_root: Option<String>) -> Result<String, String>;
175
176    /// Migrate a legacy `alc.lock` to `alc.toml` + new `alc.lock` format.
177    ///
178    /// Detects legacy format via `linked_at` / `local_dir` fields.
179    /// Backs up the old lock file as `alc.lock.bak`.
180    async fn migrate(&self, project_root: Option<String>) -> Result<String, String>;
181
182    // ─── Diagnostics ─────────────────────────────────────────
183
184    /// Show server configuration and diagnostic info.
185    async fn info(&self) -> String;
186}