algocline 0.47.0

LLM amplification engine — MCP server with Lua scripting
{
  "crate": "algocline-app",
  "version": "0.45.0",
  "items": [
    {
      "path": "algocline_app::pool",
      "kind": "module",
      "docs": "Process-pool IPC layer for `host_mode=true` execution.\n\nThis module provides the foundation types and dispatch helpers for the\npool worker protocol:\n\n- [`error`] — [`PoolError`] enum (thiserror-derived)\n- [`protocol`] — [`PoolRequest`] / [`PoolResponse`] wire types (serde JSON line)\n- [`client`] — [`PoolClient`] UDS client (connect + handshake + send_request)\n- [`registry`] — [`PoolRegistry`] persistence + GC (registry.json)\n- [`dispatch`] — worker spawn + UDS proxy orchestration"
    },
    {
      "path": "algocline_app::pool::client",
      "kind": "module",
      "docs": "UDS client for connecting to a pool worker process.\n\n[`PoolClient`] is the MCP-side (AppService-side) handle that opens a Unix\ndomain socket connection to a worker subprocess and exchanges\n[`PoolRequest`] / [`PoolResponse`] messages in JSON-line format."
    },
    {
      "path": "algocline_app::pool::client::POOL_PROTOCOL_VERSION",
      "kind": "constant",
      "docs": "Version string embedded in every handshake to prevent client/server skew."
    },
    {
      "path": "algocline_app::pool::client::PoolClient",
      "kind": "struct",
      "docs": "A thin UDS client for communicating with a pool worker process.\n\nEach `PoolClient` instance owns a single Unix domain socket connection to\none worker. Messages are JSON lines (`\\n`-terminated).\n\n# Lifecycle\n\n1. Call [`PoolClient::connect`] — opens the socket and runs the version\n   handshake atomically.  If the handshake fails the connection is dropped\n   and an error is returned; no `PoolClient` instance is produced.\n2. Call [`PoolClient::send_request`] for each message.\n3. Drop the `PoolClient` when done; the underlying socket is closed."
    },
    {
      "path": "algocline_app::pool::dispatch",
      "kind": "module",
      "docs": "Host-mode dispatch helpers.\n\nProvides [`run_via_pool`] and [`continue_via_pool`] which orchestrate\nworker subprocess spawning, UDS connection, registry persistence, and\nresponse forwarding.\n\n## Crux invariants enforced here\n\n- (MCP thin proxy IPC boundary): all host_mode=true calls reach a worker\n  subprocess via [`PoolClient`] over a Unix domain socket.  The MCP-internal\n  [`SessionRegistry`] is never touched on this path.\n- (Registry reconnect across restarts): every successful [`run_via_pool`]\n  call persists the session entry to `registry.json` via\n  [`with_registry_lock`] before returning.  A restarted MCP process can\n  rediscover live workers from that file."
    },
    {
      "path": "algocline_app::pool::dispatch::continue_via_pool",
      "kind": "function",
      "docs": "Reconnect to an existing pool worker via its registry entry and forward a\n`Continue` request.\n\n# Arguments\n\n* `entry` — the registry entry for the target worker (sock path, etc.).\n* `sid` — session ID to resume.\n* `response` — LLM response text.\n* `query_id` — optional query ID being answered.\n* `usage` — optional token usage.\n\n# Returns\n\n`Ok(json_response)` — the stringified `feed_result` JSON from the worker.\n\n# Errors\n\nReturns `Err(PoolError)` on UDS connect failure or invalid response.\n\n# Cancel safety\n\nIf this future is cancelled mid-await, the `PoolClient` is dropped and\nthe socket is closed.  `read_line` is not cancel-safe; a partial line\nwould corrupt the buffer.  Dropping the client is the correct recovery —\nthe next `continue_via_pool` call creates a fresh connection."
    },
    {
      "path": "algocline_app::pool::dispatch::run_via_pool",
      "kind": "function",
      "docs": "Spawn a worker subprocess, connect via UDS, proxy a `Run` request,\nand persist the session entry to `registry.json`.\n\nOn success, returns `(session_id, json_response, Option<pool_save_error>)`.\nThe optional `pool_save_error` is `Some(msg)` when the registry write\nfailed — callers must surface this as an additive field on the MCP wire\nresponse.\n\n# Concurrency\n\n**Cancel safety**: this function is **not** cancel safe. If dropped during\n`PoolClient::connect` or `send_request`, the `PoolClient` is dropped and\nthe UDS connection is closed. The worker subprocess continues running; the\nsession can be resumed via `continue_via_pool` using the registry entry.\n\n**Locks**: acquires an advisory `fs4` flock (inside `spawn_blocking`) for\nthe registry add/save. The lock is held only for the duration of the\nsynchronous I/O in `persist_entry` and is released before this function\nreturns. No `std::sync::Mutex` or `tokio::sync::Mutex` is held across\n`.await` points in this function.\n\n**Zombie reaping**: `spawn_worker` starts a background `tokio::spawn` reap\ntask. If this function returns `Err`, the spawned reap task continues in the\nbackground and the OS process entry is reaped when the worker exits.\n\n**Socket wait timeout**: polls for socket file appearance with a 5 s\n`tokio::time::timeout`. If the socket does not appear in 5 s,\n`Err(PoolError::Handshake)` is returned.\n\n# Errors\n\nReturns `Err(PoolError)` if worker spawn, socket wait, or UDS run\nround-trip fails. Registry persistence failure is returned in the\n`pool_save_error` field, not as `Err`."
    },
    {
      "path": "algocline_app::pool::error",
      "kind": "module",
      "docs": "Error types produced by the process-pool IPC layer.\n\nAll variants propagate to callers via `Result<T, PoolError>` and\nare converted to `String` at the `AppService` boundary (Subtask\n5/6) to satisfy the existing `EngineApi` wire contract."
    },
    {
      "path": "algocline_app::pool::error::PoolError",
      "kind": "enum",
      "docs": "Errors produced by the process-pool IPC layer.\n\nAll variants are propagated to callers via `Result<T, PoolError>`.\nAt the `AppService` boundary (Subtask 5/6) these are converted to\n`String` to satisfy the existing `EngineApi` wire contract."
    },
    {
      "path": "algocline_app::pool::protocol",
      "kind": "module",
      "docs": "Wire protocol messages exchanged between the pool client (MCP\nprocess) and pool workers over Unix domain sockets.\n\nRequests carry an `\"op\"` discriminant and are serialised as single\nJSON lines. Responses mirror the same shape and are correlated by\nthe request ordering on a per-connection basis."
    },
    {
      "path": "algocline_app::pool::protocol::PoolRequest",
      "kind": "enum",
      "docs": "A message sent from the MCP process (pool client) to a pool worker.\n\nSerialised as a single JSON line with an `\"op\"` discriminant field.\n\n```json\n{\"op\":\"handshake\",\"version\":\"0.31.0\"}\n{\"op\":\"run\",\"code\":\"return 1\",\"ctx\":null,\"lib_paths\":[]}\n{\"op\":\"continue\",\"sid\":\"abc\",\"response\":\"yes\",\"query_id\":\"q1\",\"usage\":null}\n{\"op\":\"status\"}\n{\"op\":\"shutdown\"}\n```"
    },
    {
      "path": "algocline_app::pool::protocol::PoolResponse",
      "kind": "struct",
      "docs": "A message sent from a pool worker back to the pool client.\n\nSerialised as a single JSON line:\n\n```json\n{\"ok\":true,\"data\":{\"kind\":\"handshake\",\"version\":\"0.31.0\"}}\n{\"ok\":false,\"error\":\"worker handshake failed: version mismatch\"}\n```"
    },
    {
      "path": "algocline_app::pool::protocol::PoolResponseData",
      "kind": "enum",
      "docs": "Data payload carried by a successful [`PoolResponse`].\n\n`FeedResult`-equivalent payloads are represented as `serde_json::Value` so\nthat the `pool` protocol module does not introduce a hard dependency on the\n`algocline-engine` crate's concrete type.  Subtask 5 (AppService dispatch)\nwill deserialize the value into the appropriate engine type at the call site."
    },
    {
      "path": "algocline_app::pool::registry",
      "kind": "module",
      "docs": "Pool registry: persistent session-to-worker mapping.\n\n[`PoolRegistry`] tracks live pool worker processes in\n`~/.algocline/state/pool/registry.json`.  The file survives MCP-process\ndeath so a restarted MCP can rediscover live worker sockets.\n\n## Crux invariant (Registry reconnect across restarts)\n\n`registry.json` is the **persistent source of truth**.  The in-memory\n`PoolRegistry` value is a short-lived view — callers must reload from disk\nafter acquiring the advisory lock rather than caching across lock cycles."
    },
    {
      "path": "algocline_app::pool::registry::PoolRegistry",
      "kind": "struct",
      "docs": "In-memory view of `registry.json`.\n\nThis struct must **always** be loaded from and saved to disk within a\nsingle advisory-lock region (see [`with_registry_lock`]).  Do not hold\na `PoolRegistry` value across lock boundaries.\n\n## Crux: registry.json is the persistent source of truth\n\nMCP processes must not rely on any in-memory state to discover live\nworkers after a restart.  Every mutation path must call [`save`] before\ndropping the lock.\n\n[`save`]: PoolRegistry::save"
    },
    {
      "path": "algocline_app::pool::registry::PoolSessionEntry",
      "kind": "struct",
      "docs": "A single session entry in the pool registry.\n\n# Fields\n\n- `sid` — session ID string (UUID or similar).\n- `pid` — OS process-ID of the worker; used for liveness checks via\n  `kill -0`.\n- `sock` — absolute path to the Unix-domain socket owned by the worker.\n- `version` — crate version at the time the worker was spawned; used in\n  version-handshake validation.\n- `created_at` — ISO 8601 timestamp of worker creation."
    },
    {
      "path": "algocline_app::pool::registry::with_registry_lock",
      "kind": "function",
      "docs": "Run `f` while holding an exclusive advisory lock on `lock_path`, using the\nsame `fs4`-backed mechanism as `service::lock::with_exclusive_lock`.\n\nCallers should pass the `registry.lock` sentinel path (e.g.\n`app_dir.root().join(\"pool/registry.lock\")`).\n\n# Arguments\n\n* `lock_path` — path to the advisory lock file (created if absent).\n* `f` — closure to run under the lock.\n\n# Returns\n\nPropagates the return value of `f`.\n\n# Errors\n\nReturns `PoolError::RegistryCorrupted` if the lock file cannot be created\nor the exclusive lock cannot be acquired.\n\n# Concurrency\n\nThe lock is released when the underlying `File` is dropped, which occurs\non all exit paths from this function including panics (RAII / drop)."
    }
  ]
}