chore: harden lightrag knowledge rag runtime
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user