solo-core 0.3.7

Solo: shared types and traits for the memory daemon
Documentation
// SPDX-License-Identifier: Apache-2.0

//! `LlmClient` trait + supporting types. See ADR-0002.
//!
//! The Steward struct (`solo-steward`) consumes `Arc<dyn LlmClient>` rather
//! than implementing a Steward trait — the LLM is the swap point, not the
//! consolidation logic.

use crate::error::Result;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Role {
    System,
    User,
    Assistant,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
    pub role: Role,
    pub content: String,
}

impl Message {
    pub fn system(content: impl Into<String>) -> Self {
        Self {
            role: Role::System,
            content: content.into(),
        }
    }

    pub fn user(content: impl Into<String>) -> Self {
        Self {
            role: Role::User,
            content: content.into(),
        }
    }

    pub fn assistant(content: impl Into<String>) -> Self {
        Self {
            role: Role::Assistant,
            content: content.into(),
        }
    }
}

#[async_trait]
pub trait LlmClient: Send + Sync {
    /// Backend identifier — "qwen3-coder-30b-local", "claude-sonnet-4-6",
    /// "gpt-5o", etc. Used in dev-log entries and consolidation provenance
    /// (`Provenance::by`).
    fn name(&self) -> &str;

    /// Run a single completion turn. Implementations handle their own
    /// retries, rate limits, and context-window management.
    async fn complete(&self, messages: &[Message]) -> Result<Message>;
}