Merge remote-tracking branch 'origin/master' into feat/BGfilter

# Conflicts:
#	server-rs/crates/api-server/src/config.rs
This commit is contained in:
2026-07-07 06:32:43 +00:00
18 changed files with 227 additions and 25 deletions
+46
View File
@@ -43,6 +43,7 @@ pub fn build_router(state: AppState) -> Router {
.merge(modules::auth::router(state.clone()))
.merge(modules::profile::router(state.clone()))
.merge(modules::external_api::router(state.clone()))
.merge(modules::frontend_runtime_config::router(state.clone()))
.merge(modules::assets::router(state.clone()))
.merge(modules::editor_project::router(state.clone()))
.merge(modules::platform::router(state.clone()))
@@ -518,6 +519,51 @@ mod tests {
);
}
#[tokio::test]
async fn frontend_runtime_config_defaults_agent_sidebar_to_disabled() {
let app = build_router(AppState::new(AppConfig::default()).expect("state should build"));
let response = app
.oneshot(
Request::builder()
.uri("/api/runtime/frontend-config")
.body(Body::empty())
.expect("frontend config request should build"),
)
.await
.expect("frontend config request should succeed");
assert_eq!(response.status(), StatusCode::OK);
let payload = read_json_response(response).await;
assert_eq!(
payload["imageEditorAgentSidebarEnabled"],
Value::Bool(false)
);
}
#[tokio::test]
async fn frontend_runtime_config_returns_agent_sidebar_env_flag() {
let config = AppConfig {
image_editor_agent_sidebar_enabled: true,
..AppConfig::default()
};
let app = build_router(AppState::new(config).expect("state should build"));
let response = app
.oneshot(
Request::builder()
.uri("/api/runtime/frontend-config")
.body(Body::empty())
.expect("frontend config request should build"),
)
.await
.expect("frontend config request should succeed");
assert_eq!(response.status(), StatusCode::OK);
let payload = read_json_response(response).await;
assert_eq!(payload["imageEditorAgentSidebarEnabled"], Value::Bool(true));
}
#[tokio::test]
async fn spacetime_unavailable_router_returns_service_unavailable_for_requests() {
let app =
+27
View File
@@ -61,6 +61,7 @@ pub struct AppConfig {
pub editor_bgfilter_base_url: String,
pub editor_bgfilter_token: Option<String>,
pub editor_bgfilter_request_timeout_ms: u64,
pub image_editor_agent_sidebar_enabled: bool,
pub log_filter: String,
pub otel_enabled: bool,
pub admin_username: Option<String>,
@@ -291,6 +292,7 @@ impl Default for AppConfig {
editor_bgfilter_base_url: DEFAULT_EDITOR_BGFILTER_BASE_URL.to_string(),
editor_bgfilter_token: None,
editor_bgfilter_request_timeout_ms: DEFAULT_EDITOR_BGFILTER_REQUEST_TIMEOUT_MS,
image_editor_agent_sidebar_enabled: false,
log_filter: "info,tower_http=info".to_string(),
otel_enabled: false,
admin_username: None,
@@ -494,6 +496,11 @@ impl AppConfig {
{
config.editor_bgfilter_request_timeout_ms = timeout_ms;
}
if let Some(enabled) =
read_first_bool_env(&["GENARRATIVE_ENABLE_IMAGE_EDITOR_AGENT_SIDEBAR"])
{
config.image_editor_agent_sidebar_enabled = enabled;
}
if let Some(listen_backlog) =
read_first_positive_i32_env(&["GENARRATIVE_API_LISTEN_BACKLOG"])
{
@@ -2256,6 +2263,26 @@ mod tests {
}
}
#[test]
fn from_env_reads_image_editor_agent_sidebar_runtime_flag() {
let _guard = ENV_LOCK
.get_or_init(|| Mutex::new(()))
.lock()
.expect("env lock should not poison");
unsafe {
std::env::remove_var("GENARRATIVE_ENABLE_IMAGE_EDITOR_AGENT_SIDEBAR");
std::env::set_var("GENARRATIVE_ENABLE_IMAGE_EDITOR_AGENT_SIDEBAR", "true");
}
let config = AppConfig::from_env();
assert!(config.image_editor_agent_sidebar_enabled);
unsafe {
std::env::remove_var("GENARRATIVE_ENABLE_IMAGE_EDITOR_AGENT_SIDEBAR");
}
}
#[test]
fn from_env_reads_prefixed_character_animation_ffmpeg_paths() {
let _guard = ENV_LOCK
@@ -0,0 +1,25 @@
use axum::{
Json,
extract::{Extension, State},
};
use serde::Serialize;
use crate::{api_response::json_success_body, request_context::RequestContext, state::AppState};
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FrontendRuntimeConfigResponse {
pub image_editor_agent_sidebar_enabled: bool,
}
pub async fn get_frontend_runtime_config(
State(state): State<AppState>,
Extension(request_context): Extension<RequestContext>,
) -> Json<serde_json::Value> {
json_success_body(
Some(&request_context),
FrontendRuntimeConfigResponse {
image_editor_agent_sidebar_enabled: state.config.image_editor_agent_sidebar_enabled,
},
)
}
+1
View File
@@ -53,6 +53,7 @@ mod external_editor_api;
mod external_generation;
mod external_generation_worker;
mod external_generation_worker_controller;
mod frontend_runtime_config;
pub(crate) mod generated_asset_sheets;
mod generated_image_assets;
mod health;
@@ -8,6 +8,7 @@ pub mod editor_project;
pub mod edutainment;
pub mod external_api;
pub mod external_generation;
pub mod frontend_runtime_config;
pub mod health;
pub mod internal;
pub mod jump_hop;
@@ -0,0 +1,10 @@
use axum::{Router, routing::get};
use crate::{frontend_runtime_config::get_frontend_runtime_config, state::AppState};
pub fn router(_state: AppState) -> Router<AppState> {
Router::new().route(
"/api/runtime/frontend-config",
get(get_frontend_runtime_config),
)
}