// Popup script for Cortex browser extension const CORTEX_API = 'http://localhost:3100/api'; // DOM elements const titleInput = document.getElementById('title'); const kindSelect = document.getElementById('kind'); const tagsInput = document.getElementById('tags'); const includeContent = document.getElementById('includeContent'); const selectionOnly = document.getElementById('selectionOnly'); const saveButton = document.getElementById('save'); const cancelButton = document.getElementById('cancel'); const statusDiv = document.getElementById('status'); let pageData = null; // Initialize popup async function init() { try { // Get current tab const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); // Request content from content script const response = await chrome.tabs.sendMessage(tab.id, { action: 'extract' }); pageData = response; // Pre-fill form titleInput.value = response.title || tab.title || ''; // Suggest tags based on URL const url = new URL(tab.url); const suggestedTags = ['web-clip']; if (url.hostname.includes('github')) suggestedTags.push('github'); if (url.hostname.includes('docs')) suggestedTags.push('documentation'); if (url.hostname.includes('stackoverflow')) suggestedTags.push('stackoverflow'); tagsInput.value = suggestedTags.join(', '); // Enable selection only if there's selected text if (response.selection) { selectionOnly.disabled = false; } else { selectionOnly.disabled = true; } } catch (err) { showStatus('Could not extract page content', 'error'); console.error('Init error:', err); } } // Save to Cortex async function save() { saveButton.disabled = true; saveButton.textContent = 'Saving...'; try { const content = selectionOnly.checked ? pageData?.selection : (includeContent.checked ? pageData?.content : ''); const tags = tagsInput.value .split(',') .map(t => t.trim()) .filter(t => t.length > 0); const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); const response = await fetch(`${CORTEX_API}/nodes`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ kind: kindSelect.value, title: titleInput.value, content: content, tags: tags, metadata: { source: { type: 'url', url: tab.url, savedAt: Date.now(), }, }, }), }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const node = await response.json(); showStatus(`Saved! ID: ${node.id.slice(0, 8)}`, 'success'); // Close popup after brief delay setTimeout(() => window.close(), 1500); } catch (err) { showStatus(`Failed to save: ${err.message}`, 'error'); console.error('Save error:', err); // Check if Cortex server is running if (err.message.includes('fetch')) { showStatus('Is Cortex server running? (cortex serve)', 'error'); } } finally { saveButton.disabled = false; saveButton.textContent = 'Save'; } } // Show status message function showStatus(message, type) { statusDiv.textContent = message; statusDiv.className = `status ${type}`; } // Event listeners saveButton.addEventListener('click', save); cancelButton.addEventListener('click', () => window.close()); // Toggle selection only checkbox when include content is unchecked includeContent.addEventListener('change', () => { if (!includeContent.checked) { selectionOnly.checked = false; } }); selectionOnly.addEventListener('change', () => { if (selectionOnly.checked) { includeContent.checked = true; } }); // Initialize on load init();