shuvarie-core 0.2.2

Blazingly fast AI coding TUI for chivalrous people (core module)
Documentation
use shuvarie_config::ProviderConfig;
use shuvarie_db::StoredScroll;

#[derive(Debug, Clone)]
pub enum Command {
    Ping,
    ListModels {
        provider_name: String,
    },
    AddProvider {
        id: String,
        config: ProviderConfig,
    },
    /// Sign in to an OAuth-backed provider (`chatgpt`, `copilot`) through the
    /// device flow: the verification URL + user code surface as
    /// [`crate::Event::AuthPrompt`], and completion or failure arrives as
    /// [`crate::Event::AuthSuccess`] / [`crate::Event::AuthFailed`]. A cached
    /// or pasted credential is verified in place; providers without OAuth
    /// sign-in report a failure explaining that.
    AuthProviderLogin {
        name: String,
    },
    RemoveProvider {
        name: String,
    },
    SetActiveProvider {
        name: String,
    },
    SetActiveModel {
        model: String,
    },
    /// Cycle the active model's reasoning-effort variant (Ctrl+T): forward
    /// through the Selune catalog's variants, wrapping past the last back to
    /// the unset default. A no-op when the active model is not in the catalog.
    CycleVariant,
    /// Set the active model's reasoning-effort variant directly
    /// (`/variant [name]`). The TUI validates the value against the catalog
    /// before sending; `None` selects the unset default.
    SelectVariant {
        variant: Option<String>,
    },
    SaveConfig,
    NewSession,
    /// Start a user turn. `model` optionally overrides the streaming target
    /// for this turn only: a `<provider_type>/<model>` spec resolved to a
    /// provider connection through the `default-providers` config (see
    /// `resolve_model_override`); `None` streams on the active provider.
    /// An unresolvable spec reports [`crate::Event::StreamError`]. A prompt
    /// queued behind a busy agent (steered) keeps its override.
    SendMessage {
        content: String,
        model: Option<String>,
    },
    /// Run a bash-mode (`!`-prefixed) command through the resolved shell.
    /// Display-only: the output never persists or reaches the model.
    RunBash {
        command: String,
    },
    CancelStream,
    ListSessions,
    LoadSession {
        id: uuid::Uuid,
    },
    /// Persist the chat pane's last scroll position for a session, sent by
    /// the TUI when it is about to leave the session (switch or quit).
    SaveScroll {
        id: uuid::Uuid,
        scroll: StoredScroll,
    },
    DeleteSession {
        id: uuid::Uuid,
    },
    /// Rename the active session. The core trims the title; an empty (or
    /// unchanged) title is a no-op.
    SetTitle {
        title: String,
    },
    /// Draft the active session's title with the LLM configured under
    /// `ui.title` `llm` (defaults: the active provider's catalog small model
    /// and the built-in title prompt), from the active path's first user
    /// prompt. Reports [`crate::Event::SessionTitleChanged`] on success and
    /// [`crate::Event::SessionError`] when there is no session, no user
    /// prompt, or no resolvable model. A manual rename that lands while the
    /// call runs wins over the generated title.
    GenTitle,
    SearchHistory {
        query: String,
    },
    AnswerQuestion {
        id: u64,
        /// `None` when the user dismissed the question.
        answers: Option<Vec<Vec<String>>>,
    },
    /// The user's answer to a pending `ask` permission prompt (`id` from
    /// [`crate::Event::PermissionRequested`]). `Allow` grants one call,
    /// `AllowSession` also remembers the ask's scope for the rest of the
    /// run, and `Deny` cuts the turn. A missing id is a no-op.
    PermissionDecide {
        id: u64,
        decision: crate::permissions::PermissionAnswer,
    },
    /// Fork the session: with `node: None`, walk to the active path's last
    /// user prompt (`/undo`); otherwise the fork targets `node`. Turn nodes
    /// fork *before* themselves — their parent becomes the tip and their
    /// content is recalled into the input — while summary/system nodes walk
    /// to themselves. With `after`, the targeted turn node is walked to
    /// instead: it becomes the tip and nothing is recalled (the tree's tool
    /// rows walk to their reply and reply rows walk to themselves this
    /// way). When `summarize`, an LLM summary of the prefix before the fork
    /// point is created first and the forked-away node is reparented under
    /// it.
    ForkSession {
        node: Option<u64>,
        summarize: bool,
        /// Fork *after* the node's turn instead of before it: the node
        /// itself becomes the tip and nothing is recalled into the input.
        after: bool,
    },
    /// Delete a branch of the session tree: the node and all of its
    /// descendants (must not contain the active leaf).
    DeleteBranch {
        node: u64,
    },
    /// Load the active session's tree for the `/tree` popup; reports
    /// [`crate::Event::SessionTree`].
    OpenTree,
    /// Write the active session to a JSON file (`/export [path]`); `None`
    /// picks `<session_id>-<timestamp>.json` in the working directory.
    /// Reports [`crate::Event::SessionExported`] or
    /// [`crate::Event::SessionError`].
    ExportSession {
        path: Option<std::path::PathBuf>,
    },
    /// Switch the active session's scene (`None` = the built-in default
    /// scene). Refused with [`crate::Event::SceneError`] while a stream is
    /// busy or the name does not resolve.
    SwitchScene {
        name: Option<String>,
    },
    Replay,
    Reload,
    /// Recall the most recently steered prompt into the input area. `stacked`
    /// (Alt+Shift+Up) prepends the content to the existing text (separated by
    /// two line feeds) instead of overwriting it.
    RecallSteered {
        stacked: bool,
    },
    LspStart {
        name: String,
    },
    LspStop {
        name: String,
    },
    LspRestart {
        name: String,
    },
    LspList {
        all: bool,
        filter: Option<String>,
    },
    /// Snapshot the configured MCP servers' states and report
    /// [`crate::Event::McpStatus`] (`/mcp`).
    McpList,
    /// Force a fresh connection to an MCP server, dropping any existing one.
    /// Reports [`crate::Event::McpStatus`] on success; on failure
    /// [`crate::Event::McpError`] plus a status snapshot in which the server
    /// carries its failure detail.
    McpReconnect {
        name: String,
    },
    /// Fetch the hosted (Selune) provider registry on demand. Reports
    /// [`Event::RegistryLoaded`] or [`Event::RegistryError`].
    FetchRegistry,
}