cyrup_sugars

Crates.iocyrup_sugars
lib.rscyrup_sugars
version0.5.4
created_at2025-07-17 19:56:21.92428+00
updated_at2025-10-27 03:34:02.583975+00
descriptionMain crate providing syntactic sugar and utilities for Rust development
homepagehttps://github.com/cyrup-ai/cyrup-sugars
repositoryhttps://github.com/cyrup-ai/cyrup-sugars
max_upload_size
id1758035
size59,593
David Maple (kloudsamurai)

documentation

https://docs.rs/cyrup_sugars

README

sugars

Crates.io Documentation License: MIT OR Apache-2.0

Cyrup Sugars

Syntactic sugar utilities for Rust - collections, async patterns, and macros.

Features

  • collections - Collection types: ZeroOneOrMany, OneOrMany, ByteSize
  • async - Async utilities: AsyncTask and AsyncStream
  • macros - Collection and async macros
  • array-tuples - Array tuple syntax for collections
  • builders - Builder traits: MessageChunk, ChunkHandler
  • gix-interop - Git object hash tables

Array Tuple Syntax

The array-tuples feature enables intuitive array tuple syntax in builder patterns:

let builder = FluentAi::agent_role("example")
    .additional_params([("beta", "true"), ("debug", "false")])
    .metadata([("key", "val"), ("foo", "bar")])
    .tools((
        Tool::<Perplexity>::new([("citations", "true"), ("format", "json")]),
    ));

Implementation Pattern:

/// Set additional parameters with array tuple syntax
pub fn additional_params<T>(mut self, params: T) -> Self
where
    T: IntoHashMap
{
    let config_map = params.into_hashmap();
    let mut map = HashMap::new();
    for (k, v) in config_map {
        map.insert(k.to_string(), Value::String(v.to_string()));
    }
    self.additional_params = Some(map);
    self
}

Usage: .additional_params([("beta", "true"), ("debug", "false")])

The array tuple syntax [("key", "value")] works seamlessly with the IntoHashMap trait, providing a clean and intuitive API for developers.

πŸ“– For complete implementation details, see the Array Tuple Syntax Implementation Guide

AsyncTask Pattern

The async feature provides concrete async types that avoid boxed futures:

use sugars_async_task::AsyncTask;
use sugars_collections::ZeroOneOrMany;

// Single receiver
let task = AsyncTask::new(ZeroOneOrMany::one(rx));

// Multiple receivers (first result wins)
let task = AsyncTask::new(ZeroOneOrMany::many(vec![rx1, rx2, rx3]));

// From future
let task = AsyncTask::from_future(some_async_operation());

let result = task.await;

AsyncTask supports single and multiple receivers using the ZeroOneOrMany pattern, enabling race conditions, fallback patterns, and load balancing.

πŸ“– For complete usage examples, see the AsyncTask Usage Guide

Collection Types

The collections feature provides memory-efficient collection types for different scenarios:

use sugars_collections::{OneOrMany, ZeroOneOrMany};

// OneOrMany: Non-empty collections (guaranteed at least one element)
let servers = OneOrMany::many(vec!["server1", "server2"]).unwrap();
let primary = servers.first(); // Always exists

// ZeroOneOrMany: Flexible collections (zero allocations for None/One)
let middleware = ZeroOneOrMany::none();
let middleware = middleware.with_pushed("auth");
let middleware = middleware.with_pushed("cors");

match middleware {
    ZeroOneOrMany::None => println!("No middleware"),
    ZeroOneOrMany::One(mw) => println!("Single middleware: {}", mw),
    ZeroOneOrMany::Many(mws) => println!("Multiple middleware: {:?}", mws),
}

Both types support JSON serialization, builder patterns, and zero-allocation optimizations for small collections.

πŸ“– For complete guides, see OneOrMany Guide and ZeroOneOrMany Guide

Builder Traits

The builders feature provides traits for message chunk handling:

  • MessageChunk - Trait for types that can represent both success and error states
  • ChunkHandler<T, E> - Handles streaming Result<T, E> by unwrapping to T

These traits enable consistent error handling patterns across builders with a single on_chunk method that handles both success and error cases.

πŸ“– For complete implementation guide, see the ChunkHandler Pattern Guide - Step-by-step instructions for implementing the full pattern from scratch.

Quick Start

Add this to your Cargo.toml:

[dependencies]
cyrup_sugars = "0.1.0"

Or with specific features:

[dependencies]
cyrup_sugars = { version = "0.1", features = ["array-tuples"] }

