59 lines
2.8 KiB
JavaScript
59 lines
2.8 KiB
JavaScript
import { escapeAttr } from './citations.js';
|
|
|
|
export function createAssistantImageStore() {
|
|
var generatedImages = {};
|
|
var generatedImageSeq = 0;
|
|
|
|
function renderGeneratedImage(src, alt) {
|
|
var id = 'img-' + (++generatedImageSeq);
|
|
generatedImages[id] = src;
|
|
return '<div class="assistant-generated-image"><img src="' + escapeAttr(src) + '" alt="' + escapeAttr(alt || 'Generated image') + '">' +
|
|
'<div class="assistant-image-actions">' +
|
|
'<button type="button" class="btn-sm btn-ghost" data-assistant-open-image="' + escapeAttr(id) + '"><i class="fas fa-expand"></i> Preview</button>' +
|
|
'<a class="btn-sm btn-ghost" href="' + escapeAttr(src) + '" download="clinical-visual.png"><i class="fas fa-download"></i> Download</a>' +
|
|
'</div></div>';
|
|
}
|
|
|
|
function openImagePreview(id) {
|
|
var src = generatedImages[id];
|
|
if (!src) return;
|
|
closeImagePreview();
|
|
var modal = document.createElement('div');
|
|
modal.className = 'assistant-image-modal';
|
|
modal.innerHTML = '<div class="assistant-image-modal-card"><button type="button" class="assistant-image-modal-close" aria-label="Close">×</button><img src="' + escapeAttr(src) + '" alt="Generated clinical visual"></div>';
|
|
document.body.appendChild(modal);
|
|
}
|
|
|
|
function closeImagePreview() {
|
|
document.querySelectorAll('.assistant-image-modal').forEach(function (el) { el.remove(); });
|
|
}
|
|
|
|
function clear() {
|
|
generatedImages = {};
|
|
closeImagePreview();
|
|
}
|
|
|
|
return {
|
|
renderGeneratedImage: renderGeneratedImage,
|
|
openImagePreview: openImagePreview,
|
|
closeImagePreview: closeImagePreview,
|
|
clear: clear
|
|
};
|
|
}
|
|
|
|
export function buildContextualImagePrompt(request, lastAnswer, lastSources) {
|
|
var prompt = String(request || '').trim();
|
|
if (!lastAnswer) return prompt;
|
|
var sourceText = (lastSources || []).slice(0, 6).map(function (s, idx) {
|
|
return '[' + (s.number || idx + 1) + '] ' + (s.title || s.resource || 'Source') + (s.page ? ', page ' + s.page : '');
|
|
}).join('\n');
|
|
return prompt + '\n\nUse this clinical answer as the required context. Do not switch topics or introduce unrelated scenes such as gardening. Create a medical teaching visual faithful to the answer.\n\nAnswer:\n' + String(lastAnswer || '').slice(0, 3000) + '\n\nSources:\n' + sourceText;
|
|
}
|
|
|
|
export function isImageRequest(text) {
|
|
text = String(text || '').trim();
|
|
return /^(image|photo|picture|visual|illustration|diagram|figure|flowchart|infographic)$/i.test(text) ||
|
|
/\b(show|see|display|view|image|photo|picture|visual|illustration|diagram|figure)\b/i.test(text) && text.split(/\s+/).length <= 6 ||
|
|
/\b(generate|create|draw|make|render)\b[\s\S]{0,80}\b(image|picture|illustration|visual|infographic|diagram|flowchart)\b/i.test(text) ||
|
|
/\b(generate|create|draw|make|render)\b[\s\S]{0,80}\b(an?|the)?\s*(algorithm|pathway|poster|teaching visual)\b/i.test(text);
|
|
}
|