use ag_harness::{KimiConfig, ModelClient};
#[path = "support/greeting.rs"]
mod greeting;
#[cfg(test)]
#[path = "support/process_fixture.rs"]
mod process_fixture;
#[path = "support/telemetry.rs"]
mod telemetry;
use telemetry::DynError;
#[tokio::main]
async fn main() -> Result<(), DynError> {
telemetry::run_with_metrics("ag-harness-kimi", run()).await
}
async fn run() -> Result<(), DynError> {
let config = KimiConfig {
api_key: std::env::var("KIMI_API_KEY")?,
base_url: std::env::var("KIMI_BASE_URL")?,
model: std::env::var("KIMI_MODEL")?,
};
request_greeting(config).await
}
async fn request_greeting(config: KimiConfig) -> Result<(), DynError> {
let client = ModelClient::kimi(config)?;
greeting::request(client, "Kimi").await
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test(flavor = "current_thread")]
async fn request_greeting_rejects_invalid_model() {
let config = KimiConfig {
api_key: "test-key".to_string(),
base_url: "https://example.com".to_string(),
model: " ".to_string(),
};
let error = request_greeting(config)
.await
.expect_err("invalid model configuration should fail");
assert_eq!(error.to_string(), "model identifier must not be empty");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn process_exports_metrics_over_otlp_http_on_shutdown() {
let environment = process_fixture::ProviderEnvironment::new(
"KIMI_API_KEY",
"KIMI_BASE_URL",
Some(("KIMI_MODEL", Some("kimi-k2.6"))),
);
let responses = vec![process_fixture::terminal_response(r#"{"message":"hello"}"#)];
process_fixture::assert_exports_metrics(environment, responses).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn process_timeout_kills_and_reaps_fixture() {
let environment = process_fixture::ProviderEnvironment::new(
"KIMI_API_KEY",
"KIMI_BASE_URL",
Some(("KIMI_MODEL", Some("kimi-k2.6"))),
);
process_fixture::assert_timeout_kills_and_reaps(environment).await;
}
#[test]
fn process_fixture_runs_main() {
let run = main;
process_fixture::run_main_if_requested(run);
}
}