Example

let stream = FluentAi::agent_role("rusty-squire")
    .completion_provider(Mistral::MagistralSmall)
    .temperature(1.0)
    .max_tokens(8000)
    .system_prompt("Act as a Rust developers 'right hand man'.
        You possess deep expertise in using tools to research rust, cargo doc and github libraries.
        You are a patient and thoughtful software artisan; a master of sequential thinking and step-by-step reasoning.
        You excel in compilation triage ...

        ...
        ...

        Today is {{ date }}

        ~ Be Useful, Not Thorough")
    .context( // trait Context
        Context<File>::of("/home/kloudsamurai/ai_docs/mistral_agents.pdf"),
        Context<Files>::glob("/home/kloudsamurai/cyrup-ai/**/*.{md,txt}"),
        Context<Directory>::of("/home/kloudsamurai/cyrup-ai/agent-role/ambient-rust"),
        Context<Github>::glob("/home/kloudsamurai/cyrup-ai/**/*.{rs,md}")
    )
    .mcp_server<Stdio>::bin("/user/local/bin/sweetmcp").init("cargo run -- --stdio")
    .tools( // trait Tool
        Tool<Perplexity>::new([
            ("citations", "true"), ("format", "json")
        ]),
        Tool::named("cargo").bin("~/.cargo/bin").description("cargo --help".exec_to_text())
    ) // ZeroOneOrMany `Tool` || `McpTool` || NamedTool (WASM)

    .additional_params([("beta", "true"), ("debug", "false")])
    .memory(Library::named("obsidian_vault"))
    .metadata([("key", "val"), ("foo", "bar")])
    .on_tool_result(|results| {
        // do stuff
    })
    .on_conversation_turn(|conversation, agent| {
        log.info("Agent: " + conversation.last().message())
        agent.chat(process_turn()) // your custom logic
    })
    .on_chunk(|result| match result {  // Handle Result<T, E> unwrapping
        Ok(chunk) => {
            println!("{}", chunk);
            chunk
        },
        Err(e) => ConversationChunk::bad_chunk(e)  // Convert error to bad chunk
    })
    .into_agent() // Agent Now
    .conversation_history(MessageRole::User => "What time is it in Paris, France",
            MessageRole::System => "The USER is inquiring about the time in Paris, France. Based on their IP address, I see they are currently in Las Vegas, Nevada, USA. The current local time is 16:45",
            MessageRole::Assistant => "It’s 1:45 AM CEST on July 7, 2025, in Paris, France. That’s 9 hours ahead of your current time in Las Vegas.")
    .chat("Hello")? // AsyncStream<MessageChunk
    .collect();

## Working Examples

### Message Chunk Handling

The `builders` feature provides powerful traits for handling streaming message chunks:

```rust
use cyrup_sugars::prelude::*;
use sugars_llm::*;

// MessageChunk trait - implemented by chunk types
pub trait MessageChunk: Sized {
    fn bad_chunk(error: String) -> Self;  // Create error chunk
    fn error(&self) -> Option<&str>;      // Get error if present
    fn is_error(&self) -> bool;           // Check if error chunk
}

// ChunkHandler trait - processes Result<T, E> streams
let builder = builder
    .on_chunk(|result| match result {
        Ok(chunk) => chunk,
        Err(e) => ConversationChunk::bad_chunk(e)
    });

Array Tuple Syntax

// All these patterns work with array tuple syntax:
Tool::<Perplexity>::new([("citations", "true")])
    .additional_params([("beta", "true"), ("debug", "false")])
    .metadata([("key", "val"), ("foo", "bar")])

Run Examples

# Array tuple syntax with on_chunk method
cd examples/array_tuple_syntax && cargo run

# Async task pipeline
cd examples/async_task_example && cargo run

# Collection types
cd examples/one_or_many_example && cargo run
cd examples/zero_one_or_many_example && cargo run

Testing

Run tests with full coverage:

# Run all tests
cargo test --all-features

# Generate coverage report
cargo tarpaulin --all-features --out Html

Documentation

Generate and view documentation:

cargo doc --all-features --open

Benchmarks

Run performance benchmarks:

cargo bench --all-features

Contributing

Contributions are welcome! Please ensure:

  1. All tests pass: cargo test --all-features
  2. Code is formatted: cargo fmt
  3. No clippy warnings: cargo clippy --all-features -- -D warnings
  4. Documentation is updated: cargo doc --all-features
  5. Examples work: cargo run --example <name> --features <features>

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Commit count: 0

cargo fmt