gemini-cli-sdk 0.1.0

Rust SDK wrapping Google's Gemini CLI as a subprocess via JSON-RPC 2.0
Documentation
//! ScenarioBuilder for constructing test scenarios.

use serde_json::Value;

use super::MockTransport;

/// Fluent builder for test scenarios.
///
/// `ScenarioBuilder` collects wire messages that should be emitted by the
/// mock transport during a test, then produces a [`MockTransport`] pre-loaded
/// with those messages.
///
/// # Example
///
/// ```rust,no_run
/// use gemini_cli_sdk::testing::{ScenarioBuilder, assistant_text, tool_call, tool_result};
///
/// let transport = ScenarioBuilder::new("session-123")
///     .with_model("gemini-2.5-pro")
///     .exchange(vec![
///         tool_call("tc-1", "Read file", "file_read"),
///         tool_result("tc-1", "file contents here"),
///         assistant_text("Based on the file, here is my answer."),
///     ])
///     .build();
/// ```
pub struct ScenarioBuilder {
    session_id: String,
    model: String,
    messages: Vec<Value>,
}

impl ScenarioBuilder {
    /// Create a new builder with the given session identifier.
    ///
    /// The `session_id` is stored for test assertion purposes; it does not
    /// affect the messages produced by `exchange()`.
    pub fn new(session_id: impl Into<String>) -> Self {
        Self {
            session_id: session_id.into(),
            model: "gemini-2.5-pro".to_string(),
            messages: Vec::new(),
        }
    }

    /// Override the default model string (`"gemini-2.5-pro"`).
    pub fn with_model(mut self, model: impl Into<String>) -> Self {
        self.model = model.into();
        self
    }

    /// Append a batch of raw JSON-RPC notification values to be yielded in
    /// order from the mock transport's stream.
    ///
    /// Call `exchange` multiple times to build up a multi-turn conversation.
    pub fn exchange(mut self, messages: Vec<Value>) -> Self {
        self.messages.extend(messages);
        self
    }

    /// The session identifier set at construction time.
    pub fn session_id(&self) -> &str {
        &self.session_id
    }

    /// The model string (default `"gemini-2.5-pro"`).
    pub fn model(&self) -> &str {
        &self.model
    }

    /// Consume the builder and produce a [`MockTransport`] pre-loaded with all
    /// messages added via `exchange()`.
    ///
    /// Call [`Transport::connect`] on the returned transport before reading
    /// from its stream.
    ///
    /// [`Transport::connect`]: crate::transport::Transport::connect
    pub fn build(self) -> MockTransport {
        MockTransport::new(self.messages)
    }
}