ChatBot Public

HTML Actualizado Sep 8, 2025

Archivos de Código

index.html

Todo en uno 238 líneas
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Chat con Puter AI</title>
  <script src="https://js.puter.com/v2/"></script>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <!-- Prism.js -->
  <link href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-tomorrow.css" rel="stylesheet" />
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-python.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-javascript.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-css.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-markup.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-json.min.js"></script>

  <style>
    * { box-sizing: border-box; }
    body {
      margin: 0;
      font-family: 'Segoe UI', sans-serif;
      background: #f0f0f0;
      display: flex;
      flex-direction: column;
      height: 100vh;
    }
    header {
      background: #4a90e2;
      color: white;
      padding: 15px;
      text-align: center;
      font-size: 20px;
      font-weight: bold;
    }
    #chat {
      flex: 1;
      padding: 15px;
      overflow-y: auto;
      display: flex;
      flex-direction: column;
      gap: 12px;
    }
    .message {
      max-width: 90%;
      padding: 10px 15px;
      border-radius: 18px;
      word-wrap: break-word;
      line-height: 1.5;
      white-space: pre-wrap;
    }
    .user {
      align-self: flex-end;
      background-color: #dcf8c6;
    }
    .bot {
      align-self: flex-start;
      background-color: #ffffff;
      border: 1px solid #ccc;
    }
    footer {
      padding: 10px;
      background: #fff;
      display: flex;
      flex-direction: column;
      gap: 8px;
    }
    #model, #prompt {
      width: 100%;
      padding: 10px;
      font-size: 16px;
    }
    #sendBtn {
      padding: 10px;
      font-size: 16px;
      background-color: #4a90e2;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }
    #sendBtn:disabled {
      background-color: #aaa;
      cursor: not-allowed;
    }
    pre {
      position: relative;
      margin-top: 10px;
      border-radius: 8px;
      overflow: auto;
    }
    .code-header {
      background: #2d2d2d;
      color: #fff;
      padding: 5px 10px;
      font-size: 12px;
      display: flex;
      justify-content: space-between;
      align-items: center;
      border-top-left-radius: 8px;
      border-top-right-radius: 8px;
    }
    .copy-btn {
      background: transparent;
      color: #fff;
      border: none;
      cursor: pointer;
      font-size: 12px;
    }
  </style>
</head>
<body>

  <header>Chat con Puter AI</header>

  <div id="chat"></div>

  <footer>
    <select id="model">
      <option value="o1">o1</option>
      <option value="o1-mini">o1 mini</option>
      <option value="o1-pro">o1 pro</option>
      <option value="o3">o3</option>
      <option value="03-mini">03 mini</option>
      <option value="04-mini">04 mini</option>
      <option value="gpt-4.5-preview">GPT 4.5 Preview</option>
      <option value="gpt-4">gpt-4</option>
      <option value="gpt-4o">gpt-4o</option>
      <option value="gpt-4o-mini" selected>gpt 4o mini</option>
      <option value="claude-3-7-sonnet">claude 3.7 sonnet</option>
      <option value="claude-3-5-sonnet">claude 3.5 sonnet</option>
      <option value="gemini-2.0-flash">gemini 2.0 flash</option>
      <option value="gemini-1.5-flash">gemini 1.5 flash</option>
      <option value="grok-beta">grok beta</option>
      <option value="meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo">meta llama/Meta Llama 3.1 405B Instruct Turbo</option>
    </select>
    <textarea id="prompt" rows="2" placeholder="Escribe tu mensaje..."></textarea>
    <button id="sendBtn" onclick="enviarMensaje()">Enviar</button>
  </footer>

  <script>
    const chatContainer = document.getElementById("chat");
    const promptInput = document.getElementById("prompt");
    const modelSelect = document.getElementById("model");
    const sendBtn = document.getElementById("sendBtn");
    const history = [];

    function crearBurbuja(texto, clase) {
      const div = document.createElement("div");
      div.className = `message ${clase}`;
      div.innerText = texto;
      chatContainer.appendChild(div);
      chatContainer.scrollTop = chatContainer.scrollHeight;
    }

    function copiarCodigo(btn) {
      const code = btn.closest("pre").querySelector("code");
      navigator.clipboard.writeText(code.textContent).then(() => {
        btn.innerText = "Copiado!";
        setTimeout(() => {
          btn.innerText = "Copiar";
        }, 1500);
      });
    }

    function renderizarStreaming(div, textoAcumulado) {
      div.innerHTML = "";

      const partes = textoAcumulado.split(/```/);
      partes.forEach((parte, i) => {
        if (i % 2 === 0) {
          const p = document.createElement("p");
          p.innerText = parte;
          div.appendChild(p);
        } else {
          const [lenguaje, ...lineas] = parte.split('\n');
          const codigo = lineas.join('\n');

          const pre = document.createElement("pre");
          const header = document.createElement("div");
          header.className = "code-header";
          header.innerHTML = `
            <span>${lenguaje || 'code'}</span>
            <button class="copy-btn" onclick="copiarCodigo(this)">Copiar</button>
          `;
          const code = document.createElement("code");
          code.className = `language-${lenguaje}`;
          code.textContent = codigo;

          pre.appendChild(header);
          pre.appendChild(code);
          div.appendChild(pre);
          Prism.highlightElement(code);
        }
      });

      chatContainer.scrollTop = chatContainer.scrollHeight;
    }

    async function enviarMensaje() {
      const prompt = promptInput.value.trim();
      const model = modelSelect.value;
      if (!prompt) return;

      crearBurbuja(prompt, "user");
      history.push({ role: "user", content: prompt });
      promptInput.value = "";
      sendBtn.disabled = true;

      const divBot = document.createElement("div");
      divBot.className = "message bot";
      chatContainer.appendChild(divBot);

      let textoAcumulado = "";

      try {
        const stream = await puter.ai.chat(history, {
          stream: true,
          model: model
        });

        for await (const part of stream) {
          const texto = part?.text || "";
          textoAcumulado += texto;
          renderizarStreaming(divBot, textoAcumulado);
        }

        history.push({ role: "assistant", content: textoAcumulado });
      } catch (error) {
        divBot.innerText = "Error: " + error.message;
      }

      sendBtn.disabled = false;
    }
  </script>

</body>
</html>

Comentarios (0)

¡Aún no hay comentarios. Sé el primero en comentar!