#![allow(dead_code)]
use axum::{
extract::State,
http::{header, StatusCode},
response::IntoResponse,
routing::post,
Router,
};
use serde_json::json;
use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc,
};
use tokio_util::sync::CancellationToken;
#[derive(Clone)]
pub struct DiffMockState {
pub call_count: Arc<AtomicUsize>,
}
async fn diff_messages_handler(
State(state): State<DiffMockState>,
body: axum::body::Bytes,
) -> impl IntoResponse {
if let Err(e) = serde_json::from_slice::<serde_json::Value>(&body) {
eprintln!("[compile_loop_diff_anthropic_mock] bad request body: {e}");
let err_body = json!({ "error": format!("bad request: {e}") }).to_string();
return (
StatusCode::BAD_REQUEST,
[(header::CONTENT_TYPE, "application/json")],
err_body,
);
}
let prev = state.call_count.fetch_add(1, Ordering::SeqCst);
let text = if prev == 0 {
"<<<<<<< SEARCH\nprint(\"WRONG\")\n=======\nprint(\"world\")\n>>>>>>> REPLACE"
} else {
"<<<<<<< SEARCH\nprint(\"hello\")\n=======\nprint(\"world\")\n>>>>>>> REPLACE"
};
let response_json = json!({
"id": format!("msg_diff_mock_{}", prev + 1),
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": text
}
],
"model": "claude-haiku-mock",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 10,
"output_tokens": 20
}
});
(
StatusCode::OK,
[(header::CONTENT_TYPE, "application/json")],
response_json.to_string(),
)
}
pub async fn spawn_compile_loop_diff_anthropic_mock_server(
) -> (String, Arc<AtomicUsize>, CancellationToken) {
let call_count = Arc::new(AtomicUsize::new(0));
let ct = CancellationToken::new();
let state = DiffMockState {
call_count: call_count.clone(),
};
let router = Router::new()
.route("/v1/messages", post(diff_messages_handler))
.with_state(state);
let listener = tokio::net::TcpListener::bind("127.0.0.1:0")
.await
.expect("bind ephemeral port for compile_loop diff anthropic mock");
let addr = listener.local_addr().expect("local_addr");
let ct_shutdown = ct.clone();
tokio::spawn(async move {
let _ = axum::serve(listener, router)
.with_graceful_shutdown(async move { ct_shutdown.cancelled_owned().await })
.await;
});
(format!("http://{addr}"), call_count, ct)
}