// AI dimension-naming modal (Phase 2), extracted from Sidebar.js in H4. // Pulls top/bottom activator evidence for a dimension, asks the remote provider // (Gemini) for a proposed name, and lets the user accept/edit/save the label. import { STATE, saveLabel } from '../../core/State.js'; import { updateHUD } from '../HUD.js'; import { renderDimensionInspector } from '../../visualizer/DimensionInspector.js'; import { showCustomModal } from './CustomModal.js'; /** * Open the "Nombrar Dimensión" modal for the given dimension index. * @param {number} dimIndex - Dimension to name (0-based). * @returns {void} */ export function showNamingModal(dimIndex) { const activeFilenames = STATE.reliefDocs.filter(d => d.visible).map(d => d.filename); // HTML structure for modal content const contentHTML = `

Analyzing semantic evidence for Dimension #${dimIndex}.

Chunk Evidence (+ / −)
(+) Top Activators:
(-) Bottom Activators:
`; // API response storage let apiData = null; showCustomModal({ title: `Name Dimension #${dimIndex}`, contentHTML: contentHTML, confirmText: "Save", cancelText: "Close", onConfirm: (overlay) => { const inputName = overlay.querySelector('#modal-input-name'); const inputRationale = overlay.querySelector('#modal-input-rationale'); const selectConfidence = overlay.querySelector('#modal-select-confidence'); const finalName = inputName ? inputName.value.trim() : ""; const finalRationale = inputRationale ? inputRationale.value.trim() : ""; const finalConfidence = selectConfidence ? selectConfidence.value : "high"; if (finalName) { saveLabel( dimIndex, finalName, finalRationale, finalConfidence, apiData ? apiData.evidence : {}, 'human' ); updateHUD(); if (STATE.comparisonMode === 'C') { renderDimensionInspector(); } } } }); const confirmBtn = document.getElementById('modal-confirm-btn'); if (confirmBtn) confirmBtn.style.display = 'none'; (async () => { const overlay = document.getElementById('app-modal-overlay'); if (!overlay) return; const posList = overlay.querySelector('#modal-evidence-pos'); const negList = overlay.querySelector('#modal-evidence-neg'); const copyBtn = overlay.querySelector('#modal-btn-copy-prompt'); const loadingEl = overlay.querySelector('#modal-proposal-loading'); const displayEl = overlay.querySelector('#modal-proposal-display'); const nameEl = overlay.querySelector('#modal-proposal-name'); const rationaleEl = overlay.querySelector('#modal-proposal-rationale'); const confidenceEl = overlay.querySelector('#modal-proposal-confidence'); const editSection = overlay.querySelector('#modal-edit-section'); try { if (!STATE.provider) throw new Error("No provider active"); apiData = await STATE.provider.nameDimension(dimIndex, activeFilenames, STATE.featureSpace || 'RAW'); if (posList && apiData.evidence && apiData.evidence.top_activators) { posList.innerHTML = apiData.evidence.top_activators.map(c => `
  • [Val: ${c.value.toFixed(3)}] ${c.text.slice(0, 160)}… (F: ${c.filename})
  • ` ).join('') || '
  • No evidence.
  • '; } if (negList && apiData.evidence && apiData.evidence.bottom_activators) { negList.innerHTML = apiData.evidence.bottom_activators.map(c => `
  • [Val: ${c.value.toFixed(3)}] ${c.text.slice(0, 160)}… (F: ${c.filename})
  • ` ).join('') || '
  • No evidence.
  • '; } if (copyBtn && apiData.prompt) { copyBtn.removeAttribute('disabled'); copyBtn.onclick = () => { navigator.clipboard.writeText(apiData.prompt) .then(() => { copyBtn.textContent = '✅ Copied!'; setTimeout(() => { copyBtn.textContent = '📋 Copy Gemini Prompt'; }, 2000); }) .catch(err => console.error("Clipboard copy failed:", err)); }; } if (loadingEl) loadingEl.style.display = 'none'; if (apiData.has_api && apiData.success && apiData.proposal) { if (displayEl) displayEl.style.display = 'flex'; if (nameEl) nameEl.textContent = apiData.proposal.name; if (rationaleEl) rationaleEl.textContent = apiData.proposal.rationale; if (confidenceEl) { confidenceEl.textContent = apiData.proposal.confidence; const conf = apiData.proposal.confidence.toLowerCase(); if (conf === 'high') { confidenceEl.style.color = 'var(--color-neutral-50)'; confidenceEl.style.backgroundColor = 'oklch(from var(--color-semantic-success) l c h / 0.3)'; confidenceEl.style.border = '1px solid var(--color-semantic-success)'; } else if (conf === 'medium') { confidenceEl.style.color = 'var(--color-neutral-50)'; confidenceEl.style.backgroundColor = 'oklch(from var(--color-semantic-warning) l c h / 0.3)'; confidenceEl.style.border = '1px solid var(--color-semantic-warning)'; } else { confidenceEl.style.color = 'var(--color-neutral-50)'; confidenceEl.style.backgroundColor = 'oklch(from var(--color-semantic-error) l c h / 0.3)'; confidenceEl.style.border = '1px solid var(--color-semantic-error)'; } } const acceptBtn = overlay.querySelector('#modal-btn-accept'); if (acceptBtn) { acceptBtn.onclick = () => { saveLabel( dimIndex, apiData.proposal.name, apiData.proposal.rationale, apiData.proposal.confidence, apiData.evidence, 'ai' ); updateHUD(); if (STATE.comparisonMode === 'C') { renderDimensionInspector(); } overlay.classList.remove('active'); setTimeout(() => overlay.remove(), 300); }; } const editProposalBtn = overlay.querySelector('#modal-btn-edit-proposal'); if (editProposalBtn) { editProposalBtn.onclick = () => { if (displayEl) displayEl.style.display = 'none'; if (editSection) editSection.style.display = 'flex'; if (confirmBtn) confirmBtn.style.display = 'block'; const inputName = overlay.querySelector('#modal-input-name'); const inputRationale = overlay.querySelector('#modal-input-rationale'); const selectConfidence = overlay.querySelector('#modal-select-confidence'); if (inputName) inputName.value = apiData.proposal.name; if (inputRationale) inputRationale.value = apiData.proposal.rationale; if (selectConfidence) selectConfidence.value = apiData.proposal.confidence; setTimeout(() => { if (inputName) { inputName.focus(); inputName.select(); } }, 50); }; } } else { if (loadingEl) { if (apiData.error) { loadingEl.textContent = `❌ API failed: ${apiData.error}. Switching to MANUAL mode.`; loadingEl.style.color = 'var(--color-semantic-error)'; loadingEl.style.display = 'block'; } else { loadingEl.textContent = "ℹ️ MANUAL mode active (copy the prompt above and fill in the fields below)."; loadingEl.style.color = 'var(--color-neutral-400)'; loadingEl.style.display = 'block'; } } if (editSection) editSection.style.display = 'flex'; if (confirmBtn) confirmBtn.style.display = 'block'; const prefix = (STATE.featureSpace || 'RAW').toLowerCase(); const key = `${prefix}_${dimIndex}`; const currentLabel = STATE.dimensionLabels[key] || ""; const dictEntry = STATE.dimensionDictionary ? STATE.dimensionDictionary[key] : null; const inputName = overlay.querySelector('#modal-input-name'); const inputRationale = overlay.querySelector('#modal-input-rationale'); const selectConfidence = overlay.querySelector('#modal-select-confidence'); if (inputName) inputName.value = currentLabel; if (inputRationale && dictEntry) inputRationale.value = dictEntry.rationale || ""; if (selectConfidence && dictEntry) selectConfidence.value = dictEntry.confidence || "high"; setTimeout(() => { if (inputName) { inputName.focus(); inputName.select(); } }, 50); } } catch (err) { console.error("Error loading naming evidence:", err); if (loadingEl) { loadingEl.textContent = `❌ Error: ${err.message}`; loadingEl.style.color = 'var(--color-semantic-error)'; } } })(); }