-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbundle2.min.js
More file actions
119 lines (118 loc) · 8.6 KB
/
bundle2.min.js
File metadata and controls
119 lines (118 loc) · 8.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
class LangflowChat extends HTMLElement {
constructor() {
super(), this.attachShadow({ mode: "open" }), (this.debug = !1)
}
log(...t) {
this.debug && console.log("[LangflowChat]", ...t)
}
async validateConfig(t, e, s) {
if ((this.log("Validating config:", { apiKey: t, hostUrl: e, flowId: s }), !t || !e || !s)) {
const i = []
throw (
(t || i.push("apiKey"),
e || i.push("hostUrl"),
s || i.push("flowId"),
new Error(`Missing required configuration: ${i.join(", ")}`))
)
}
try {
const i = await fetch(`${e}/api/v1/health`, {
method: "GET",
headers: { Accept: "application/json", "api-key": t },
})
if ((this.log("Validation response:", i.status), 403 === i.status))
throw new Error("Invalid API key or insufficient permissions")
if (!i.ok) throw new Error(`API validation failed: ${i.status}`)
} catch (i) {
throw (this.log("Validation error:", i), i)
}
}
async connectedCallback() {
const t = this.getAttribute("window_title") || "Chat Support",
e = this.getAttribute("flow_id"),
s = this.getAttribute("host_url"),
i = this.getAttribute("api_key")
this.debug = "true" === this.getAttribute("debug")
try {
await this.validateConfig(i, s, e)
} catch (n) {
return console.error("Configuration Error:", n), void this.renderError(n.message)
}
const a = document.createElement("style")
;(a.textContent = `:host{--primary:#7c3aed;--primary-foreground:#fff;--muted:#f3f4f6;--muted-foreground:#6b7280;--border:#e5e7eb}:host(.dark){--primary:#7c3aed;--primary-foreground:#fff;--muted:#1f2937;--muted-foreground:#9ca3af;--border:#374151}.widget-container{position:fixed;bottom:1rem;right:1rem;z-index:50;font-family:system-ui,sans-serif}.chat-card{width:380px;height:600px;background:#fff;border:1px solid var(--border);border-radius:.5rem;box-shadow:0 20px 25px -5px rgba(0,0,0,.1);display:flex;flex-direction:column}.dark .chat-card{background:#111827;color:#fff}.chat-header{padding:1rem;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between}.header-title{display:flex;align-items:center;gap:.5rem;font-weight:600}.header-actions{display:flex;align-items:center;gap:.5rem}.chat-content{flex:1;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:1rem}.message{display:flex;align-items:start;gap:.5rem}.message.user{flex-direction:row-reverse}.message-bubble{max-width:80%;padding:.5rem 1rem;border-radius:.5rem}.message.assistant .message-bubble{background:var(--muted);color:var(--muted-foreground)}.message.user .message-bubble{background:var(--primary);color:var(--primary-foreground)}.avatar{width:2rem;height:2rem;border-radius:50%;overflow:hidden}.avatar img{width:100%;height:100%;object-fit:cover}.chat-footer{padding:1rem;border-top:1px solid var(--border)}.chat-form{display:flex;gap:.5rem}.chat-input{flex:1;padding:.5rem;border:1px solid var(--border);border-radius:.375rem;background:transparent;color:inherit}.dark .chat-input{border-color:var(--border)}.chat-input:focus{outline:2px solid var(--primary);outline-offset:-1px}.btn{display:inline-flex;align-items:center;justify-content:center;padding:.5rem;border:none;border-radius:.375rem;background:var(--primary);color:var(--primary-foreground);cursor:pointer}.btn:hover{opacity:.9}.btn.icon{padding:.5rem}.toggle-btn{position:fixed;bottom:1rem;right:1rem;width:3rem;height:3rem;border-radius:9999px;background:var(--primary);color:var(--primary-foreground);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center}.theme-toggle{background:transparent;border:none;color:inherit;cursor:pointer;padding:.5rem;border-radius:.375rem}.theme-toggle:hover{background:var(--muted)}.error-message{position:fixed;bottom:1rem;right:1rem;background:#fee2e2;border:1px solid #ef4444;color:#dc2626;padding:1rem;border-radius:.5rem;max-width:300px;z-index:50}`),
this.shadowRoot.appendChild(a)
const r = document.createElement("div")
;(r.className = "widget-container"),
(r.innerHTML = `<div id="chat-window" style="display:none" class="chat-card"><div class="chat-header"><div class="header-title"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>${t}</div><div class="header-actions"><button id="theme-toggle" class="theme-toggle"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg></button><button id="close-chat" class="theme-toggle"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg></button></div></div><div id="chat-content" class="chat-content"></div><div class="chat-footer"><form id="chat-form" class="chat-form"><input type="text" id="message-input" class="chat-input" placeholder="Type your message..."><button type="submit" class="btn icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z"/></svg></button></form></div></div><button id="toggle-chat" class="toggle-btn"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></button>`),
this.shadowRoot.appendChild(r)
const o = this.shadowRoot.getElementById("chat-window"),
d = this.shadowRoot.getElementById("toggle-chat"),
l = this.shadowRoot.getElementById("close-chat"),
h = this.shadowRoot.getElementById("chat-content"),
c = this.shadowRoot.getElementById("chat-form"),
g = this.shadowRoot.getElementById("message-input"),
m = this.shadowRoot.getElementById("theme-toggle"),
p = window.matchMedia("(prefers-color-scheme: dark)"),
u = (t) => {
this.classList.toggle("dark", t)
}
u(p.matches),
p.addEventListener("change", (t) => u(t.matches)),
m.addEventListener("click", () => {
this.classList.toggle("dark")
}),
d.addEventListener("click", () => {
;(o.style.display = "flex"), (d.style.display = "none")
}),
l.addEventListener("click", () => {
;(o.style.display = "none"), (d.style.display = "flex")
}),
c.addEventListener("submit", async (t) => {
t.preventDefault()
const n = g.value.trim()
if (!n) return
f("user", n), (g.value = "")
try {
const t = new URL(`${s}/api/v1/process/${e}`)
this.log("Sending request to:", t.toString()), this.log("Using API key:", i)
const a = await fetch(t, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json", "api-key": i },
body: JSON.stringify({ input: { question: n }, conversation_id: Date.now().toString() }),
})
if ((this.log("Response status:", a.status), 403 === a.status)) {
const t = await a.json()
throw (
(this.log("Error response:", t),
new Error(`Authentication failed: ${t.detail || "Invalid API key format or permissions"}`))
)
}
if (!a.ok) {
const t = await a.text()
throw (this.log("Error response text:", t), new Error(`HTTP error! status: ${a.status}, message: ${t}`))
}
const r = await a.json()
if ((this.log("Response data:", r), !r.data || !r.data.length)) throw new Error("Invalid response format")
f("assistant", r.data[0].content)
} catch (t) {
console.error("Chat API Error:", t), f("assistant", `Error: ${t.message}`)
}
})
const f = (t, e) => {
const s = document.createElement("div")
s.className = `message ${t}`
let i = `<div class="message-bubble">${e}</div>`
"assistant" === t &&
(i = `<div class="avatar"><img src="https://hebbkx1anhila5yf.public.blob.vercel-storage.com/399-rmQgplK2ef7TvviORQuRol3msTsG4E.png" alt="AI Assistant"></div>${i}`),
(s.innerHTML = i),
h.appendChild(s),
(h.scrollTop = h.scrollHeight)
}
f("assistant", "Hello! How can I help you today?")
}
renderError(t) {
const e = document.createElement("div")
;(e.className = "error-message"), (e.textContent = `Configuration Error: ${t}`), this.shadowRoot.appendChild(e)
}
}
customElements.define("langflow-chat", LangflowChat)