Skip to main content

EngineApi

Trait EngineApi 

Source
pub trait EngineApi: Send + Sync {
Show 54 methods // Required methods fn run<'life0, 'async_trait>( &'life0 self, code: Option<String>, code_file: Option<String>, ctx: Option<Value>, project_root: Option<String>, host_mode: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn advice<'life0, 'life1, 'async_trait>( &'life0 self, strategy: &'life1 str, task: Option<String>, opts: Option<Value>, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn continue_single<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_id: &'life1 str, response: String, query_id: Option<&'life2 str>, usage: Option<TokenUsage>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn continue_batch<'life0, 'life1, 'async_trait>( &'life0 self, session_id: &'life1 str, responses: Vec<QueryResponse>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn status<'life0, 'life1, 'async_trait>( &'life0 self, session_id: Option<&'life1 str>, pending_filter: Option<Value>, include_history: bool, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn eval<'life0, 'life1, 'async_trait>( &'life0 self, scenario: Option<String>, scenario_file: Option<String>, scenario_name: Option<String>, strategy: &'life1 str, strategy_opts: Option<Value>, auto_card: bool, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn eval_history<'life0, 'life1, 'async_trait>( &'life0 self, strategy: Option<&'life1 str>, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn eval_detail<'life0, 'life1, 'async_trait>( &'life0 self, eval_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn eval_compare<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, eval_id_a: &'life1 str, eval_id_b: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn scenario_list<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn scenario_show<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn scenario_install<'life0, 'async_trait>( &'life0 self, url: String, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_link<'life0, 'async_trait>( &'life0 self, path: String, name: Option<String>, force: Option<bool>, scope: Option<String>, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_list<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, limit: Option<i32>, sort: Option<String>, filter: Option<Value>, fields: Option<Vec<String>>, verbose: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_install<'life0, 'async_trait>( &'life0 self, url: String, name: Option<String>, force: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_unlink<'life0, 'async_trait>( &'life0 self, name: String, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_remove<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, project_root: Option<String>, version: Option<String>, scope: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn pkg_repair<'life0, 'async_trait>( &'life0 self, name: Option<String>, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_doctor<'life0, 'async_trait>( &'life0 self, name: Option<String>, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_test<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, code_file: Option<String>, code: Option<String>, spec_dir: Option<String>, filter: Option<String>, search_paths: Option<Vec<String>>, project_root: Option<String>, auto_search_paths: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn add_note<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, session_id: &'life1 str, content: &'life2 str, title: Option<&'life3 str>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait; fn log_view<'life0, 'life1, 'async_trait>( &'life0 self, session_id: Option<&'life1 str>, limit: Option<usize>, max_chars: Option<usize>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn stats<'life0, 'life1, 'async_trait>( &'life0 self, strategy_filter: Option<&'life1 str>, days: Option<u64>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn init<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn update<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn migrate<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_get_narrative_md<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<String>, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn session_new<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, mode: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn card_list<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn card_get<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn card_find<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, where_: Option<Value>, order_by: Option<Value>, limit: Option<usize>, offset: Option<usize>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn card_alias_list<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn card_get_by_alias<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn card_alias_set<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, card_id: &'life2 str, pkg: Option<String>, note: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait; fn card_append<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, fields: Value, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn card_install<'life0, 'async_trait>( &'life0 self, url: String, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn card_samples<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, offset: Option<usize>, limit: Option<usize>, where_: Option<Value>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn card_lineage<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, direction: Option<String>, depth: Option<usize>, include_stats: Option<bool>, relation_filter: Option<Vec<String>>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn hub_reindex<'life0, 'async_trait>( &'life0 self, output_path: Option<String>, source_dir: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn hub_gendoc<'life0, 'async_trait>( &'life0 self, source_dir: String, out_dir: Option<String>, projections: Option<Vec<String>>, config_path: Option<String>, lint_strict: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn hub_dist<'life0, 'async_trait>( &'life0 self, source_dir: String, output_path: Option<String>, out_dir: Option<String>, preset: Option<String>, project_root: Option<String>, projections: Option<Vec<String>>, config_path: Option<String>, lint_strict: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn hub_info<'life0, 'async_trait>( &'life0 self, pkg: String, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn hub_search<'life0, 'async_trait>( &'life0 self, query: Option<String>, category: Option<String>, installed_only: Option<bool>, limit: Option<i32>, sort: Option<String>, filter: Option<Value>, fields: Option<Vec<String>>, verbose: Option<String>, local_indices: Option<Vec<String>>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_scaffold<'life0, 'async_trait>( &'life0 self, name: String, target_dir: Option<String>, category: Option<String>, description: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pkg_read_init_lua<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn pkg_meta<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait; fn setting_resolve<'life0, 'async_trait>( &'life0 self, target: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn info<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = String> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn hub_index_aggregate<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pool_ensure<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pool_status<'life0, 'async_trait>( &'life0 self, sid: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; fn pool_stop<'life0, 'async_trait>( &'life0 self, sid: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait; // Provided methods fn card_sink_backfill<'life0, 'async_trait>( &'life0 self, _sink: String, _dry_run: bool, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn card_analyze<'life0, 'life1, 'async_trait>( &'life0 self, _card_id: &'life1 str, _pkg: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... }
}
Expand description

