Improve LightRAG knowledge search locator alignment
This commit is contained in:
@@ -50,6 +50,10 @@ export function createSidebarPageAiRuntime(context) {
|
||||
{ id: 'changed_files', label: '最近修改' }
|
||||
];
|
||||
var pageAiDelegatesInstalled = false;
|
||||
var PAGE_AI_DRAWER_WIDTH_STORAGE_KEY = 'mnote.page_ai.drawer_width';
|
||||
var PAGE_AI_DRAWER_DEFAULT_WIDTH = 440;
|
||||
var PAGE_AI_DRAWER_MIN_WIDTH = 340;
|
||||
var PAGE_AI_DRAWER_MAX_WIDTH = 760;
|
||||
|
||||
function clonePageAiDefaultValue(value) {
|
||||
if (Array.isArray(value)) return value.slice();
|
||||
@@ -57,6 +61,70 @@ export function createSidebarPageAiRuntime(context) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function pageAiClampDrawerWidth(width) {
|
||||
var viewportMax = Math.max(PAGE_AI_DRAWER_MIN_WIDTH, Math.min(PAGE_AI_DRAWER_MAX_WIDTH, window.innerWidth - 24));
|
||||
var numeric = Number(width);
|
||||
if (!Number.isFinite(numeric) || numeric <= 0) numeric = PAGE_AI_DRAWER_DEFAULT_WIDTH;
|
||||
return Math.max(PAGE_AI_DRAWER_MIN_WIDTH, Math.min(viewportMax, Math.round(numeric)));
|
||||
}
|
||||
|
||||
function pageAiStoredDrawerWidth() {
|
||||
try {
|
||||
return pageAiClampDrawerWidth(window.localStorage ? window.localStorage.getItem(PAGE_AI_DRAWER_WIDTH_STORAGE_KEY) : PAGE_AI_DRAWER_DEFAULT_WIDTH);
|
||||
} catch (_error) {
|
||||
return pageAiClampDrawerWidth(PAGE_AI_DRAWER_DEFAULT_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
function pageAiApplyDrawerWidth(drawer, width) {
|
||||
var target = drawer instanceof HTMLElement ? drawer : document.querySelector('[data-testid="wolai-page-ai-drawer"]');
|
||||
if (!(target instanceof HTMLElement)) return;
|
||||
var next = pageAiClampDrawerWidth(width == null ? pageAiStoredDrawerWidth() : width);
|
||||
target.style.setProperty('--mnote-page-ai-width', next + 'px');
|
||||
}
|
||||
|
||||
function handlePageAiPointerDown(event, helpers) {
|
||||
var closestAction = helpers && helpers.closestAction;
|
||||
if (typeof closestAction !== 'function') return false;
|
||||
var handle = closestAction(event.target, '[data-page-ai-resize-handle]');
|
||||
if (!(handle instanceof HTMLElement)) return false;
|
||||
var drawer = handle.closest('[data-testid="wolai-page-ai-drawer"]');
|
||||
var panel = drawer instanceof HTMLElement ? drawer.querySelector('.wolai-page-ai-panel') : null;
|
||||
if (!(drawer instanceof HTMLElement) || !(panel instanceof HTMLElement)) return false;
|
||||
event.preventDefault();
|
||||
var pointerId = event.pointerId;
|
||||
var startX = Number(event.clientX || 0);
|
||||
var startWidth = panel.getBoundingClientRect().width || pageAiStoredDrawerWidth();
|
||||
drawer.setAttribute('data-page-ai-resizing', 'true');
|
||||
document.documentElement.setAttribute('data-mnote-page-ai-resizing', 'true');
|
||||
try {
|
||||
handle.setPointerCapture(pointerId);
|
||||
} catch (_error) {}
|
||||
function move(nextEvent) {
|
||||
var nextWidth = startWidth + (startX - Number(nextEvent.clientX || 0));
|
||||
pageAiApplyDrawerWidth(drawer, nextWidth);
|
||||
}
|
||||
function finish(nextEvent) {
|
||||
move(nextEvent);
|
||||
var value = drawer.style.getPropertyValue('--mnote-page-ai-width').replace('px', '').trim();
|
||||
try {
|
||||
if (window.localStorage) window.localStorage.setItem(PAGE_AI_DRAWER_WIDTH_STORAGE_KEY, String(pageAiClampDrawerWidth(value)));
|
||||
} catch (_error) {}
|
||||
drawer.removeAttribute('data-page-ai-resizing');
|
||||
document.documentElement.removeAttribute('data-mnote-page-ai-resizing');
|
||||
window.removeEventListener('pointermove', move, true);
|
||||
window.removeEventListener('pointerup', finish, true);
|
||||
window.removeEventListener('pointercancel', finish, true);
|
||||
try {
|
||||
handle.releasePointerCapture(pointerId);
|
||||
} catch (_error) {}
|
||||
}
|
||||
window.addEventListener('pointermove', move, true);
|
||||
window.addEventListener('pointerup', finish, true);
|
||||
window.addEventListener('pointercancel', finish, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
function ensurePageAiStateFacade(state) {
|
||||
var defaults = {
|
||||
pageAiOpen: false,
|
||||
@@ -743,9 +811,12 @@ export function createSidebarPageAiRuntime(context) {
|
||||
var prefix = '/documents/';
|
||||
if (!url.pathname.startsWith(prefix)) return '';
|
||||
try {
|
||||
return decodeURIComponent(url.pathname.slice(prefix.length).split('/')[0] || '');
|
||||
var raw = url.pathname.slice(prefix.length).split('/')[0] || '';
|
||||
var decoded = decodeURIComponent(raw);
|
||||
if (decoded.indexOf('%') >= 0 || decoded.indexOf('\uFFFD') >= 0) return '';
|
||||
return decoded;
|
||||
} catch (_error) {
|
||||
return url.pathname.slice(prefix.length).split('/')[0] || '';
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -753,6 +824,14 @@ export function createSidebarPageAiRuntime(context) {
|
||||
var explicitPath = String(url.searchParams.get('resourcePath') || '').trim();
|
||||
if (explicitPath) return explicitPath;
|
||||
var raw = String(url.searchParams.get('resourceTab') || '').trim();
|
||||
if (!raw) {
|
||||
try {
|
||||
var decodedHash = decodeURIComponent(String(url.hash || ''));
|
||||
var marker = '#resource-tab-';
|
||||
var markerIndex = decodedHash.indexOf(marker);
|
||||
if (markerIndex >= 0) raw = decodedHash.slice(markerIndex + marker.length).replace(/^#+/, '').trim();
|
||||
} catch (_error) {}
|
||||
}
|
||||
if (raw.indexOf('::') >= 0) raw = raw.slice(raw.indexOf('::') + 2);
|
||||
if (!raw.startsWith('resource:file:')) return '';
|
||||
var rest = raw.slice('resource:file:'.length);
|
||||
@@ -761,6 +840,40 @@ export function createSidebarPageAiRuntime(context) {
|
||||
return rest.slice(prefix.length).replace(/^\/+/, '');
|
||||
}
|
||||
|
||||
function pageAiSameMnoteOrigin(url) {
|
||||
try {
|
||||
var current = new URL(window.location.origin);
|
||||
if (url.origin === current.origin) return true;
|
||||
if (url.hostname === 'mnote.local') return true;
|
||||
var localNames = ['localhost', '127.0.0.1', '::1', 'mnote.local'];
|
||||
function defaultPort(protocol) {
|
||||
return protocol === 'https:' ? '443' : protocol === 'http:' ? '80' : '';
|
||||
}
|
||||
return localNames.indexOf(url.hostname) >= 0 &&
|
||||
localNames.indexOf(current.hostname) >= 0 &&
|
||||
String(url.port || defaultPort(url.protocol)) === String(current.port || defaultPort(current.protocol));
|
||||
} catch (_error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function pageAiPortableCitationUrl(url) {
|
||||
try {
|
||||
if (url.pathname === '/api/local-folder/files/open') {
|
||||
return Boolean(String(url.searchParams.get('rootUri') || '').trim()) &&
|
||||
Boolean(String(url.searchParams.get('path') || '').trim());
|
||||
}
|
||||
if (!url.pathname.startsWith('/documents/')) return false;
|
||||
var resourceTab = String(url.searchParams.get('resourceTab') || '').trim();
|
||||
return String(url.searchParams.get('sourceKind') || '').trim() === 'local_folder' ||
|
||||
Boolean(String(url.searchParams.get('rootUri') || '').trim()) ||
|
||||
Boolean(String(url.searchParams.get('resourcePath') || '').trim()) ||
|
||||
resourceTab.startsWith('resource:file:');
|
||||
} catch (_error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function pageAiOpenCitationUrl(href) {
|
||||
var url;
|
||||
try {
|
||||
@@ -768,7 +881,34 @@ export function createSidebarPageAiRuntime(context) {
|
||||
} catch (_error) {
|
||||
return false;
|
||||
}
|
||||
if (url.origin !== window.location.origin || !url.pathname.startsWith('/documents/')) return false;
|
||||
var unwrappedHref = pageAiUnwrapSearchCitationUrl(url);
|
||||
if (unwrappedHref) return pageAiOpenCitationUrl(unwrappedHref);
|
||||
if (!pageAiSameMnoteOrigin(url) && !pageAiPortableCitationUrl(url)) return false;
|
||||
if (url.pathname === '/api/local-folder/files/open') {
|
||||
var fileRootUri = String(url.searchParams.get('rootUri') || currentRootUri() || '').trim();
|
||||
var filePath = String(url.searchParams.get('path') || '').trim();
|
||||
if (!filePath) return false;
|
||||
void openLocalResourceInActiveTab({
|
||||
path: filePath,
|
||||
rootUri: fileRootUri,
|
||||
documentId: currentDocumentId() || '',
|
||||
workspaceId: resolveWorkspaceId(document.body) || '',
|
||||
sourceKind: currentSourceKind() || 'local_folder',
|
||||
page: url.searchParams.get('page') || undefined,
|
||||
bbox: pageAiEvidenceBboxFromParam(url.searchParams.get('bbox')),
|
||||
sourceMapPath: String(url.searchParams.get('sourceMapPath') || '').trim(),
|
||||
blockId: String(url.searchParams.get('blockId') || '').trim(),
|
||||
evidenceText: String(url.searchParams.get('evidenceText') || '').trim(),
|
||||
lineRange: pageAiEvidenceRangeFromParam(url.searchParams.get('lineRange')),
|
||||
charRange: pageAiEvidenceRangeFromParam(url.searchParams.get('charRange')),
|
||||
openTarget: 'active-tab',
|
||||
paneRole: 'primary'
|
||||
}).then(function(opened) {
|
||||
if (!opened) window.open(url.toString(), '_blank', 'noopener,noreferrer');
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (!url.pathname.startsWith('/documents/')) return false;
|
||||
var rootUri = String(url.searchParams.get('rootUri') || currentRootUri() || '').trim();
|
||||
var resourcePath = pageAiCitationResourcePath(url, rootUri);
|
||||
var documentId = pageAiDocumentIdFromUrl(url) || currentDocumentId() || '';
|
||||
@@ -784,6 +924,7 @@ export function createSidebarPageAiRuntime(context) {
|
||||
bbox: pageAiEvidenceBboxFromParam(url.searchParams.get('bbox')),
|
||||
sourceMapPath: String(url.searchParams.get('sourceMapPath') || '').trim(),
|
||||
blockId: String(url.searchParams.get('blockId') || '').trim(),
|
||||
evidenceText: String(url.searchParams.get('evidenceText') || '').trim(),
|
||||
lineRange: pageAiEvidenceRangeFromParam(url.searchParams.get('lineRange')),
|
||||
charRange: pageAiEvidenceRangeFromParam(url.searchParams.get('charRange')),
|
||||
openTarget: 'active-tab',
|
||||
@@ -1035,6 +1176,30 @@ export function createSidebarPageAiRuntime(context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function pageAiUnwrapSearchCitationUrl(url) {
|
||||
try {
|
||||
var raw = '';
|
||||
['wd', 'q', 'query'].some(function(key) {
|
||||
raw = String(url.searchParams.get(key) || '').trim();
|
||||
return Boolean(raw);
|
||||
});
|
||||
if (!raw) return '';
|
||||
if (/^documents\//i.test(raw)) raw = '/' + raw;
|
||||
if (!/^\/documents\//i.test(raw) && !/^https?:\/\/[^/]+\/documents\//i.test(raw) && !/^mnote:\/\/open/i.test(raw)) return '';
|
||||
if (/^mnote:\/\/open/i.test(raw)) return raw;
|
||||
var nested = new URL(raw, window.location.origin);
|
||||
if (!nested.pathname.startsWith('/documents/')) return '';
|
||||
['sourceKind', 'rootUri', 'workspaceId', 'resourceTab', 'resourcePath', 'page', 'bbox', 'sourceMapPath', 'blockId', 'evidenceText', 'lineRange', 'charRange'].forEach(function(key) {
|
||||
if (nested.searchParams.get(key)) return;
|
||||
var value = String(url.searchParams.get(key) || '').trim();
|
||||
if (value) nested.searchParams.set(key, value);
|
||||
});
|
||||
return nested.pathname + nested.search;
|
||||
} catch (_error) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function pageAiPreviewValue(value) {
|
||||
if (value == null || value === '') return '';
|
||||
if (typeof value === 'string') return value.length > 120 ? value.slice(0, 120) + '…' : value;
|
||||
@@ -1259,9 +1424,12 @@ export function createSidebarPageAiRuntime(context) {
|
||||
if (argsSummary) existing.argsSummary = argsSummary;
|
||||
if (resultSummary) existing.resultSummary = resultSummary;
|
||||
if (locations.length) existing.locations = locations;
|
||||
existing.rawOutput = toolEvent && toolEvent.output;
|
||||
existing.rawResult = resultSource;
|
||||
if (status === 'completed') {
|
||||
pageAiNotifyToolWriteCompleted(toolName, toolEvent, runId, runTraceId);
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
async function pageAiCancelQueuedRun(queueId) {
|
||||
@@ -1735,6 +1903,7 @@ export function createSidebarPageAiRuntime(context) {
|
||||
renderPageAiProviderButtons();
|
||||
renderPageAiControls();
|
||||
var drawer = ensurePageAiDrawer();
|
||||
pageAiApplyDrawerWidth(drawer);
|
||||
drawer.hidden = false;
|
||||
pageUiState.pageAiOpen = true;
|
||||
updatePageAiTriggerState();
|
||||
@@ -1840,13 +2009,113 @@ export function createSidebarPageAiRuntime(context) {
|
||||
return message.content;
|
||||
}
|
||||
|
||||
function pageAiFinishStreamingAssistantMessage(runId, finalText, promptText) {
|
||||
function pageAiAppendCitationSection(content, citations) {
|
||||
var text = String(content || '');
|
||||
var unique = [];
|
||||
pageAiNormalizeArray(citations).forEach(function(value) {
|
||||
var citation = String(value || '').trim();
|
||||
if (!citation || unique.indexOf(citation) >= 0) return;
|
||||
unique.push(citation);
|
||||
});
|
||||
var missing = unique.filter(function(citation) {
|
||||
return text.indexOf(citation) < 0;
|
||||
});
|
||||
if (!missing.length) return text;
|
||||
return text.replace(/\s+$/g, '') + '\n\n**引用**\n' + missing.map(function(citation) {
|
||||
return '- ' + citation;
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
function pageAiPromptNeedsKnowledgeRagCitations(prompt) {
|
||||
var text = searchText(prompt);
|
||||
if (!text) return false;
|
||||
var asksCitation = ['链接', '引用', '来源', '出处', '证据', '定位', 'link', 'citation', 'source'].some(function(word) {
|
||||
return text.indexOf(word) >= 0;
|
||||
});
|
||||
if (!asksCitation) return false;
|
||||
return ['lightrag', '资料库', '知识库', 'rag', '文献', '论文', '保护基'].some(function(word) {
|
||||
return text.indexOf(word) >= 0;
|
||||
});
|
||||
}
|
||||
|
||||
function pageAiCleanDegradedCitationNotes(content) {
|
||||
return String(content || '')
|
||||
.split('\n')
|
||||
.filter(function(line) {
|
||||
var text = String(line || '');
|
||||
return text.indexOf('来源定位降级') < 0 && text.toLowerCase().indexOf('locator degraded') < 0;
|
||||
})
|
||||
.join('\n')
|
||||
.replace(/\n{3,}/g, '\n\n')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function pageAiCollectKnowledgeRagApiCitations(payload) {
|
||||
var references = pageAiNormalizeArray(payload && payload.references);
|
||||
var citations = references.map(function(reference) {
|
||||
return String(reference && reference.citationMarkdown || '').trim();
|
||||
}).filter(Boolean);
|
||||
var hasPreciseCitation = references.some(function(reference) {
|
||||
return String(reference && reference.citationMarkdown || '').trim() && reference && reference.locatorDegraded !== true;
|
||||
});
|
||||
var seen = {};
|
||||
return citations.filter(function(citation) {
|
||||
if (seen[citation]) return false;
|
||||
if (hasPreciseCitation && citation.indexOf('来源定位降级') >= 0) return false;
|
||||
seen[citation] = true;
|
||||
return true;
|
||||
}).slice(0, 5);
|
||||
}
|
||||
|
||||
async function pageAiAppendKnowledgeRagFallbackCitations(runId, promptText) {
|
||||
if (!pageAiPromptNeedsKnowledgeRagCitations(promptText)) return;
|
||||
var rootUri = currentRootUri();
|
||||
if (!rootUri) return;
|
||||
try {
|
||||
var response = await fetch('/api/knowledge-rag/query', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json', 'accept': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
workspaceId: resolveWorkspaceId(document.body) || undefined,
|
||||
rootUri: rootUri,
|
||||
query: String(promptText || '').trim(),
|
||||
mode: 'mix',
|
||||
topK: 8,
|
||||
chunkTopK: 8,
|
||||
includeChunkContent: true
|
||||
})
|
||||
});
|
||||
var payload = await response.json().catch(function() { return null; });
|
||||
if (!response.ok) return;
|
||||
var citations = pageAiCollectKnowledgeRagApiCitations(payload);
|
||||
if (!citations.length) return;
|
||||
var message = pageUiState.pageAiMessages.find(function(item) {
|
||||
return item.role === 'assistant' && item.runId === runId;
|
||||
}) || pageUiState.pageAiMessages.filter(function(item) { return item.role === 'assistant'; }).slice(-1)[0];
|
||||
if (!message) return;
|
||||
var hasPrecise = citations.some(function(citation) { return citation.indexOf('来源定位降级') < 0; });
|
||||
var baseContent = hasPrecise ? pageAiCleanDegradedCitationNotes(message.content) : String(message.content || '');
|
||||
message.content = pageAiAppendCitationSection(baseContent, citations);
|
||||
pageAiSyncCurrentSessionMessages();
|
||||
pageAiPersistSessions();
|
||||
renderPageAiConversation();
|
||||
} catch (error) {
|
||||
console.warn('MNote Page AI 自动追加 LightRAG 引用失败', error);
|
||||
}
|
||||
}
|
||||
|
||||
function pageAiFinishStreamingAssistantMessage(runId, finalText, promptText, citations) {
|
||||
var id = String(runId || pageUiState.pageAiCurrentRunId || '');
|
||||
var message = pageUiState.pageAiMessages.find(function(item) {
|
||||
return item.role === 'assistant' && item.streaming === true && item.runId === id;
|
||||
});
|
||||
var text = String(finalText || (message && message.content) || '');
|
||||
var content = humanizePageAiResponse(text, promptText);
|
||||
var hasPreciseCitation = pageAiNormalizeArray(citations).some(function(citation) {
|
||||
return String(citation || '').indexOf('来源定位降级') < 0;
|
||||
});
|
||||
var contentBase = humanizePageAiResponse(text, promptText);
|
||||
if (hasPreciseCitation) contentBase = pageAiCleanDegradedCitationNotes(contentBase);
|
||||
var content = pageAiAppendCitationSection(contentBase, citations);
|
||||
if (message) {
|
||||
message.content = content;
|
||||
message.streaming = false;
|
||||
@@ -1859,6 +2128,123 @@ export function createSidebarPageAiRuntime(context) {
|
||||
}
|
||||
pageAiSyncCurrentSessionMessages();
|
||||
pageAiPersistSessions();
|
||||
void pageAiAppendKnowledgeRagFallbackCitations(id, promptText);
|
||||
}
|
||||
|
||||
function pageAiToolOutputText(value) {
|
||||
var parts = [];
|
||||
function visit(node) {
|
||||
if (node == null) return;
|
||||
if (typeof node === 'string') {
|
||||
parts.push(node);
|
||||
return;
|
||||
}
|
||||
if (typeof node === 'number' || typeof node === 'boolean') return;
|
||||
if (Array.isArray(node)) {
|
||||
node.forEach(visit);
|
||||
return;
|
||||
}
|
||||
if (typeof node !== 'object') return;
|
||||
if (typeof node.text === 'string') parts.push(node.text);
|
||||
if (typeof node.content === 'string') parts.push(node.content);
|
||||
if (node.content && typeof node.content === 'object') visit(node.content);
|
||||
if (node.output && typeof node.output === 'object') visit(node.output);
|
||||
if (node.result && typeof node.result === 'object') visit(node.result);
|
||||
}
|
||||
visit(value);
|
||||
return parts.join('\n');
|
||||
}
|
||||
|
||||
function pageAiParseJsonMaybe(value) {
|
||||
if (value && typeof value === 'object') return value;
|
||||
var text = String(value || '').trim();
|
||||
if (!text || (text[0] !== '{' && text[0] !== '[')) return null;
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (_error) {
|
||||
var firstLine = text.split('\n')[0].trim();
|
||||
if (firstLine && firstLine !== text && (firstLine[0] === '{' || firstLine[0] === '[')) {
|
||||
try {
|
||||
return JSON.parse(firstLine);
|
||||
} catch (_lineError) {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function pageAiCollectCitationMarkdowns(value) {
|
||||
var citations = [];
|
||||
var seen = {};
|
||||
function add(value) {
|
||||
var citation = String(value || '').trim();
|
||||
if (!citation || seen[citation]) return;
|
||||
seen[citation] = true;
|
||||
citations.push(citation);
|
||||
}
|
||||
function visit(node) {
|
||||
if (node == null) return;
|
||||
if (typeof node === 'string') {
|
||||
var parsed = pageAiParseJsonMaybe(node);
|
||||
if (parsed) visit(parsed);
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(node)) {
|
||||
node.forEach(visit);
|
||||
return;
|
||||
}
|
||||
if (typeof node !== 'object') return;
|
||||
if (typeof node.citationMarkdown === 'string') add(node.citationMarkdown);
|
||||
if (Array.isArray(node.citationMarkdowns)) {
|
||||
node.citationMarkdowns.forEach(function(value) {
|
||||
if (typeof value === 'string') add(value);
|
||||
else visit(value);
|
||||
});
|
||||
}
|
||||
Object.keys(node).forEach(function(key) {
|
||||
visit(node[key]);
|
||||
});
|
||||
}
|
||||
visit(value);
|
||||
return citations;
|
||||
}
|
||||
|
||||
function pageAiCollectKnowledgeRagCitations(toolItem, toolEvent) {
|
||||
var toolName = String((toolItem && toolItem.toolName) || (toolEvent && (toolEvent.name || toolEvent.tool || toolEvent.toolName)) || '');
|
||||
var sources = [
|
||||
toolEvent,
|
||||
toolItem,
|
||||
toolEvent && toolEvent.output,
|
||||
toolEvent && toolEvent.result,
|
||||
toolEvent && toolEvent.summary,
|
||||
toolItem && toolItem.rawOutput,
|
||||
toolItem && toolItem.rawResult,
|
||||
toolItem && toolItem.resultSummary
|
||||
];
|
||||
var citations = [];
|
||||
var outputText = '';
|
||||
sources.forEach(function(source) {
|
||||
citations = citations.concat(pageAiCollectCitationMarkdowns(source));
|
||||
var sourceText = pageAiToolOutputText(source);
|
||||
if (sourceText) outputText += '\n' + sourceText;
|
||||
var parsed = pageAiParseJsonMaybe(sourceText);
|
||||
if (parsed) citations = citations.concat(pageAiCollectCitationMarkdowns(parsed));
|
||||
});
|
||||
var looksLikeKnowledgeRag = toolName.indexOf('knowledge_rag') >= 0 ||
|
||||
toolName.indexOf('knowledge.rag') >= 0 ||
|
||||
outputText.indexOf('mnote.knowledge_rag') >= 0 ||
|
||||
outputText.indexOf('uiCitations') >= 0;
|
||||
if (!looksLikeKnowledgeRag && citations.length === 0) return [];
|
||||
var hasPreciseCitation = citations.some(function(value) {
|
||||
return String(value || '').indexOf('来源定位降级') < 0;
|
||||
});
|
||||
var seen = {};
|
||||
return citations.filter(function(value) {
|
||||
var citation = String(value || '').trim();
|
||||
if (!citation || seen[citation]) return false;
|
||||
if (hasPreciseCitation && citation.indexOf('来源定位降级') >= 0) return false;
|
||||
seen[citation] = true;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function pageAiLooksLikeBlockEdit(prompt) {
|
||||
@@ -2078,6 +2464,7 @@ export function createSidebarPageAiRuntime(context) {
|
||||
throw new Error(pageAiErrorMessage(eventError, 'hermes_events_failed_' + eventResponse.status));
|
||||
}
|
||||
var assistantText = '';
|
||||
var autoCitations = [];
|
||||
await streamPageAiResponse(eventResponse, function(eventName, payloadText) {
|
||||
if (eventName === 'message.delta') {
|
||||
if (pageUiState.pageAiStoppedRunIds[runId]) return;
|
||||
@@ -2222,7 +2609,15 @@ export function createSidebarPageAiRuntime(context) {
|
||||
} catch (_) {}
|
||||
}
|
||||
if (eventName === 'tool.started' || eventName === 'tool.completed' || eventName === 'tool.failed') {
|
||||
pageAiApplyToolEvent(eventName, payloadText, runId, runTraceId);
|
||||
var toolEventPayload = null;
|
||||
try {
|
||||
toolEventPayload = JSON.parse(payloadText || 'null');
|
||||
} catch (_) {}
|
||||
var toolItem = pageAiApplyToolEvent(eventName, payloadText, runId, runTraceId);
|
||||
if (eventName === 'tool.completed') {
|
||||
var completedCitations = pageAiCollectKnowledgeRagCitations(toolItem, toolEventPayload);
|
||||
if (completedCitations.length) autoCitations = completedCitations;
|
||||
}
|
||||
pageAiSyncCurrentSessionMessages();
|
||||
pageAiPersistSessions();
|
||||
renderPageAiConversation();
|
||||
@@ -2231,7 +2626,7 @@ export function createSidebarPageAiRuntime(context) {
|
||||
}
|
||||
});
|
||||
if (!pageUiState.pageAiStoppedRunIds[runId]) {
|
||||
pageAiFinishStreamingAssistantMessage(runId, assistantText, prompt);
|
||||
pageAiFinishStreamingAssistantMessage(runId, assistantText, prompt, autoCitations);
|
||||
}
|
||||
currentSession = pageAiCurrentSession();
|
||||
if (currentSession) {
|
||||
@@ -2596,6 +2991,9 @@ export function createSidebarPageAiRuntime(context) {
|
||||
document.addEventListener('click', function(event) {
|
||||
handlePageAiClick(event, helpers);
|
||||
});
|
||||
document.addEventListener('pointerdown', function(event) {
|
||||
handlePageAiPointerDown(event, helpers);
|
||||
});
|
||||
document.addEventListener('keydown', function(event) {
|
||||
handlePageAiKeyDown(event, helpers);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user