feat: add pi lab ai management integration

This commit is contained in:
Agent Board
2026-07-04 21:47:42 +08:00
parent 36d027a4a1
commit c8472bb898
62 changed files with 15077 additions and 443 deletions
+115
View File
@@ -261,6 +261,88 @@ pub async fn user_access_policy_entry(
Ok(response)
}
pub async fn admin_ai_entry(
State(state): State<AppState>,
Extension(context): Extension<RequestContext>,
) -> Result<Response, WebError> {
if !has_real_auth_context(&state, &context) {
let mut response = Response::builder()
.status(StatusCode::SEE_OTHER)
.header(header::LOCATION, "/auth")
.body(Body::empty())
.map_err(|error| WebError::internal(format!("认证入口跳转响应构造失败: {error}")))?;
stamp_gateway_headers(response.headers_mut(), false);
return Ok(response);
}
if !is_local_access_policy_admin_context(&context) {
return Err(WebError::new(
StatusCode::FORBIDDEN,
"ai_admin_required",
"只有管理员可以访问 AI 管理中心",
)
.with_context(&context));
}
ai_management_response(&state, &context, true)
}
pub async fn user_ai_entry(
State(state): State<AppState>,
Extension(context): Extension<RequestContext>,
) -> Result<Response, WebError> {
if !has_real_auth_context(&state, &context) {
let mut response = Response::builder()
.status(StatusCode::SEE_OTHER)
.header(header::LOCATION, "/auth")
.body(Body::empty())
.map_err(|error| WebError::internal(format!("认证入口跳转响应构造失败: {error}")))?;
stamp_gateway_headers(response.headers_mut(), false);
return Ok(response);
}
ai_management_response(&state, &context, false)
}
fn ai_management_response(
state: &AppState,
context: &RequestContext,
is_admin: bool,
) -> Result<Response, WebError> {
let workspace_name = default_workspace_name_for_context(state, context);
let content = crate::ssr::render_view(leptos::view! {
<crate::ssr::pages::ai_admin::AiManagementPage
workspace_name={workspace_name}
is_admin={is_admin}
/>
});
let title = if is_admin { "AI 管理" } else { "AI 设置" };
let shell = if is_admin {
"admin-ai"
} else {
"user-ai-admin"
};
let mut response = Html(format!(
r#"<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{}</title>
<style>{}</style>
</head>
<body data-mnote-web-owner="mnote-web" data-mnote-shell="{}" data-mnote-actor-id="{}">
{}
</body>
</html>"#,
title,
crate::ssr::MNOTE_CSS,
shell,
escape_html(context.auth.actor_id.as_str()),
content
))
.into_response();
stamp_gateway_headers(response.headers_mut(), false);
Ok(response)
}
pub async fn root_entry(
State(state): State<AppState>,
Extension(context): Extension<RequestContext>,
@@ -579,6 +661,21 @@ pub async fn root_entry(
escape_script_json(&panes_bootstrap_json),
render_editor_island_adapter_script(),
);
let body_extra = if state.config().enable_page_ai_pi_lab {
body_extra
+ &format!(
r#"<script>
(function() {{
var s = document.createElement('script');
s.src = '/api/mnote-browser-runtime/sidebar-page-ai-pi-lab-runtime.js';
s.onload = function() {{ if (window.createSidebarPageAiPiLabRuntime) window.createSidebarPageAiPiLabRuntime({{}}); }};
document.body.appendChild(s);
}})();
</script>"#
)
} else {
body_extra
};
("MNOTE".to_string(), render_workspace_entry(), body_extra)
} else {
match build_page_aggregate_snapshot(
@@ -639,6 +736,21 @@ pub async fn root_entry(
render_document_title_controller_script(),
render_editor_island_adapter_script(),
);
let body_extra = if state.config().enable_page_ai_pi_lab {
body_extra
+ &format!(
r#"<script>
(function() {{
var s = document.createElement('script');
s.src = '/api/mnote-browser-runtime/sidebar-page-ai-pi-lab-runtime.js';
s.onload = function() {{ if (window.createSidebarPageAiPiLabRuntime) window.createSidebarPageAiPiLabRuntime({{}}); }};
document.body.appendChild(s);
}})();
</script>"#
)
} else {
body_extra
};
(title.to_string(), content, body_extra)
}
Err(_) => ("MNOTE".to_string(), render_workspace_entry(), String::new()),
@@ -2554,6 +2666,7 @@ mod tests {
enable_legacy_next_compat,
enable_debug_shell_routes: false,
enable_editor_actor: true,
enable_page_ai_pi_lab: false,
hermes_base_path: "/api/hermes".into(),
compat_next_base_path: "/api/compat/next".into(),
convex_url,
@@ -3074,6 +3187,7 @@ mod tests {
enable_legacy_next_compat: false,
enable_debug_shell_routes: false,
enable_editor_actor: true,
enable_page_ai_pi_lab: false,
hermes_base_path: "/api/hermes".into(),
compat_next_base_path: "/api/compat/next".into(),
convex_url: None,
@@ -3366,6 +3480,7 @@ mod tests {
enable_legacy_next_compat: false,
enable_debug_shell_routes: false,
enable_editor_actor: true,
enable_page_ai_pi_lab: false,
hermes_base_path: "/api/hermes".into(),
compat_next_base_path: "/api/compat/next".into(),
convex_url: None,