Transport-independent API for the algocline engine.

Abstracts the full public surface of AppService so that callers (MCP handler, future daemon client, etc.) can operate through Arc<dyn EngineApi> without depending on the concrete implementation.

All methods are async to support both local (in-process) and remote (socket/HTTP) implementations uniformly.

Required Methods§

Source

fn run<'life0, 'async_trait>( &'life0 self, code: Option<String>, code_file: Option<String>, ctx: Option<Value>, project_root: Option<String>, host_mode: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Execute Lua code with optional JSON context.

When host_mode: Some(true) is passed, the call is proxied via PoolClient to a long-lived worker subprocess over a Unix domain socket. When host_mode is None or Some(false) the existing in-process Executor::start_session path is used unchanged.

Source

fn advice<'life0, 'life1, 'async_trait>( &'life0 self, strategy: &'life1 str, task: Option<String>, opts: Option<Value>, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Apply an installed strategy package. Task is optional.

Source

fn continue_single<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, session_id: &'life1 str, response: String, query_id: Option<&'life2 str>, usage: Option<TokenUsage>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Continue a paused execution — single response (with optional query_id).

Source

fn continue_batch<'life0, 'life1, 'async_trait>( &'life0 self, session_id: &'life1 str, responses: Vec<QueryResponse>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Continue a paused execution — batch feed.

Source

fn status<'life0, 'life1, 'async_trait>( &'life0 self, session_id: Option<&'life1 str>, pending_filter: Option<Value>, include_history: bool, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Query active session status.

pending_filter is a free-form JSON value forwarded from MCP callers, decoded inside the app layer into either a preset name ("meta" / "preview" / "full") or a custom field-filter object. None keeps the legacy count-only snapshot.

include_history: when true, each session snapshot includes conversation_history (capped at 10 entries). Default false preserves the lightweight snapshot contract for high-frequency pollers.

Source

fn eval<'life0, 'life1, 'async_trait>( &'life0 self, scenario: Option<String>, scenario_file: Option<String>, scenario_name: Option<String>, strategy: &'life1 str, strategy_opts: Option<Value>, auto_card: bool, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run an evalframe evaluation suite.

auto_card: when true, emit an immutable Card (~/.algocline/cards/{strategy}/{card_id}.toml) summarizing the run.

Source

fn eval_history<'life0, 'life1, 'async_trait>( &'life0 self, strategy: Option<&'life1 str>, limit: usize, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

List eval history, optionally filtered by strategy.

Source

fn eval_detail<'life0, 'life1, 'async_trait>( &'life0 self, eval_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

View a specific eval result by ID.

Source

fn eval_compare<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, eval_id_a: &'life1 str, eval_id_b: &'life2 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Compare two eval results with statistical significance testing.

Source

fn scenario_list<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

List available scenarios.

Source

fn scenario_show<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Show the content of a named scenario.

Source

fn scenario_install<'life0, 'async_trait>( &'life0 self, url: String, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Install scenarios from a Git URL or local path.

Link a local directory as a project-local package (symlink to cache).

Scope selection:

  • scope = None or Some("global") — symlink into ~/.algocline/packages/ (visible to all projects).
  • scope = Some("variant") — record the path in alc.local.toml at the project root (worktree-scoped override, git-ignored). No symlink is created.
  • Any other value → Err("invalid scope: ...").

project_root is only consulted when scope = Some("variant"). If None, falls back to ALC_PROJECT_ROOT env or ancestor walk from cwd.

Source

fn pkg_list<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, limit: Option<i32>, sort: Option<String>, filter: Option<Value>, fields: Option<Vec<String>>, verbose: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

List installed packages with metadata.

When project_root is provided, project-local packages from alc.toml/alc.lock are included with scope: "project". Global packages carry scope: "global".

Mirrors the list-tool knob contract used by Self::hub_search (plan.md §4.1). Parameters are individual JSON-primitive Option<T> values so the algocline-core crate stays free of algocline-app-internal types; the impl folds them into its pub(crate) ListOpts struct.

  • limit is Option<i32> at this layer (MCP/JSON boundary). The impl clamps negative values to 0 and casts to usize. Some(0) (and thus clamped negatives) means no limit (return all entries — empty-means-all idiom); None falls back to the tool’s default cap.
  • filter is a free-form JSON object; it is Deserialized into a HashMap<String, Value> inside the app layer. Non-object values are logged via tracing::warn and treated as no filter.
  • fields / verbose drive projection on each entry of the packages array; fields wins when both are supplied.
  • Top-level keys (packages, search_paths, project_root, lockfile_path) are never projected away.
Source

fn pkg_install<'life0, 'async_trait>( &'life0 self, url: String, name: Option<String>, force: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Install a package from a Git URL or local path.

force (optional, default false): Collection mode only — overwrite existing packages at dest. Single mode rejects pre-existing dest with an error regardless.

Remove a symlinked package from ~/.algocline/packages/.

Only removes symlinks; for installed (copied) packages, use pkg_remove.

Source

fn pkg_remove<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, project_root: Option<String>, version: Option<String>, scope: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Remove a package entry, scoped by scope ("project" / "global" / "all", default "project").

  • "project": remove from alc.toml + alc.lock. Requires an alc.toml via project_root or ancestor walk.
  • "global": remove from ~/.algocline/installed.json only. project_root is ignored.
  • "all": remove from both; succeeds if either scope had the entry.

Physical files in ~/.algocline/packages/{name}/ are never deleted.

Source

fn pkg_repair<'life0, 'async_trait>( &'life0 self, name: Option<String>, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Heal broken package state by reinstalling entries whose installed directory is missing. Other broken kinds (dangling symlink, declared-path missing) are surfaced as unrepairable with a suggested remediation.

Source

fn pkg_doctor<'life0, 'async_trait>( &'life0 self, name: Option<String>, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Diagnose package state without side effects.

Read-only counterpart of Self::pkg_repair. Classifies packages into four buckets — healthy, installed_missing, symlink_dangling, path_missing — and returns the result as a JSON string. No filesystem writes, no pkg_install calls.

name restricts the report to a single package; None inspects every known package. project_root is used for the alc.toml / alc.local.toml pass (falls back to ancestor walk from cwd).

Source

fn pkg_test<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, code_file: Option<String>, code: Option<String>, spec_dir: Option<String>, filter: Option<String>, search_paths: Option<Vec<String>>, project_root: Option<String>, auto_search_paths: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Run mlua-lspec tests for a package, a single file, or inline code.

Exactly one of pkg, code_file, or code must be provided; providing zero or more than one returns a typed Err.

§Arguments
  • pkg — installed package name; spec files are discovered under <pkg_root>/<spec_dir>/*_spec.lua (default spec_dir = "spec").
  • code_file — absolute path to a single .lua test file.
  • code — inline Lua source code containing lspec tests.
  • spec_dir — subdirectory within the package root that holds spec files (default "spec"). Only used when pkg is provided.
  • filter — substring filter applied to spec file stems (only when pkg is provided).
  • search_paths — additional directories appended to package.path inside the Lua VM, after auto-resolved paths.
  • project_root — optional project root for variant-scope package resolution (alc.local.toml). Falls back to ancestor walk from cwd.
  • auto_search_paths — when true (default) or None, auto-prepends parent dirs of all linked/installed packages (installed ~/.algocline/packages/, alc.toml path entries, alc.local.toml path entries) to package.path. When false, no auto-resolve is performed and zero paths are injected. Resolved mapping is returned in the JSON response resolved_search_paths field.
§Returns

On success: JSON string {passed, failed, pending, total, duration_ms, spec_files: [{path, passed, failed, total, duration_ms, tests: [{suite, name, passed, pending, error}]}], resolved_search_paths: [{name, search_dir, source}], search_path_warnings?: [...]}.

§Errors
  • Zero or multiple input sources provided → "pkg_test: provide exactly one of pkg, code_file, code".
  • pkg not found → "pkg_test: package '<name>' not found …".
  • No spec files found → "pkg_test: no spec files found in <path> …".
  • mlua VM init failure, I/O errors, or spawn_blocking panic → typed Err string.
Source

fn add_note<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, session_id: &'life1 str, content: &'life2 str, title: Option<&'life3 str>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait,

Append a note to a session’s log file.

Source

fn log_view<'life0, 'life1, 'async_trait>( &'life0 self, session_id: Option<&'life1 str>, limit: Option<usize>, max_chars: Option<usize>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

View session logs.

Source

fn stats<'life0, 'life1, 'async_trait>( &'life0 self, strategy_filter: Option<&'life1 str>, days: Option<u64>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Aggregate stats across all logged sessions.

Source

fn init<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Initialize alc.toml in the given project root.

Creates a minimal alc.toml ([packages] section only). Fails if alc.toml already exists (no overwrite).

Source

fn update<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Re-resolve all alc.toml entries and rewrite alc.lock.

Requires an alc.toml to be present. Returns resolved count and errors.

Source

fn migrate<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Migrate a legacy alc.lock to alc.toml + new alc.lock format.

Detects legacy format via linked_at / local_dir fields. Backs up the old lock file as alc.lock.bak.

Source

fn pkg_get_narrative_md<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<Option<String>, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Render the narrative markdown for a package on-the-fly.

Extracts the init.lua docstring H2/H3 sections via the embedded gendoc pipeline (extract.split_sections + projections.narrative_md) and returns the rendered markdown string.

Returns Ok(Some(markdown)) when the pkg is found and its init.lua is loadable. Returns Ok(None) when the pkg is not installed. Returns Err(...) when the pkg is found but the gendoc pipeline fails (e.g. malformed init.lua).

Source

fn session_new<'life0, 'async_trait>( &'life0 self, project_root: Option<String>, mode: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Activate a session pin for the current MCP connection.

project_root is resolved at activation time using the existing fallback chain (P > E > W) and cached on the AppService. Subsequent tool calls without an explicit project_root argument resolve via P > S > E > W, where S is this pin (issue #1776627475 §6).

mode accepts "default" (or None) and "test". Unknown values return a typed error rather than silent fallback. Mode is exposed back to callers so downstream tools can adapt behaviour (e.g. scenario test isolation).

Returns a JSON string with session_id, project_root (resolved or null), and mode.

Source

fn card_list<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

List Card summaries, optionally filtered by pkg.

Source

fn card_get<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Fetch a full Card by id.

Source

fn card_find<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, where_: Option<Value>, order_by: Option<Value>, limit: Option<usize>, offset: Option<usize>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Filter/sort Cards using the Prisma-style where DSL.

  • pkg: restricts filesystem scan to a single pkg subdir (I/O hint).
  • where_: nested-object predicate (see card::parse_where).
  • order_by: array of dotted-path sort keys; - prefix = desc.
  • limit / offset: pagination.
Source

fn card_alias_list<'life0, 'async_trait>( &'life0 self, pkg: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

List aliases, optionally filtered by pkg.

Source

fn card_get_by_alias<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Resolve an alias name to its bound Card and return the full Card JSON.

Source

fn card_alias_set<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, name: &'life1 str, card_id: &'life2 str, pkg: Option<String>, note: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Bind (or rebind) an alias to a Card.

Source

fn card_append<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, fields: Value, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Append new top-level fields to an existing Card (additive-only).

Source

fn card_install<'life0, 'async_trait>( &'life0 self, url: String, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Install Cards from a Card Collection repo (Git URL or local path).

Source

fn card_samples<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, offset: Option<usize>, limit: Option<usize>, where_: Option<Value>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Read per-case samples from a Card’s sidecar JSONL file.

where_ applies the same Prisma-style DSL used by card_find to each sample row; offset/limit page the post-filter stream.

Source

fn card_lineage<'life0, 'life1, 'async_trait>( &'life0 self, card_id: &'life1 str, direction: Option<String>, depth: Option<usize>, include_stats: Option<bool>, relation_filter: Option<Vec<String>>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Walk a Card’s lineage tree via metadata.prior_card_id.

  • direction: "up" | "down" | "both" (default "up").
  • depth: max traversal depth (default 10).
  • include_stats: include each node’s [stats] section.
  • relation_filter: optional list of accepted prior_relation values.
Source

fn hub_reindex<'life0, 'async_trait>( &'life0 self, output_path: Option<String>, source_dir: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Rebuild hub index from a packages directory.

When source_dir is provided, scans that directory directly (pure metadata, no manifest). When omitted, scans ~/.algocline/packages/.

Source

fn hub_gendoc<'life0, 'async_trait>( &'life0 self, source_dir: String, out_dir: Option<String>, projections: Option<Vec<String>>, config_path: Option<String>, lint_strict: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Generate human-readable documentation artifacts from a hub index.

Runs the embedded Lua gen_docs pipeline (originally shipped with algocline-bundled-packages) against source_dir, which must contain a fresh hub_index.json. Emits narrative/{pkg}.md, llms.txt, llms-full.txt under out_dir (defaults to {source_dir}/docs), plus optional projections depending on projections:

  • "hub"{out_dir}/hub/{pkg}.json
  • "context7"{source_dir}/context7.json
  • "devin"{source_dir}/.devin/wiki.json
  • "lint" → run V0 lint pass (warnings only)
  • "lint_only" → run lint, skip file generation

config_path — optional path to a TOML config file. When omitted, the project root’s alc.toml is auto-explored for [hub.context7] and [hub.devin] sections. Core defaults apply when neither a config_path nor alc.toml provides projection config. Passing a .lua path is a typed error (retired). See docs/hub-gendoc-config.md for the full schema.

Projection names are validated strictly and unknown values are rejected with Err("gendoc: unknown projection ...").

lint_strict = true upgrades lint errors to a hard failure (equivalent to the --strict CLI flag).

Returns a JSON string containing the collected stdout / stderr plus the resolved source_dir / out_dir for observability.

Source

fn hub_dist<'life0, 'async_trait>( &'life0 self, source_dir: String, output_path: Option<String>, out_dir: Option<String>, preset: Option<String>, project_root: Option<String>, projections: Option<Vec<String>>, config_path: Option<String>, lint_strict: Option<bool>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Run hub_reindex followed by hub_gendoc as a single facade.

This is a convenience wrapper for downstream hub repositories that want to regenerate the index and the public docs in one call. The composed response is a JSON object:

{
  "reindex": <hub_reindex response>,
  "gendoc": <hub_gendoc response>,
  "preset_catalog_version": "...",
  "preset": { "name": ..., "catalog_version": ..., "resolved": { ... } }
}

Error propagation:

  • If hub_reindex fails, hub_dist returns immediately with Err("dist: reindex failed: {inner}") and does not invoke hub_gendoc.
  • If hub_gendoc fails, the error text includes the reindex JSON that already succeeded: Err("dist: gendoc failed: {inner}\nreindex result (succeeded): {json}"). The reindex-side side effects (written hub_index.json) are not rolled back.

output_path is the hub_index.json destination (reindex arg). Callers typically pass {source_dir}/hub_index.json so the subsequent gendoc step can read it back.

Presets (preset) are expanded inside hub_dist into primitive hub_gendoc arguments (projections / config_path / lint_strict). When preset is set, the successful JSON response includes a preset object with catalog_version plus the fully resolved knobs for observability.

Merge order (strongest wins):

  1. explicit MCP arguments (projections / config_path / lint_strict)
  2. optional alc.toml overrides under [hub.dist.presets.<name>] (keyed by project_root) — only fills omitted knobs
  3. builtin Current defaults for the selected preset
Source

fn hub_info<'life0, 'async_trait>( &'life0 self, pkg: String, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Show detailed information for a single package.

Search packages across remote index + local install state.

This trait method mirrors the MCP alc_hub_search tool. Parameters are deliberately individual JSON-primitive Option<T> values (rather than an aggregate struct) so that the algocline-core crate stays free of algocline-app-internal types (see plan.md §4.1). The algocline-app side of the impl folds these into its pub(crate) ListOpts struct.

  • limit is Option<i32> at this layer (MCP/JSON boundary). The impl casts to usize internally.
  • filter is a free-form JSON object; it is Deserialized into a HashMap<String, Value> inside the app layer.
  • fields / verbose drive projection; fields wins when both are supplied.
Source

fn pkg_scaffold<'life0, 'async_trait>( &'life0 self, name: String, target_dir: Option<String>, category: Option<String>, description: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Generate a minimal package skeleton at <target_dir>/<name>/init.lua.

Writes an M.meta / M.spec.entries.run / M.run template with a pre-filled alc_shapes_compat range derived from the embedded alc_shapes version. Optional category / description are emitted as uncommented fields in M.meta when provided.

Returns { "status": "ok", "path": "...", "bytes_written": N } on success. Typed errors (NameInvalid, AlreadyExists, IoError) are propagated via Err(String) to the MCP wire response.

Source

fn pkg_read_init_lua<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Read the init.lua source of an installed package.

Searches global (~/.algocline/packages/) and variant (alc.local.toml) scope in priority order (variant wins). Returns the raw Lua source on success, or an Err(String) describing why the package was not found or could not be read.

Source

fn pkg_meta<'life0, 'life1, 'async_trait>( &'life0 self, name: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Read metadata for a single installed package.

Returns the JSON object string for one package entry (the same shape pkg_list returns inside packages[*]). Err("pkg not found: ...") when the package is unknown.

Source

fn setting_resolve<'life0, 'async_trait>( &'life0 self, target: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Resolve [setting.<target>] config across env, project (alc.toml/alc.local.toml), and global (~/.algocline/config.toml) layers.

Field-level merge: each field independently selects the highest-priority layer that defines it (env > project > global). The returned JSON contains both the resolved values and a per-field sources map identifying the winning layer.

When target is None, all [setting.*] tables across all layers are returned. When target is Some(t), only the specified target (snake_case) is returned.

Returns JSON string with shape:

{
  "resolved": { "journal": { "path": "...", "pkg": true } },
  "sources":  { "journal": { "path": "env",  "pkg": "global" } }
}
Source

fn info<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = String> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Show server configuration and diagnostic info.

Source

fn hub_index_aggregate<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Return the aggregated hub index across all registered sources as a JSON string.

Merges the cached hub_index.json from every discovered source URL. Sources that fail to load produce warnings that are embedded in the returned JSON under a "warnings" field so the MCP caller can observe partial failures.

Returns Ok(json_string) where the JSON has shape:

{ "schema_version": "hub_index/v0", "packages": [...], "warnings": [...] }

Returns Err(message) only when the hub registries file itself is corrupt (hard I/O failure), making further index discovery impossible.

Source

fn pool_ensure<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Ensure pool workers are alive; GC stale entries. Idempotent.

Returns JSON {"sessions": [...], "pool_version": "..."}.

Source

fn pool_status<'life0, 'async_trait>( &'life0 self, sid: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Return pool worker status (registry.json + live state).

When sid is provided, restricts to a single worker. Returns JSON {"sessions": [...], "pool_version": "..."}.

Source

fn pool_stop<'life0, 'async_trait>( &'life0 self, sid: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Send SIGTERM to all workers (sid=None) or a single worker.

Returns JSON {"stopped": [...], "errors": [...]}.

Provided Methods§

Source

fn card_sink_backfill<'life0, 'async_trait>( &'life0 self, _sink: String, _dry_run: bool, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Backfill one subscriber (sink URI) with all cards from the primary store. Drift-safe: cards already present on the sink are skipped (never overwritten). Returns a SinkBackfillReport serialized as a JSON string.

Source

fn card_analyze<'life0, 'life1, 'async_trait>( &'life0 self, _card_id: &'life1 str, _pkg: Option<String>, ) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run a Card analyzer package over a single Card.

The host loads the Card body + samples sidecar, builds a Lua ctx ({ card, samples, card_id }), and dispatches to the named pkg via require(pkg).run(ctx). The default pkg name is "card_analysis" — backed by the constant DEFAULT_CARD_ANALYZE_PKG defined in algocline_app::service::card. This is an IF promise, not a bundled hard dependency. If the pkg is missing the call returns an error.

Sister tool to advice: advice runs a generic strategy over a free-form task, while card_analyze runs an analyzer over a Card and its samples. The Card domain is owned by the host (Card schema parsing + samples sidecar load), not the pkg.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§