use std::{
env, fs,
io::{self, Write},
};
use claus::{
anthropic::{Message, MessagesResponse, Role},
deserialize_response,
};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Config {
anthropic_api_key: String,
}
fn main() {
let config_file = env::args()
.nth(1)
.expect("requires argument: path to TOML config file");
let client = reqwest::blocking::Client::new();
let config_content = fs::read_to_string(&config_file).expect("failed to read config file");
let config: Config = toml::from_str(&config_content).expect("failed to parse config TOML");
let api = claus::Api::new(config.anthropic_api_key);
let mut messages = im::Vector::new();
while let Some(input) = read_next_line() {
messages.push_back(Message::from_text(Role::User, input));
let http_req = claus::MessagesRequestBuilder::new()
.set_messages(messages.clone())
.build(&api);
let raw = client
.execute(http_req.into())
.expect("failed to execute request")
.text()
.expect("failed to fetch response text");
let response: MessagesResponse =
deserialize_response(&raw).expect("failed to parse response");
for content in &response.message {
println!("Claude: {}", content);
}
messages.push_back(response.message);
}
}
fn read_next_line() -> Option<String> {
let stdin = io::stdin();
let mut stdout = io::stdout();
let mut input = String::new();
stdout.write_all(b"You: ").expect("stdout failed to write");
stdout.flush().expect("stdout failed to flush");
if stdin.read_line(&mut input).expect("stdin failed to read") == 0 {
None
} else {
Some(input)
}
}