feat(rag): replace LiteParse flows with LightRAG provider

This commit is contained in:
lix-2026
2026-06-07 01:10:31 +08:00
parent f46c2fb5d0
commit 1f25364374
40 changed files with 7232 additions and 2350 deletions
+39 -47
View File
@@ -188,8 +188,7 @@ pub fn PageLayout(
<span class="wolai-public-pill" data-testid="wolai-public-state" hidden></span>
<button type="button" class="wolai-icon-button" title="星标置顶" aria-label="星标置顶" data-mnote-action="toggle-sidebar-shortcut" data-mnote-shortcut-kind="page"><span class="material-symbols-outlined" data-icon="star" aria-hidden="true"></span></button>
<button type="button" class="wolai-icon-button" title="演示" aria-label="演示"><span class="material-symbols-outlined" data-icon="slideshow" aria-hidden="true"></span></button>
<button type="button" class="wolai-icon-button mnote-local-ocr-task-toggle" title="OCR 设置" aria-label="OCR 设置" data-testid="mnote-local-ocr-task-toggle" data-mnote-action="open-ocr-settings"><span class="material-symbols-outlined" data-icon="document_scanner" aria-hidden="true"></span><span class="mnote-local-ocr-task-badge" data-mnote-local-ocr-task-count hidden>0</span></button>
<button type="button" class="wolai-icon-button" title="索引设置" aria-label="索引设置" data-testid="mnote-local-index-settings-toggle" data-mnote-action="open-index-settings"><span class="material-symbols-outlined" data-icon="manage_search" aria-hidden="true"></span></button>
<button type="button" class="wolai-icon-button" title="资料库问答" aria-label="资料库问答" data-testid="mnote-knowledge-rag-settings-toggle" data-mnote-action="open-knowledge-rag-settings"><span class="material-symbols-outlined" data-icon="travel_explore" aria-hidden="true"></span></button>
<button type="button" class="wolai-icon-button" title="评论" aria-label="评论"><span class="material-symbols-outlined" data-icon="comment" aria-hidden="true"></span></button>
<button type="button" class="wolai-icon-button" title="分享" aria-label="分享"><span class="material-symbols-outlined" data-icon="share" aria-hidden="true"></span></button>
<button type="button" class="wolai-icon-button" title="成员" aria-label="成员"><span class="material-symbols-outlined" data-icon="person_add" aria-hidden="true"></span></button>
@@ -201,7 +200,6 @@ pub fn PageLayout(
{children()}
</article>
<div class="wolai-floating-actions" aria-label="浮动操作">
<button type="button" data-testid="mnote-floating-task-toggle" class="wolai-floating-button wolai-floating-button--tasks mnote-local-ocr-task-toggle" title="后台任务" aria-label="后台任务" data-mnote-action="toggle-ocr-tasks"><span class="material-symbols-outlined" data-icon="pending_actions" aria-hidden="true"></span><span class="mnote-local-ocr-task-badge" data-mnote-local-ocr-task-count hidden>0</span></button>
<button type="button" data-testid="wolai-floating-ai" class="wolai-floating-button wolai-floating-button--ai" aria-label="AI 助手" title="点击 进入空间智能问答" data-mnote-action="open-page-ai"><span class="material-symbols-outlined material-symbols-filled" data-icon="auto_awesome" aria-hidden="true"></span></button>
</div>
</div>
@@ -489,61 +487,55 @@ mod tests {
}
#[test]
fn page_layout_exposes_standalone_index_and_ocr_settings() {
fn page_layout_exposes_lightrag_knowledge_rag_settings_only() {
let html = crate::ssr::render_view(leptos::view! {
<super::PageLayout current_nav="documents" topbar_title={"个人".to_string()}>
<main>"正文"</main>
</super::PageLayout>
});
assert!(html.contains(r#"data-testid="mnote-local-index-settings-toggle""#));
assert!(html.contains(r#"data-mnote-action="open-index-settings""#));
assert!(html.contains(r#"data-icon="manage_search""#));
assert!(html.contains(r#"data-testid="mnote-local-ocr-task-toggle""#));
assert!(html.contains(r#"data-mnote-action="open-ocr-settings""#));
assert!(html.contains(r#"data-testid="mnote-floating-task-toggle""#));
assert!(html.contains(r#"data-mnote-action="toggle-ocr-tasks""#));
assert!(html.contains(r#"data-icon="pending_actions""#));
assert!(!html.contains(r#"data-testid="mnote-local-index-settings-toggle""#));
assert!(!html.contains(r#"data-mnote-action="open-index-settings""#));
assert!(html.contains(r#"data-testid="mnote-knowledge-rag-settings-toggle""#));
assert!(html.contains(r#"data-mnote-action="open-knowledge-rag-settings""#));
assert!(html.contains(r#"data-icon="travel_explore""#));
assert!(crate::ssr::styles::MNOTE_CSS.contains(r#"data-icon="travel_explore""#));
assert!(!html.contains(r#"data-testid="mnote-local-ocr-task-toggle""#));
assert!(!html.contains(r#"data-mnote-action="open-ocr-settings""#));
assert!(!html.contains(r#"data-testid="mnote-floating-task-toggle""#));
assert!(!html.contains(r#"data-mnote-action="toggle-ocr-tasks""#));
}
#[test]
fn sidebar_settings_runtime_keeps_index_and_ocr_out_of_page_settings() {
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("mnote-local-index-settings-popover"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("mnote-local-ocr-settings-popover"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("data-local-index-range-input"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("data-index-status=\"' + kind"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("if (kind === 'indexed')"));
fn sidebar_settings_runtime_routes_index_and_ocr_to_lightrag_settings() {
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("mnote-knowledge-rag-settings-popover"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("/api/knowledge-rag/status?"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("/api/knowledge-rag/ingest"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("/api/knowledge-rag/prune-registry"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("use-filetree-selection"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("data-knowledge-rag-action=\"prune\""));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("mnote-knowledge-rag-source-filters"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("filter-sources"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("LightRAG 未映射"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("scheduleKnowledgeRagStatusBridge"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("knowledgeRagStatusHasInFlight"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("delete_submitted"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("delete_completed"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("publicKnowledgeRagDashboardUrl"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("label.hidden = status === 'idle'"));
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("data-knowledge-rag-input-status-label"));
assert!(
SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains(
"renderLocalIndexRangeRows(popover, currentLocalIndexRangeValues(popover).concat([''])"
),
"新增索引范围必须保留空白输入行,不能先过滤成默认 ."
SIDEBAR_TREE_RUNTIME_JS.contains("[data-mnote-action=\"open-knowledge-rag-settings\"]")
);
assert!(
SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("data-local-index-persisted=\"true\""),
"已保存索引范围必须锁定为不可直接修改"
);
assert!(
SIDEBAR_PAGE_SETTINGS_RUNTIME_JS
.contains("return currentLocalIndexRangeValues(popover).map"),
"删除最后一个索引范围后保存应提交空数组,不能强制回填 ."
);
assert!(
SIDEBAR_PAGE_SETTINGS_RUNTIME_JS
.contains("var savedIncludePaths = Array.isArray(settings.includePaths) ? settings.includePaths : [];"),
"索引面板默认不应把空配置回填成工作区根目录"
);
assert!(
SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains(
"var includePaths = savedIncludePaths.length ? savedIncludePaths : indexedPaths;"
),
"无用户配置但已有索引缓存时仍应展示旧索引范围,便于删除"
);
assert!(SIDEBAR_PAGE_SETTINGS_RUNTIME_JS
.contains("data-local-ocr-settings-action=\"run-active\""));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote:local-ocr-settings-action"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("[data-mnote-action=\"toggle-ocr-tasks\"]"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("detail: { action: 'tasks' }"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("[data-knowledge-rag-action]"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("useKnowledgeRagFileTreeSelection"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("reindex-source"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("deleteKnowledgeRagSource"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("pruneKnowledgeRagRegistry"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("setKnowledgeRagSourceFilter"));
assert!(SIDEBAR_TREE_RUNTIME_JS.contains("mnote:knowledge-rag-source-updated"));
assert!(!SIDEBAR_TREE_RUNTIME_JS.contains("openPageIndexSettingsPopover();"));
assert!(!SIDEBAR_TREE_RUNTIME_JS.contains("openLocalOcrSettingsPopover();"));
assert!(!SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("data-page-settings-tab=\"index\""));
assert!(!SIDEBAR_PAGE_SETTINGS_RUNTIME_JS.contains("本地索引仅在本地工作区页面可用"));
assert!(
+168
View File
@@ -184,6 +184,7 @@ a:hover {
.material-symbols-outlined[data-icon="mode_comment"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 5h14v10H9l-4 4V5Z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="person_add"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='9' cy='8' r='3.2' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='M3.5 20a5.5 5.5 0 0 1 11 0M18 8v6M15 11h6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="slideshow"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 5h16v12H4z' fill='none' stroke='black' stroke-width='2' stroke-linejoin='round'/%3E%3Cpath d='m10 9 5 2-5 2zM9 21h6' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="travel_explore"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='11' cy='11' r='7' fill='none' stroke='black' stroke-width='2'/%3E%3Cpath d='M4 11h14M11 4a10 10 0 0 1 0 14M11 4a10 10 0 0 0 0 14M16.5 16.5 21 21' fill='none' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3Cpath d='M7.5 8.5h2.5l1 1.5 2.5-.5 1 2-2 1 .5 2.5h-3l-1.5-2-2 .5' fill='none' stroke='black' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="document_scanner"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 3H5a2 2 0 0 0-2 2v2M17 3h2a2 2 0 0 1 2 2v2M7 21H5a2 2 0 0 1-2-2v-2M17 21h2a2 2 0 0 0 2-2v-2M7 8h10M7 12h10M7 16h7' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="article"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 4h12v16H6zM9 8h6M9 12h6M9 16h4' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.material-symbols-outlined[data-icon="sync"] { --mnote-icon-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20 6v5h-5M4 18v-5h5M7.5 9A6 6 0 0 1 18 6M16.5 15A6 6 0 0 1 6 18' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
@@ -1747,6 +1748,7 @@ body {
}
.sidebar-tree .tree-row[data-index-status="indexed"] .tree-kind-badge::after,
.sidebar-tree .tree-row[data-index-status="indexing"] .tree-kind-badge::after,
.sidebar-tree .tree-row[data-index-status="failed"] .tree-kind-badge::after {
position: absolute;
left: -1px;
@@ -1767,6 +1769,11 @@ body {
background: #38B86E;
}
.sidebar-tree .tree-row[data-index-status="indexing"] .tree-kind-badge::after {
content: "…";
background: #D99A2B;
}
.sidebar-tree .tree-row[data-index-status="failed"] .tree-kind-badge::after {
content: "x";
background: #D94841;
@@ -3867,6 +3874,167 @@ body {
width: min(386px, calc(100vw - 24px));
}
.mnote-knowledge-rag-settings-panel {
width: min(440px, calc(100vw - 24px));
max-height: calc(100vh - 72px);
overflow-y: auto;
}
.mnote-knowledge-rag-meta {
display: flex;
flex-direction: column;
gap: 5px;
}
.mnote-knowledge-rag-meta div {
display: grid;
grid-template-columns: 72px minmax(0, 1fr);
gap: 8px;
align-items: baseline;
color: #8B8782;
font-size: 12px;
line-height: 18px;
}
.mnote-knowledge-rag-meta code {
min-width: 0;
overflow: hidden;
color: #1B1C1C;
font: 11px/16px "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
text-overflow: ellipsis;
white-space: nowrap;
}
.mnote-knowledge-rag-source-list,
.mnote-knowledge-rag-source-inputs {
display: flex;
flex-direction: column;
gap: 6px;
}
.mnote-knowledge-rag-source-tools {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.mnote-knowledge-rag-control-group .wolai-page-settings-index-actions {
justify-content: flex-start;
}
.mnote-knowledge-rag-source-filters {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.mnote-knowledge-rag-source-filters button {
border: 1px solid #E3E1DE;
border-radius: 6px;
background: #FFFFFF;
color: #5F5A54;
font-size: 11px;
line-height: 18px;
padding: 2px 7px;
white-space: nowrap;
}
.mnote-knowledge-rag-source-filters button[data-active="true"] {
border-color: #B8DDBB;
background: #EAF7EA;
color: #166534;
}
.mnote-knowledge-rag-source-filters button span {
color: #8B8782;
font-variant-numeric: tabular-nums;
}
.mnote-knowledge-rag-source-row,
.mnote-knowledge-rag-source-input-row {
display: grid;
grid-template-columns: 12px minmax(0, 1fr) auto;
align-items: center;
gap: 8px;
}
.mnote-knowledge-rag-source-input-row {
grid-template-columns: minmax(0, 1fr) 56px 28px;
}
.mnote-knowledge-rag-input-status {
color: #8B8782;
font-size: 11px;
line-height: 16px;
text-align: right;
white-space: nowrap;
}
.mnote-knowledge-rag-input-status[data-status="done"] {
color: #15803D;
}
.mnote-knowledge-rag-input-status[data-status="running"],
.mnote-knowledge-rag-input-status[data-status="retry"] {
color: #B45309;
}
.mnote-knowledge-rag-input-status[data-status="failed"] {
color: #B91C1C;
}
.mnote-knowledge-rag-source-main {
display: flex;
min-width: 0;
flex-direction: column;
gap: 2px;
}
.mnote-knowledge-rag-source-main strong {
overflow: hidden;
color: #1B1C1C;
font-size: 12px;
font-weight: 600;
line-height: 17px;
text-overflow: ellipsis;
white-space: nowrap;
}
.mnote-knowledge-rag-source-main span {
overflow: hidden;
color: #8B8782;
font: 11px/16px "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
text-overflow: ellipsis;
white-space: nowrap;
}
.mnote-knowledge-rag-source-actions {
display: flex;
gap: 6px;
justify-content: flex-end;
}
.mnote-knowledge-rag-source-actions button {
min-width: 0;
border: 1px solid #E3E1DE;
border-radius: 6px;
background: #FFFFFF;
color: #5F5A54;
font-size: 11px;
line-height: 18px;
padding: 2px 6px;
white-space: nowrap;
}
.mnote-knowledge-rag-source-actions button:hover:not(:disabled) {
background: #F4F3F3;
color: #1B1C1C;
}
.mnote-knowledge-rag-source-actions button:disabled {
opacity: 0.45;
}
.wolai-page-settings-tabs {
display: flex;
gap: 6px;