Download app/static/widget/replyflow-widget.js from nvikou/ReplyFlow: direct link, hf CLI and curl.
- Browser
- Download file 4.58 kB
-
https://huggingface.co/spaces/nvikou/ReplyFlow/resolve/main/app/static/widget/replyflow-widget.js
- Command line
-
hf download hf://spaces/nvikou/ReplyFlow/app/static/widget/replyflow-widget.js
-
curl -L -o replyflow-widget.js https://huggingface.co/spaces/nvikou/ReplyFlow/resolve/main/app/static/widget/replyflow-widget.js
4.58 kB
| /** | |
| * ReplyFlow embeddable widget. | |
| * Usage: <script src="https://YOUR_HOST/widget.js" defer></script> | |
| */ | |
| (function () { | |
| if (window.__ReplyFlowWidgetLoaded) return; | |
| window.__ReplyFlowWidgetLoaded = true; | |
| const script = | |
| document.currentScript || | |
| document.querySelector('script[src*="widget.js"]'); | |
| const base = | |
| (script && script.src | |
| ? script.src.replace(/\/widget\.js(?:\?.*)?$/, "") | |
| : window.location.origin) || ""; | |
| const style = document.createElement("style"); | |
| style.textContent = ` | |
| #rf-launcher{position:fixed;right:20px;bottom:20px;z-index:99999; | |
| width:58px;height:58px;border-radius:50%;border:0;cursor:pointer; | |
| background:linear-gradient(135deg,#d4a24c,#e8c078);color:#1a1408; | |
| font:700 14px/1 Manrope,system-ui,sans-serif;box-shadow:0 12px 30px rgba(0,0,0,.35)} | |
| #rf-panel{position:fixed;right:20px;bottom:90px;z-index:99999;width:min(360px,calc(100vw - 24px)); | |
| height:min(520px,70vh);display:none;flex-direction:column;overflow:hidden; | |
| border-radius:18px;background:#16302b;color:#f3f0e8;border:1px solid rgba(243,240,232,.12); | |
| box-shadow:0 24px 60px rgba(0,0,0,.4);font:14px/1.4 Manrope,system-ui,sans-serif} | |
| #rf-panel.open{display:flex} | |
| #rf-head{padding:12px 14px;border-bottom:1px solid rgba(243,240,232,.12)} | |
| #rf-head strong{font-family:Syne,Manrope,sans-serif;letter-spacing:-.02em} | |
| #rf-msgs{flex:1;overflow:auto;padding:12px;display:flex;flex-direction:column;gap:8px} | |
| .rf-b{max-width:88%;padding:8px 10px;border-radius:12px;white-space:pre-wrap} | |
| .rf-u{align-self:flex-end;background:rgba(212,162,76,.22)} | |
| .rf-a{align-self:flex-start;background:rgba(255,255,255,.06);border:1px solid rgba(243,240,232,.1)} | |
| #rf-form{display:flex;gap:6px;padding:10px;border-top:1px solid rgba(243,240,232,.12)} | |
| #rf-form input{flex:1;border-radius:999px;border:1px solid rgba(243,240,232,.15); | |
| background:rgba(0,0,0,.25);color:#f3f0e8;padding:10px 12px;font:inherit} | |
| #rf-form button{border:0;border-radius:999px;padding:10px 12px;cursor:pointer; | |
| background:linear-gradient(135deg,#d4a24c,#e8c078);color:#1a1408;font-weight:700} | |
| `; | |
| document.head.appendChild(style); | |
| const launcher = document.createElement("button"); | |
| launcher.id = "rf-launcher"; | |
| launcher.type = "button"; | |
| launcher.setAttribute("aria-label", "Open ReplyFlow chat"); | |
| launcher.textContent = "RF"; | |
| const panel = document.createElement("div"); | |
| panel.id = "rf-panel"; | |
| panel.innerHTML = ` | |
| <div id="rf-head"> | |
| <strong>ReplyFlow</strong> | |
| </div> | |
| <div id="rf-msgs"></div> | |
| <form id="rf-form"> | |
| <input id="rf-input" placeholder="Message…" autocomplete="off" /> | |
| <button type="submit">Send</button> | |
| </form> | |
| `; | |
| document.body.appendChild(panel); | |
| document.body.appendChild(launcher); | |
| const msgs = panel.querySelector("#rf-msgs"); | |
| const form = panel.querySelector("#rf-form"); | |
| const input = panel.querySelector("#rf-input"); | |
| let conversationId = null; | |
| let started = false; | |
| function bubble(role, text) { | |
| const el = document.createElement("div"); | |
| el.className = `rf-b ${role === "user" ? "rf-u" : "rf-a"}`; | |
| el.textContent = text; | |
| msgs.appendChild(el); | |
| msgs.scrollTop = msgs.scrollHeight; | |
| } | |
| async function start() { | |
| msgs.innerHTML = ""; | |
| const res = await fetch( | |
| `${base}/api/chat/start?ui_language=en`, | |
| { method: "POST" } | |
| ); | |
| const data = await res.json(); | |
| conversationId = data.conversation_id; | |
| bubble("assistant", data.greeting); | |
| started = true; | |
| } | |
| launcher.addEventListener("click", async () => { | |
| panel.classList.toggle("open"); | |
| if (panel.classList.contains("open") && !started) { | |
| await start(); | |
| } | |
| }); | |
| form.addEventListener("submit", async (e) => { | |
| e.preventDefault(); | |
| const text = input.value.trim(); | |
| if (!text || !conversationId) return; | |
| input.value = ""; | |
| bubble("user", text); | |
| const res = await fetch(`${base}/api/chat/message`, { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ | |
| conversation_id: conversationId, | |
| message: text, | |
| ui_language: "en", | |
| }), | |
| }); | |
| const data = await res.json(); | |
| bubble("assistant", data.reply || "…"); | |
| }); | |
| })(); | |