feat(rag): harden post-LightRAG runtime

Retire legacy OCR/media/evidence fallbacks, add local-folder event bus and Page Aggregate guards, and archive completed design checklists.

Validation: cargo test -p mnote-web -- --test-threads=1; cargo test --workspace -- --test-threads=1; git diff --check; codegraph sync .; codegraph_status.
This commit is contained in:
lix-2026
2026-06-07 10:35:21 +08:00
parent 22a92edcda
commit 9551d4c1dc
59 changed files with 4053 additions and 5249 deletions
@@ -209,7 +209,6 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
const isPageSettingsOpen = (...args) => sidebarPageSettings.isPageSettingsOpen(...args);
const openPageHistoryDrawer = (...args) => sidebarPageSettings.openPageHistoryDrawer(...args);
const openPageIndexSettingsPopover = (...args) => sidebarPageSettings.openPageIndexSettingsPopover(...args);
const openLocalOcrSettingsPopover = (...args) => sidebarPageSettings.openLocalOcrSettingsPopover(...args);
const openKnowledgeRagSettingsPopover = (...args) => sidebarPageSettings.openKnowledgeRagSettingsPopover(...args);
const openPageShareDialog = (...args) => sidebarPageSettings.openPageShareDialog(...args);
const pageOptionIsSupported = (...args) => sidebarPageSettings.pageOptionIsSupported(...args);
@@ -223,7 +222,6 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
const pruneKnowledgeRagRegistry = (...args) => sidebarPageSettings.pruneKnowledgeRagRegistry(...args);
const setKnowledgeRagSourceFilter = (...args) => sidebarPageSettings.setKnowledgeRagSourceFilter(...args);
const useKnowledgeRagFileTreeSelection = (...args) => sidebarPageSettings.useKnowledgeRagFileTreeSelection(...args);
const persistLocalOcrAutoPreference = (...args) => sidebarPageSettings.persistLocalOcrAutoPreference(...args);
const persistLocalIndexSettings = (...args) => sidebarPageSettings.persistLocalIndexSettings(...args);
const persistPageOptionsPatch = (...args) => sidebarPageSettings.persistPageOptionsPatch(...args);
const persistPageWidthPreference = (...args) => sidebarPageSettings.persistPageWidthPreference(...args);
@@ -477,7 +475,7 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
return title && title.textContent ? title.textContent.trim() : (fallback || '文件夹');
}
function isLocalOcrMarkdownPath(relativePath) {
function isRetiredOcrSidecarMarkdownPath(relativePath) {
var normalized = String(relativePath || '').trim().replace(/\\/g, '/').replace(/^\/+/, '');
return /(^|\/)[^/]+\.ocr\/[^/]+\.ocr\.md$/i.test(normalized);
}
@@ -1298,24 +1296,8 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
applyEditorAttachmentMeta(link, attachmentMetaCache[assetId]);
return;
}
attachmentMetaPending[assetId] = fetch('/api/media/sign?assetId=' + encodeURIComponent(assetId), {
method: 'GET',
credentials: 'include',
cache: 'no-store'
}).then(function(response) {
return response.json().catch(function() { return null; }).then(function(payload) {
if (!response.ok || !payload) return null;
var asset = payload.asset && typeof payload.asset === 'object' ? payload.asset : {};
var meta = {
assetId: assetId,
fileSize: uploadedFileSize(asset)
};
attachmentMetaCache[assetId] = meta;
return meta;
});
}).catch(function() {
return null;
}).finally(function() {
document.documentElement.setAttribute('data-mnote-media-sign-retired', 'true');
attachmentMetaPending[assetId] = Promise.resolve(null).finally(function() {
delete attachmentMetaPending[assetId];
});
try {
@@ -1899,20 +1881,8 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
throw new Error('上传失败');
}
} else {
var form = new FormData();
form.append('file', file);
form.append('workspaceId', plan.workspaceId);
form.append('documentId', plan.targetDocumentId);
if (plan.targetMindmapId) form.append('mindmapId', plan.targetMindmapId);
var response = await fetchWithTimeout('/api/media/upload', {
method: 'POST',
credentials: 'include',
body: form
}, 15000, '上传');
payload = await response.json().catch(function() { return null; });
if (!response.ok || !payload || !payload.asset) {
throw new Error(payload && payload.error ? payload.error : '上传失败');
}
document.documentElement.setAttribute('data-mnote-media-upload-retired', 'true');
throw new Error('旧 Convex Files 上传链已退役;local-first 附件请使用本地文件夹上传目标。');
}
appendUploadedAssetRow(payload.asset, plan.targetDocumentId);
if (options && options.insertIntoEditor) {
@@ -2695,20 +2665,6 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
return;
}
var ocrTaskTrigger = closestAction(e.target, '[data-mnote-action="toggle-ocr-tasks"]');
if (ocrTaskTrigger) {
e.preventDefault();
openKnowledgeRagSettingsPopover();
return;
}
var ocrSettingsTrigger = closestAction(e.target, '[data-mnote-action="open-ocr-settings"]');
if (ocrSettingsTrigger) {
e.preventDefault();
openKnowledgeRagSettingsPopover();
return;
}
var settingsClose = closestAction(e.target, '[data-settings-action="close"]');
if (settingsClose) {
e.preventDefault();
@@ -2750,17 +2706,6 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
}
}
var localOcrSettingsAction = closestAction(e.target, '[data-local-ocr-settings-action]');
if (localOcrSettingsAction) {
e.preventDefault();
var localOcrSettingsActionName = localOcrSettingsAction.getAttribute('data-local-ocr-settings-action') || '';
closeAllSettingsPopovers();
window.dispatchEvent(new CustomEvent('mnote:local-ocr-settings-action', {
detail: { action: localOcrSettingsActionName }
}));
return;
}
var knowledgeRagAction = closestAction(e.target, '[data-knowledge-rag-action]');
if (knowledgeRagAction) {
e.preventDefault();
@@ -3042,14 +2987,14 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
if (e.shiftKey || e.ctrlKey || e.metaKey) {
return;
}
if ((rowKind === 'document' || rowKind === 'index' || rowKind === 'markdown') && isLocalOcrMarkdownPath(localRelativePath)) {
document.documentElement.setAttribute('data-mnote-local-ocr-filetree-open', 'resource-tab');
var ocrResourceInput = {
if ((rowKind === 'document' || rowKind === 'index' || rowKind === 'markdown') && isRetiredOcrSidecarMarkdownPath(localRelativePath)) {
document.documentElement.setAttribute('data-mnote-retired-ocr-sidecar-filetree-open', 'resource-tab');
var retiredOcrSidecarResourceInput = {
path: localRelativePath,
title: fileTreeRowTitleForShortcut(fileRow, localRelativePath),
kind: 'markdown',
objectIdentity: 'local-ocr:' + localRelativePath,
assetId: 'local-ocr:' + localRelativePath,
objectIdentity: 'retired-ocr-sidecar:' + localRelativePath,
assetId: 'retired-ocr-sidecar:' + localRelativePath,
documentId: documentId || ownerDocumentId || null,
workspaceId: resolveWorkspaceId(fileRow),
sourceKind: 'local_folder',
@@ -3059,9 +3004,9 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
paneRole: 'primary'
};
if (typeof window.__mnoteDocumentPaneRuntime?.openResourceInActiveTab === 'function') {
void window.__mnoteDocumentPaneRuntime.openResourceInActiveTab(ocrResourceInput);
void window.__mnoteDocumentPaneRuntime.openResourceInActiveTab(retiredOcrSidecarResourceInput);
} else {
void openLocalResourceInActiveTab(ocrResourceInput);
void openLocalResourceInActiveTab(retiredOcrSidecarResourceInput);
}
return;
}
@@ -3219,11 +3164,6 @@ import { createSidebarPageSettingsRuntime } from './sidebar-page-settings-runtim
renderPageSettingsPopover();
return;
}
var localOcrCheckbox = closestAction(event.target, '[data-local-ocr-option-checkbox="autoEnabled"]');
if (localOcrCheckbox instanceof HTMLInputElement) {
void persistLocalOcrAutoPreference(localOcrCheckbox.checked);
return;
}
var checkbox = closestAction(event.target, '[data-page-option-checkbox]');
if (checkbox instanceof HTMLInputElement) {
var key = checkbox.getAttribute('data-page-option-checkbox') || '';