📜
ai.js
Back
📝 Javascript ⚡ Executable Ctrl+S: Save • Ctrl+R: Run • Ctrl+F: Find
// ===== AI Overlay & Chat Interface ===== // Wait for editor to be ready document.addEventListener('DOMContentLoaded', () => { // Get editor reference from global API const { editor, getSelectedText, getValue, focus: focusEditor } = window.editorAPI || {}; if (!editor) { console.warn('Editor not found, AI functionality may be limited'); } // DOM elements const aiBtn = document.getElementById("aiBtn"); const aiOverlay = document.getElementById("aiOverlay"); const overlayClose = document.getElementById("overlayClose"); const promptForm = document.getElementById("promptForm"); const prompt = document.getElementById("prompt"); const messages = document.getElementById("messages"); // ===== Overlay Management ===== function openOverlay() { aiOverlay.classList.add("open"); setTimeout(() => { prompt.focus(); autoGrow(prompt); }, 0); } function closeOverlay() { aiOverlay.classList.remove("open"); aiBtn.focus(); } // Event listeners aiBtn.addEventListener("click", openOverlay); overlayClose.addEventListener("click", closeOverlay); // ESC key to close window.addEventListener("keydown", (e) => { if (aiOverlay.classList.contains("open") && e.key === "Escape") { closeOverlay(); } }); // ===== Auto-growing Textarea ===== function autoGrow(el) { el.style.height = "auto"; el.style.height = Math.min(el.scrollHeight, window.innerHeight * 0.4) + "px"; } prompt.addEventListener("input", () => autoGrow(prompt)); prompt.addEventListener("paste", () => setTimeout(() => autoGrow(prompt), 0)); // ===== Message Management ===== function appendMsg(role, text) { const div = document.createElement("div"); div.className = `msg ${role === "user" ? "user" : "assistant"}`; div.textContent = text; messages.appendChild(div); // Auto-scroll to bottom messages.parentElement.scrollTop = messages.parentElement.scrollHeight; } function clearMessages() { messages.innerHTML = ""; } // ===== AI Chat Handler (Stubbed) ===== promptForm.addEventListener("submit", async (e) => { e.preventDefault(); const text = prompt.value.trim(); if (!text) return; // Add user message appendMsg("user", text); // Get code context const selection = getSelectedText ? getSelectedText() : ""; const context = selection || (getValue ? getValue().slice(0, 1500) : ""); // Clear prompt prompt.value = ""; autoGrow(prompt); // Simulate AI response (replace with actual API call) await simulateAIResponse(text, context, selection); }); async function simulateAIResponse(userQuery, codeContext, isSelection) { // Add loading indicator const loadingMsg = document.createElement("div"); loadingMsg.className = "msg assistant"; loadingMsg.textContent = "AI is thinking..."; messages.appendChild(loadingMsg); // Simulate processing delay await new Promise(resolve => setTimeout(resolve, 1000)); // Remove loading message loadingMsg.remove(); // Generate response const contextType = isSelection ? "the selected code" : "the current file"; const response = `You asked: "${userQuery}" (This is a stub response. In a real implementation, this would connect to an AI API.) I would analyze ${contextType} and provide helpful suggestions about: ${codeContext.slice(0, 300)}${codeContext.length > 300 ? "..." : ""} Some things I could help with: • Code review and suggestions • Bug detection and fixes • Optimization recommendations • Documentation generation • Refactoring guidance • Adding new features To enable real AI responses, configure your API settings in the Settings panel.`; appendMsg("assistant", response); } // ===== Real AI API Integration (Template) ===== async function callAIAPI(userQuery, codeContext) { const aiProvider = document.getElementById("ai-provider")?.value; const aiModel = document.getElementById("ai-model")?.value; const aiKey = document.getElementById("ai-key")?.value; const aiTemp = parseFloat(document.getElementById("ai-temp")?.value || "0.4"); if (!aiProvider || aiProvider === "none" || !aiKey) { throw new Error("AI provider and API key must be configured in Settings"); } const systemPrompt = `You are a helpful coding assistant. The user is working with code and may ask questions about it, request modifications, or seek explanations. Always provide clear, actionable advice. Current code context: ${codeContext}`; const requestBody = { model: aiModel, messages: [ { role: "system", content: systemPrompt }, { role: "user", content: userQuery } ], temperature: aiTemp, max_tokens: 1000 }; let apiUrl, headers; switch (aiProvider) { case "openai": apiUrl = "https://api.openai.com/v1/chat/completions"; headers = { "Content-Type": "application/json", "Authorization": `Bearer ${aiKey}` }; break; case "anthropic": apiUrl = "https://api.anthropic.com/v1/messages"; headers = { "Content-Type": "application/json", "x-api-key": aiKey, "anthropic-version": "2023-06-01" }; // Adjust request body for Anthropic's format requestBody.model = aiModel || "claude-3-sonnet-20240229"; requestBody.max_tokens = 1000; delete requestBody.messages; requestBody.messages = [{ role: "user", content: userQuery }]; requestBody.system = systemPrompt; break; case "deepseek": apiUrl = "https://api.deepseek.com/v1/chat/completions"; headers = { "Content-Type": "application/json", "Authorization": `Bearer ${aiKey}` }; break; default: throw new Error(`Unsupported AI provider: ${aiProvider}`); } const response = await fetch(apiUrl, { method: "POST", headers, body: JSON.stringify(requestBody) }); if (!response.ok) { throw new Error(`API request failed: ${response.status} ${response.statusText}`); } const data = await response.json(); // Extract response based on provider if (aiProvider === "anthropic") { return data.content[0].text; } else { return data.choices[0].message.content; } } // ===== Keyboard Shortcuts ===== document.addEventListener("keydown", (e) => { // Ctrl/Cmd + Shift + A to open AI overlay if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === "A") { e.preventDefault(); openOverlay(); } }); // ===== Export AI API for potential external use ===== window.aiAPI = { openOverlay, closeOverlay, appendMsg, clearMessages, callAIAPI }; console.log("AI module loaded successfully"); });