feat: use indexed assistant topic suggestions

This commit is contained in:
Daniel 2026-05-07 03:43:28 +02:00
parent 9c7f1ba499
commit 08d43298f3

View file

@ -496,6 +496,14 @@ async function multimodalSearch(query, opts) {
});
}
async function indexedTopicSuggestions(limit) {
return callMcpTool('nc_indexed_topic_suggestions', {
limit: limit || 9,
sample_size: 900,
doc_type: 'file'
});
}
async function callMcpTool(name, args) {
var session = await mcpRequest({
jsonrpc: '2.0',
@ -1056,6 +1064,15 @@ async function getAvailableExamples() {
var now = Date.now();
if (_exampleCache.expiresAt > now && _exampleCache.examples.length) return _exampleCache.examples;
var indexedExamples = await getIndexedTopicExamples().catch(function(e) {
console.warn('[clinical-assistant] indexed topic suggestions skipped:', e.message);
return [];
});
if (indexedExamples.length >= 3) {
_exampleCache = { expiresAt: now + EXAMPLE_CACHE_MS, examples: indexedExamples };
return indexedExamples;
}
var examples = [];
var candidates = rotateExamples(EXAMPLE_CANDIDATES, now);
for (var i = 0; i < candidates.length && examples.length < 9; i++) {
@ -1087,6 +1104,31 @@ async function getAvailableExamples() {
return examples;
}
async function getIndexedTopicExamples() {
var response = await indexedTopicSuggestions(9);
var data = response && (response.structuredContent || response.data || response);
if ((!data || !Array.isArray(data.suggestions)) && response && Array.isArray(response.content)) {
for (var i = 0; i < response.content.length; i++) {
var c = response.content[i];
if (c && c.type === 'text' && c.text) {
try {
var parsed = JSON.parse(c.text);
if (parsed && Array.isArray(parsed.suggestions)) data = parsed;
} catch (e) {}
}
}
}
if (!data || !Array.isArray(data.suggestions)) return [];
return data.suggestions.slice(0, 9).map(function(item) {
return {
label: item.label || 'Indexed topic',
prompt: item.prompt || '',
sourceTitle: Array.isArray(item.sample_titles) ? item.sample_titles[0] : '',
category: item.category || ''
};
}).filter(function(item) { return item.prompt; });
}
function rotateExamples(items, seed) {
var copy = items.slice();
var offset = Math.floor(seed / EXAMPLE_CACHE_MS) % copy.length;
@ -1109,15 +1151,15 @@ async function generateImage(prompt, model) {
function imageSizeForPrompt(prompt) {
var text = String(prompt || '');
if (/\b(flow\s*chart|flowchart|algorithm|pathway|timeline|vertical|stepwise|decision\s*tree|age\s*group|0-21|22-28|29-60)\b/i.test(text)) return '1024x1792';
if (/\b(table|matrix|comparison|wide|landscape|side-by-side)\b/i.test(text)) return '1792x1024';
if (/\b(flow\s*chart|flowchart|algorithm|pathway|timeline|vertical|stepwise|decision\s*tree|age\s*group|0-21|22-28|29-60)\b/i.test(text)) return '1024x1536';
if (/\b(table|matrix|comparison|wide|landscape|side-by-side)\b/i.test(text)) return '1536x1024';
return '1024x1024';
}
function imagePromptForCanvas(prompt, size) {
var guidance = ' Keep all text and boxes fully inside the canvas with generous margins. Use fewer words per box, large readable type, and avoid cropping at edges.';
if (size === '1024x1792') guidance += ' Use a vertical portrait layout with top-to-bottom flow and ample spacing between decision nodes.';
if (size === '1792x1024') guidance += ' Use a wide landscape layout with columns and ample horizontal spacing.';
if (size === '1024x1536') guidance += ' Use a vertical portrait layout with top-to-bottom flow and ample spacing between decision nodes.';
if (size === '1536x1024') guidance += ' Use a wide landscape layout with columns and ample horizontal spacing.';
return String(prompt || '').trim() + guidance;
}