Context: Rust

Let's look at using Tenx with ruskel to provide library context for Rust.

Ruskel

Ruskel takes a Rust crate or module, and produces a skeleton of its public API, using syntactically correct Rust, all in one file. If the crate or module is not local, it will consult crates.io to download the source to produce the skeleton.

As an example, here's the output of the ruskel command line tool for the very tiny termsize library.

Note that the module structure is preserved with rust mod statements, and all structs, traits, functions in the public API are included along with their docs, but the implementation is elided.

Now this is very useufl as a quick, complete command-line reference to a module, but it really shines when used to provide complete module context to a model. Tenx's Ruskel integration means you can easily and quickly provide full module documentation for any library on crates.io.

Another handy trick is to add a Ruskel context for local crates to your config. Tenx itself does this to add libtenx by default, which means that we always have an up to date snapshot of our API while working.

Ruskel and Tenx

Let's do something a bit more meaty. Misanthropy is a complete set of bindings to the Anthropic API. It's a sister project of Tenx, as well as being developed entirely using Tenx. The Ruskel output for Misanthropy is too long to include here, but you can view it yourself with:

ruskel misanthropy

Our mission is to write a simple command line tool that uses Misanthropy to make a call to the Anthropic API. First, let's define our starting point - initially, we'll just have a simple placeholder command that prints "Hello word!", like this:

fn main() {
    println!("Hello, world!");
} 

Now, we create a new session, and add the Misanthropy Ruskel skeleton to it.

caption

Finally, we use the tenx code command to ask Tenx to write code within the current session. For good measure, we'll also use GPT4o for this, rather than the default Claude Sonnet.

caption

And here's the result - the model has used the detailed API definition we provided it to create a perfectly valid interaction with Anthropic.

use misanthropy::{Anthropic, Content, Message, MessagesRequest, Role};
use std::env;

#[tokio::main]
async fn main() {
    // Read API key from the environment
    let api_key = env::var("ANTHROPIC_API_KEY").expect("API key not found in environment");

    // Create a new Anthropic client
    let client = Anthropic::new(&api_key);

    // Create a new message request
    let request = MessagesRequest {
        model: misanthropy::DEFAULT_MODEL.to_string(),
        max_tokens: 50,
        messages: vec![Message {
            role: Role::User,
            content: vec![Content::Text(misanthropy::Text::new("How do you feel?"))],
        }],
        ..Default::default()
    };

    // Send the request to the API and await the response
    match client.messages(&request).await {
        Ok(response) => {
            for content in response.content {
                if let Content::Text(text) = content {
                    println!("{}", text.text);
                }
            }
        }
        Err(err) => eprintln!("Error: {:?}", err),
    }
} 

For good measure, here's the output of a run of the resulting program:

As an AI language model, I don't have feelings in the same way that humans do. I don't experience emotions like happiness, sadness, or anger. My responses are generated based on the patterns and information I've learned from the vast amount