Coal AI - Chat
Autentikace
Přihlášení
Pro vstup do Coal AI Chat se přihlas nebo si vytvoř účet.
Použije se Autentikace s email / password přihlášením.
`);
workspacePreview.srcdoc = fullHtml;
}
function toggleWorkspacePanel(mode) {
workspacePanelMode = mode;
workspacePreviewToggle.classList.toggle("active", mode === 'preview');
workspaceChatToggle.classList.toggle("active", mode === 'chat');
workspacePreviewContent.classList.toggle("active", mode === 'preview');
workspaceChatContent.classList.toggle("active", mode === 'chat');
}
async function downloadWorkspaceAsZip() {
const zip = new JSZip();
Object.entries(workspaceFiles).forEach(([filename, content]) => {
zip.file(filename, content);
});
const blob = await zip.generateAsync({ type: "blob" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "workspace.zip";
a.click();
URL.revokeObjectURL(url);
}
async function sendWorkspaceMessage() {
const text = workspaceChatInput.value.trim();
if (!text) return;
// Check credits before sending
const canSend = await checkAndDeductCredits();
if (!canSend) return;
workspaceChatInput.value = "";
workspaceEmptyState.classList.add("hidden");
// Add user message
const userMsgDiv = document.createElement("div");
userMsgDiv.className = "message user";
userMsgDiv.textContent = text;
workspaceChat.appendChild(userMsgDiv);
// Prepare file context
const fileContext = Object.entries(workspaceFiles)
.map(([filename, content]) => `Soubor: ${filename}\n\`\`\`\n${content}\n\`\`\``)
.join("\n\n");
const systemPrompt = `Jsi Coal AI — coding asistent.
Uživatel pracuje na webovém projektu. Aktuální soubory:
${fileContext}
PRAVIDLA:
- Odpovídáš VŽDY pouze česky
- Navrhuj změny kódu ve formátu:
Soubor:
\`\`\`
\`\`\`
- Buď stručný a přímý
- Pokud něco nevíš, řekni to přímo`;
try {
const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer 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`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: MODELS[currentModel].id,
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: text }
],
max_tokens: 1024
})
});
if (!response.ok) {
throw new Error("Nepodařilo se spojit s Coal AI");
}
const data = await response.json();
const aiMessage = data.choices?.[0]?.message?.content;
if (!aiMessage) {
throw new Error("Neplatná odpověď od AI");
}
// Add AI message with apply buttons
const aiMsgDiv = document.createElement("div");
aiMsgDiv.className = "message assistant";
// Parse AI response for code blocks
const lines = aiMessage.split('\n');
let currentCodeBlock = null;
let currentFile = null;
let output = "";
lines.forEach(line => {
if (line.startsWith("Soubor:")) {
currentFile = line.replace("Soubor:", "").trim();
output += `${line}
`;
} else if (line.startsWith("```")) {
if (currentCodeBlock) {
// End code block
const lang = currentCodeBlock.lang || "text";
const isPython = lang === "python";
output += `${currentCodeBlock.content}
`;
if (isPython) {
output += `Python kód lze spustit lokálně.
`;
} else if (currentFile) {
output += ``;
}
currentCodeBlock = null;
} else {
// Start code block
currentCodeBlock = {
lang: line.replace("```", "").trim(),
content: ""
};
}
} else if (currentCodeBlock) {
currentCodeBlock.content += line + "\n";
} else {
output += `${line}
`;
}
});
aiMsgDiv.innerHTML = marked.parse(output);
workspaceChat.appendChild(aiMsgDiv);
// Add event listeners for apply buttons
aiMsgDiv.querySelectorAll('.workspace-apply-btn').forEach(btn => {
btn.addEventListener('click', () => {
const file = btn.dataset.file;
const code = decodeURIComponent(btn.dataset.code);
if (workspaceFiles[file]) {
workspaceFiles[file] = code;
if (workspaceCurrentFile === file) {
workspaceEditor.setValue(code);
}
renderWorkspaceFileList();
debouncedUpdatePreview();
btn.textContent = "✓ Změna aplikována";
btn.disabled = true;
}
});
});
workspaceChat.scrollTop = workspaceChat.scrollHeight;
} catch (error) {
console.error("Workspace chat error:", error);
const errorDiv = document.createElement("div");
errorDiv.className = "chat-error";
errorDiv.textContent = "Omlouváme se, ale něco se pokazilo. Zkus to znovu.";
workspaceChat.appendChild(errorDiv);
}
}
// Event listeners
btnSignIn.addEventListener("click", () => handleAuth("signin"));
btnSignUp.addEventListener("click", () => handleAuth("signup"));
profileBtn.addEventListener("click", toggleProfileMenu);
btnSaveName.addEventListener("click", saveProfileName);
btnLogout.addEventListener("click", async () => {
await signOut(auth);
});
sidebarToggle.addEventListener("click", toggleSidebar);
newChatBtn.addEventListener("click", createNewChat);
chatSend.addEventListener("click", sendMessage);
chatInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
sendMessage();
}
});
chatUpload.addEventListener("click", () => {
imageInput.click();
});
imageInput.addEventListener("change", handleImageUpload);
imageRemove.addEventListener("click", removeImage);
modelMini.addEventListener("click", () => selectModel('mini'));
modelStandard.addEventListener("click", () => selectModel('standard'));
modelPro.addEventListener("click", () => selectModel('pro'));
// Workspace event listeners
navWorkspaceBtn.addEventListener("click", toggleWorkspace);
workspaceNewFileBtn.addEventListener("click", createWorkspaceFile);
workspaceUploadFolderBtn.addEventListener("click", () => {
workspaceFolderInput.click();
});
workspaceFolderInput.addEventListener("change", handleFolderUpload);
workspaceRunBtn.addEventListener("click", updatePreview);
workspaceDownloadBtn.addEventListener("click", downloadWorkspaceAsZip);
workspacePreviewToggle.addEventListener("click", () => toggleWorkspacePanel('preview'));
workspaceChatToggle.addEventListener("click", () => toggleWorkspacePanel('chat'));
workspaceChatSend.addEventListener("click", sendWorkspaceMessage);
workspaceChatInput.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
sendWorkspaceMessage();
}
});
onAuthStateChanged(auth, (user) => {
if (user) {
currentUser = user;
setAppVisible(true, user);
syncProfileBadge();
loadChatList();
initializeUserCredits();
} else {
currentUser = null;
setAppVisible(false);
authMessage.textContent = "Přihlas se, nebo si vytvoř účet.";
// Clean up
if (chatMessagesListener) {
chatMessagesListener();
chatMessagesListener = null;
}
currentChatId = null;
}
});