chore: harden lightrag knowledge rag runtime

This commit is contained in:
lix-2026
2026-06-09 22:12:09 +08:00
parent 922965d30f
commit f698aad964
22 changed files with 899 additions and 101 deletions
+75 -8
View File
@@ -79,8 +79,21 @@ pub async fn document_page_shell(
)
));
}
let primary_source_kind = normalize_source_kind(query.source_kind.as_deref());
let mut primary_source_kind = normalize_source_kind(query.source_kind.as_deref());
let primary_root_uri = normalize_optional_query_value(query.root_uri.as_deref());
if primary_source_kind.is_none()
&& document_id.trim().starts_with("local-md:")
&& primary_root_uri.is_some()
{
primary_source_kind = Some("local_folder");
}
if primary_source_kind.is_none() && document_id.trim().starts_with("local-md:") {
return redirect_response(&format!(
"/?routeGuard={}&missingPage={}",
query_escape("local_folder_source_required"),
query_escape(&document_id),
));
}
let aggregate = match build_page_aggregate_snapshot(
&state,
&context,
@@ -2249,12 +2262,25 @@ pub async fn pdf_preview_page(Query(query): Query<PdfPreviewQuery>) -> Response
if (viewer) viewer.append(canvas);
if (evidencePage === pageNumber) {{
canvas.setAttribute('data-mnote-evidence-page', 'true');
let evidenceTargetY = null;
if (evidenceBBox) {{
const rect = viewport.convertToViewportRectangle([evidenceBBox.x0, evidenceBBox.y0, evidenceBBox.x1, evidenceBBox.y1]);
const x = Math.min(rect[0], rect[2]);
const y = Math.min(rect[1], rect[3]);
const width = Math.max(1, Math.abs(rect[2] - rect[0]));
const height = Math.max(1, Math.abs(rect[3] - rect[1]));
const normalizedMineruBox = evidenceBBox.x0 >= 0 && evidenceBBox.y0 >= 0 && evidenceBBox.x1 <= 1000 && evidenceBBox.y1 <= 1000;
let x;
let y;
let width;
let height;
if (normalizedMineruBox) {{
x = Math.min(evidenceBBox.x0, evidenceBBox.x1) / 1000 * viewport.width;
y = Math.min(evidenceBBox.y0, evidenceBBox.y1) / 1000 * viewport.height;
width = Math.max(1, Math.abs(evidenceBBox.x1 - evidenceBBox.x0) / 1000 * viewport.width);
height = Math.max(1, Math.abs(evidenceBBox.y1 - evidenceBBox.y0) / 1000 * viewport.height);
}} else {{
const rect = viewport.convertToViewportRectangle([evidenceBBox.x0, evidenceBBox.y0, evidenceBBox.x1, evidenceBBox.y1]);
x = Math.min(rect[0], rect[2]);
y = Math.min(rect[1], rect[3]);
width = Math.max(1, Math.abs(rect[2] - rect[0]));
height = Math.max(1, Math.abs(rect[3] - rect[1]));
}}
context.save();
context.scale(outputScale, outputScale);
context.fillStyle = 'rgba(37, 99, 235, 0.18)';
@@ -2263,8 +2289,17 @@ pub async fn pdf_preview_page(Query(query): Query<PdfPreviewQuery>) -> Response
context.fillRect(x, y, width, height);
context.strokeRect(x, y, width, height);
context.restore();
evidenceTargetY = y + height / 2;
}}
window.setTimeout(() => canvas.scrollIntoView({{ block: 'center', inline: 'nearest' }}), 0);
window.setTimeout(() => {{
if (Number.isFinite(evidenceTargetY)) {{
const rect = canvas.getBoundingClientRect();
const absoluteTargetTop = rect.top + window.scrollY + evidenceTargetY;
window.scrollTo({{ top: Math.max(0, absoluteTargetTop - window.innerHeight / 2), behavior: 'auto' }});
return;
}}
canvas.scrollIntoView({{ block: 'center', inline: 'nearest' }});
}}, 0);
}}
}}
@@ -3869,6 +3904,38 @@ mod tests {
assert!(location.contains("missingPage=local-md%3Adocs%7E2FPlan.md"));
}
#[tokio::test]
async fn document_shell_local_markdown_without_source_kind_does_not_fall_back_to_convex() {
let response = app_with_unreachable_convex_without_fixture()
.oneshot(
Request::builder()
.uri("/documents/local-md:docs~2FPlan.md?resourceTab=primary%3A%3Aresource%3Afile%3Afile%3A%2F%2F%2Ftmp%3Adocs%2FPlan.pdf")
.header("x-mnote-actor-id", "user_test")
.header("x-mnote-actor-type", "user")
.body(Body::empty())
.expect("request"),
)
.await
.expect("response");
assert_eq!(response.status(), StatusCode::SEE_OTHER);
assert_ne!(
response
.headers()
.get("x-error-code")
.and_then(|value| value.to_str().ok()),
Some("convex_retired")
);
let location = response
.headers()
.get(header::LOCATION)
.and_then(|value| value.to_str().ok())
.unwrap_or_default();
assert!(location.starts_with("/?"));
assert!(location.contains("routeGuard=local_folder_source_required"));
assert!(location.contains("missingPage=local-md%3Adocs%7E2FPlan.md"));
}
#[tokio::test]
async fn document_shell_records_local_markdown_page_recent() {
let root = temp_root("mnote-document-shell-record-page-recent");
@@ -4490,7 +4557,7 @@ mod tests {
.headers()
.get("x-upstream-service")
.and_then(|value| value.to_str().ok()),
Some("convex-retired")
Some("legacy-cloud-retired")
);
let body = to_bytes(response.into_body(), usize::MAX)
.await