draft working stuff
This commit is contained in:
@@ -1,25 +1,116 @@
|
||||
use axum::body::Bytes;
|
||||
use axum::{
|
||||
body::Bytes,
|
||||
response::{IntoResponse, Response},
|
||||
routing::post,
|
||||
Router,
|
||||
};
|
||||
use http::{HeaderMap, StatusCode};
|
||||
use reqwest::Client;
|
||||
use windmill_common::ee::{EEServiceError, WINDMILL_CUSTOMER_SERVICE_BASE_URL};
|
||||
use tracing::{error, info, warn};
|
||||
use windmill_common::ee::WINDMILL_CUSTOMER_SERVICE_BASE_URL;
|
||||
use windmill_common::error::{to_anyhow, Error, Result};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref HTTP_CLIENT: Client = reqwest::ClientBuilder::new()
|
||||
.timeout(std::time::Duration::from_secs(60 * 5))
|
||||
.user_agent("windmill/beta")
|
||||
.build().unwrap();
|
||||
|
||||
static ref OPENAI_AZURE_BASE_PATH: Option<String> = std::env::var("OPENAI_AZURE_BASE_PATH").ok();
|
||||
|
||||
pub static ref AI_REQUEST_CACHE: Cache<(String, AIProvider), ExpiringAIRequestConfig> = Cache::new(500);
|
||||
}
|
||||
|
||||
pub async fn send_inkeep_request(body: Bytes) -> Result<()> {
|
||||
let request_url = format!("{}/inkeep", WINDMILL_CUSTOMER_SERVICE_BASE_URL.as_str());
|
||||
let response = http_client.post(request_url).body(body).send().await?;
|
||||
pub fn global_service() -> Router {
|
||||
Router::new().route("/", post(send_inkeep_request))
|
||||
}
|
||||
|
||||
if response.status().is_success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(EEServiceError::new("Failed to send inkeep request"))
|
||||
pub async fn send_inkeep_request(headers: HeaderMap, body: Bytes) -> impl IntoResponse {
|
||||
let request_url = format!("{}/inkeep", WINDMILL_CUSTOMER_SERVICE_BASE_URL.as_str());
|
||||
|
||||
// Ensure Content-Type is set to application/json
|
||||
let mut forwarded_headers = headers.clone();
|
||||
forwarded_headers.insert(
|
||||
http::header::CONTENT_TYPE,
|
||||
"application/json".parse().unwrap(),
|
||||
);
|
||||
|
||||
match HTTP_CLIENT
|
||||
.post(&request_url)
|
||||
.headers(forwarded_headers)
|
||||
.body(body)
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
let status = response.status();
|
||||
let response_headers = response.headers().clone();
|
||||
|
||||
match response.bytes().await {
|
||||
Ok(response_body) => {
|
||||
info!("Response body size: {} bytes", response_body.len());
|
||||
|
||||
// Build proper axum Response
|
||||
let mut response_builder = Response::builder().status(status);
|
||||
|
||||
// Filter out hop-by-hop headers that shouldn't be forwarded
|
||||
let skip_headers = [
|
||||
"connection",
|
||||
"keep-alive",
|
||||
"proxy-authenticate",
|
||||
"proxy-authorization",
|
||||
"te",
|
||||
"trailers",
|
||||
"transfer-encoding",
|
||||
"upgrade",
|
||||
"content-length", // Let axum handle this
|
||||
];
|
||||
|
||||
// Add safe headers from the upstream response
|
||||
for (key, value) in response_headers.iter() {
|
||||
let key_str = key.as_str().to_lowercase();
|
||||
if !skip_headers.contains(&key_str.as_str()) {
|
||||
response_builder = response_builder.header(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we have content-type for JSON responses
|
||||
response_builder = response_builder.header("content-type", "application/json");
|
||||
|
||||
match response_builder.body(axum::body::Body::from(response_body)) {
|
||||
Ok(response) => {
|
||||
info!("Successfully built response");
|
||||
response
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to build response: {}", e);
|
||||
Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.header("content-type", "application/json")
|
||||
.body(axum::body::Body::from(
|
||||
r#"{"error": "Failed to build response"}"#,
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to read response body: {}", e);
|
||||
Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.header("content-type", "application/json")
|
||||
.body(axum::body::Body::from(
|
||||
r#"{"error": "Failed to read response body"}"#,
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to send request to inkeep service: {}", e);
|
||||
Response::builder()
|
||||
.status(StatusCode::BAD_GATEWAY)
|
||||
.header("content-type", "application/json")
|
||||
.body(axum::body::Body::from(
|
||||
r#"{"error": "Failed to connect to inkeep service"}"#,
|
||||
))
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,11 +151,10 @@ function triggerComponent(args: { id: string; value: string }): string {
|
||||
}
|
||||
|
||||
async function getDocumentation(args: { request: string }): Promise<string | null> {
|
||||
const retrieval = await fetch('https://api.inkeep.com/v1/chat/completions', {
|
||||
const retrieval = await fetch('/api/inkeep', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${import.meta.env.VITE_INKEEP_API_KEY}`
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'inkeep-rag',
|
||||
|
||||
Reference in New Issue
Block a user