@makemore/agent-frontend 2.7.2 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,590 @@
1
+ var nt=Object.defineProperty;var st=(e,t,n)=>t in e?nt(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Me=(e,t,n)=>(st(e,typeof t!="symbol"?t+"":t,n),n);import{render as et}from"preact";import{html as ht}from"htm/preact";import{html as J}from"htm/preact";import{useState as W,useEffect as ae,useCallback as te,useMemo as Xe}from"preact/hooks";import{html as G}from"htm/preact";function at(e){return e.replace(/_([a-z])/g,(t,n)=>n.toUpperCase())}function we(e){return e.replace(/[A-Z]/g,t=>`_${t.toLowerCase()}`)}function le(e){return Array.isArray(e)?e.map(le):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([t,n])=>[at(t),le(n)])):e}function ce(e){return Array.isArray(e)?e.map(ce):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([t,n])=>[we(t),ce(n)])):e}function de(){return"msg-"+Date.now()+"-"+Math.random().toString(36).substr(2,9)}function D(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}function Ie(e){if(!e)return"";try{let t=new Date(e),o=new Date-t,i=Math.floor(o/6e4),c=Math.floor(o/36e5),w=Math.floor(o/864e5);return i<1?"Just now":i<60?`${i}m ago`:c<24?`${c}h ago`:w<7?`${w}d ago`:t.toLocaleDateString()}catch{return""}}function Ee(e,t=null){if(t)return t(e);let n=D(e);return n=n.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>"),n=n.replace(/__(.+?)__/g,"<strong>$1</strong>"),n=n.replace(/\*(.+?)\*/g,"<em>$1</em>"),n=n.replace(/_(.+?)_/g,"<em>$1</em>"),n=n.replace(/`(.+?)`/g,"<code>$1</code>"),n=n.replace(/\[(.+?)\]\((.+?)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>'),n=n.replace(/\n/g,"<br>"),n}function xe(e=""){let t=n=>e?`${n}_${e}`:n;return{get(n){try{return localStorage.getItem(t(n))}catch{return null}},set(n,o){try{let i=t(n);o===null?localStorage.removeItem(i):localStorage.setItem(i,o)}catch{}}}}function Re(e="csrftoken"){let t=document.cookie.split(";");for(let o of t){let[i,c]=o.trim().split("=");if(i===e)return decodeURIComponent(c)}let n=document.querySelector('meta[name="csrf-token"]');return n?n.getAttribute("content"):null}function ue(e){if(e===0)return"0 B";let t=1024,n=["B","KB","MB","GB"],o=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,o)).toFixed(1))+" "+n[o]}function pe(e){return e?e.startsWith("image/")?"\u{1F5BC}\uFE0F":e.startsWith("video/")?"\u{1F3AC}":e.startsWith("audio/")?"\u{1F3B5}":e.includes("pdf")?"\u{1F4D5}":e.includes("spreadsheet")||e.includes("excel")?"\u{1F4CA}":e.includes("document")||e.includes("word")?"\u{1F4DD}":e.includes("presentation")||e.includes("powerpoint")?"\u{1F4FD}\uFE0F":e.includes("zip")||e.includes("compressed")?"\u{1F5DC}\uFE0F":(e.includes("text/"),"\u{1F4C4}"):"\u{1F4C4}"}function Ae({config:e,debugMode:t,isExpanded:n,isSpeaking:o,messagesCount:i,isLoading:c,currentAgent:w,onClose:$,onToggleExpand:m,onToggleDebug:f,onToggleTTS:l,onClear:k,onToggleSidebar:p}){let{title:y,primaryColor:g,embedded:u,showConversationSidebar:h,showClearButton:v,showDebugButton:T,enableDebugMode:A,showTTSButton:F,showExpandButton:j,enableTTS:U,elevenLabsApiKey:N,ttsProxyUrl:P}=e,L=N||P;return G`
2
+ <div class="cw-header" style=${{backgroundColor:g}}>
3
+ ${h&&G`
4
+ <button
5
+ class="cw-header-btn cw-hamburger"
6
+ onClick=${p}
7
+ title="Conversations"
8
+ >
9
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
10
+ <line x1="3" y1="6" x2="21" y2="6"></line>
11
+ <line x1="3" y1="12" x2="21" y2="12"></line>
12
+ <line x1="3" y1="18" x2="21" y2="18"></line>
13
+ </svg>
14
+ </button>
15
+ `}
16
+
17
+ <div class="cw-title-container">
18
+ <span class="cw-title">${D(y)}</span>
19
+ ${w&&G`
20
+ <span class="cw-current-agent" title="Currently active agent">
21
+ <span class="cw-agent-indicator">🤖</span>
22
+ <span class="cw-agent-name">${D(w.name||w.key)}</span>
23
+ </span>
24
+ `}
25
+ </div>
26
+
27
+ <div class="cw-header-actions">
28
+ ${v&&G`
29
+ <button
30
+ class="cw-header-btn"
31
+ onClick=${k}
32
+ title="Clear"
33
+ disabled=${c||i===0}
34
+ >🗑️</button>
35
+ `}
36
+
37
+ ${T&&A&&G`
38
+ <button
39
+ class="cw-header-btn ${t?"cw-btn-active":""}"
40
+ onClick=${f}
41
+ title="Debug"
42
+ >🐛</button>
43
+ `}
44
+
45
+ ${F&&L&&G`
46
+ <button
47
+ class="cw-header-btn ${U?"cw-btn-active":""}"
48
+ onClick=${l}
49
+ title="TTS"
50
+ >${U?"\u{1F50A}":"\u{1F507}"}</button>
51
+ `}
52
+
53
+ ${j&&!u&&G`
54
+ <button
55
+ class="cw-header-btn"
56
+ onClick=${m}
57
+ title=${n?"Minimize":"Expand"}
58
+ >${n?"\u2296":"\u2295"}</button>
59
+ `}
60
+
61
+ ${!u&&G`
62
+ <button
63
+ class="cw-header-btn"
64
+ onClick=${$}
65
+ title="Close"
66
+ >✕</button>
67
+ `}
68
+ </div>
69
+ </div>
70
+ `}import{html as Q}from"htm/preact";import{useRef as Fe,useEffect as Pe}from"preact/hooks";import{html as O}from"htm/preact";import{useState as he,useRef as ot,useEffect as rt}from"preact/hooks";function ve({msg:e,show:t,onToggle:n}){return t?O`
71
+ <div class="cw-debug-payload">
72
+ <button class="cw-debug-payload-close" onClick=${n}>×</button>
73
+ <pre class="cw-debug-payload-content">${JSON.stringify(e,null,2)}</pre>
74
+ </div>
75
+ `:O`
76
+ <button
77
+ class="cw-debug-payload-btn"
78
+ onClick=${n}
79
+ title="Show message payload"
80
+ >{ }</button>
81
+ `}function Oe({onEdit:e,onRetry:t,isLoading:n,position:o,showEdit:i=!0}){return n?null:O`
82
+ <div class="cw-message-actions cw-message-actions-${o||"left"}">
83
+ ${i&&O`
84
+ <button
85
+ class="cw-message-action-btn"
86
+ onClick=${e}
87
+ title="Edit message"
88
+ >
89
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
90
+ <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
91
+ </svg>
92
+ </button>
93
+ `}
94
+ <button
95
+ class="cw-message-action-btn"
96
+ onClick=${t}
97
+ title="Retry from here"
98
+ >
99
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
100
+ <path d="M21 2v6h-6"></path>
101
+ <path d="M3 12a9 9 0 0 1 15-6.7L21 8"></path>
102
+ <path d="M3 22v-6h6"></path>
103
+ <path d="M21 12a9 9 0 0 1-15 6.7L3 16"></path>
104
+ </svg>
105
+ </button>
106
+ </div>
107
+ `}function it({initialContent:e,onSave:t,onCancel:n}){let[o,i]=he(e),c=ot(null);return rt(()=>{c.current&&(c.current.focus(),c.current.setSelectionRange(o.length,o.length),c.current.style.height="auto",c.current.style.height=c.current.scrollHeight+"px")},[]),O`
108
+ <div class="cw-inline-edit">
109
+ <textarea
110
+ ref=${c}
111
+ class="cw-inline-edit-input"
112
+ value=${o}
113
+ onInput=${m=>{i(m.target.value),m.target.style.height="auto",m.target.style.height=m.target.scrollHeight+"px"}}
114
+ onKeyDown=${m=>{m.key==="Enter"&&!m.shiftKey?(m.preventDefault(),o.trim()&&t(o.trim())):m.key==="Escape"&&n()}}
115
+ rows="1"
116
+ />
117
+ <div class="cw-inline-edit-actions">
118
+ <button
119
+ class="cw-inline-edit-btn cw-inline-edit-cancel"
120
+ onClick=${n}
121
+ title="Cancel (Esc)"
122
+ >Cancel</button>
123
+ <button
124
+ class="cw-inline-edit-btn cw-inline-edit-save"
125
+ onClick=${()=>o.trim()&&t(o.trim())}
126
+ disabled=${!o.trim()}
127
+ title="Save & Resend (Enter)"
128
+ >Save & Send</button>
129
+ </div>
130
+ </div>
131
+ `}function De({msg:e,debugMode:t,markdownParser:n,onEdit:o,onRetry:i,isLoading:c,messageIndex:w}){let[$,m]=he(!1),[f,l]=he(!1),[k,p]=he(!1),y=e.role==="user",g=e.role==="system",u=e.type==="tool_call",h=e.type==="tool_result",v=e.type==="error",T=e.type==="sub_agent_start",A=e.type==="sub_agent_end",F=e.type==="agent_context";if(g&&!t)return null;if(T||A||F)return O`
132
+ <div class="cw-agent-context ${T?"cw-agent-delegating":""} ${A?"cw-agent-returned":""}" style="position: relative;">
133
+ <span class="cw-agent-context-icon">${T?"\u{1F517}":A?"\u2713":"\u{1F916}"}</span>
134
+ <span class="cw-agent-context-text">${e.content}</span>
135
+ ${e.metadata?.agentName&&O`
136
+ <span class="cw-agent-context-name">${e.metadata.agentName}</span>
137
+ `}
138
+ ${t&&O`<${ve} msg=${e} show=${f} onToggle=${()=>l(!f)} />`}
139
+ </div>
140
+ `;if(u||h){let b=e.metadata?.arguments||e.metadata?.result,M=r=>{if(typeof r=="string")try{return JSON.stringify(JSON.parse(r),null,2)}catch{return r}return JSON.stringify(r,null,2)};return O`
141
+ <div class="cw-tool-message ${h?"cw-tool-result":"cw-tool-call"}" style="position: relative;">
142
+ <span class="cw-tool-label" onClick=${()=>b&&m(!$)}>
143
+ ${e.content}
144
+ ${b&&O`<span class="cw-tool-expand">${$?"\u25BC":"\u25B6"}</span>`}
145
+ </span>
146
+ ${$&&b&&O`
147
+ <pre class="cw-tool-details">${D(M(u?e.metadata.arguments:e.metadata.result))}</pre>
148
+ `}
149
+ ${t&&O`<${ve} msg=${e} show=${f} onToggle=${()=>l(!f)} />`}
150
+ </div>
151
+ `}let j=["cw-message",y&&"cw-message-user",v&&"cw-message-error"].filter(Boolean).join(" "),U=`cw-message-row ${y?"cw-message-row-user":""}`,N=e.role==="assistant"?Ee(e.content,n):D(e.content),P=e.files&&e.files.length>0,L=()=>P?O`
152
+ <div class="cw-message-attachments">
153
+ ${e.files.map(b=>b.type&&b.type.startsWith("image/")?O`
154
+ <a class="cw-attachment-thumbnail" href=${b.url} target="_blank" title=${b.name}>
155
+ <img src=${b.url} alt=${b.name} />
156
+ </a>
157
+ `:O`
158
+ <a class="cw-attachment-file" href=${b.url} target="_blank" title=${b.name}>
159
+ <span class="cw-attachment-icon">${pe(b.type)}</span>
160
+ <span class="cw-attachment-info">
161
+ <span class="cw-attachment-name">${b.name}</span>
162
+ <span class="cw-attachment-size">${ue(b.size)}</span>
163
+ </span>
164
+ </a>
165
+ `)}
166
+ </div>
167
+ `:null,z=b=>{p(!1),o&&o(w,b)},H=()=>{i&&i(w)};if(y&&k)return O`
168
+ <div class=${U} style="position: relative;">
169
+ ${L()}
170
+ <${it}
171
+ initialContent=${e.content}
172
+ onSave=${z}
173
+ onCancel=${()=>p(!1)}
174
+ />
175
+ </div>
176
+ `;let s=y&&o&&i,C=e.role==="assistant"&&i&&!c;return O`
177
+ <div class="${U} ${s||C?"cw-message-row-with-actions":""}">
178
+ ${L()}
179
+ ${s&&O`
180
+ <div class="cw-user-actions-wrapper">
181
+ <${Oe}
182
+ onEdit=${()=>p(!0)}
183
+ onRetry=${H}
184
+ isLoading=${c}
185
+ position="left"
186
+ showEdit=${!0}
187
+ />
188
+ <div class=${j} dangerouslySetInnerHTML=${{__html:N}} />
189
+ </div>
190
+ `}
191
+ ${!s&&O`
192
+ <div class=${j} dangerouslySetInnerHTML=${{__html:N}} />
193
+ `}
194
+ ${C&&O`
195
+ <${Oe}
196
+ onRetry=${H}
197
+ isLoading=${c}
198
+ position="right"
199
+ showEdit=${!1}
200
+ />
201
+ `}
202
+ ${t&&O`<${ve} msg=${e} show=${f} onToggle=${()=>l(!f)} />`}
203
+ </div>
204
+ `}function Le({messages:e,isLoading:t,hasMoreMessages:n,loadingMoreMessages:o,onLoadMore:i,onEditMessage:c,onRetryMessage:w,debugMode:$,markdownParser:m,emptyStateTitle:f,emptyStateMessage:l}){let k=Fe(null),p=Fe(!0),y=u=>{let h=u.target,v=h.scrollHeight-h.scrollTop-h.clientHeight<100;if(p.current=v,h.scrollTop<50&&n&&!o){let T=h.scrollHeight;i().then(()=>{let A=h.scrollHeight;h.scrollTop=A-T+h.scrollTop})}};Pe(()=>{let u=k.current;u&&p.current&&requestAnimationFrame(()=>{u.scrollTop=u.scrollHeight})},[e,t]),Pe(()=>{let u=k.current;u&&e.length<=2&&(p.current=!0,requestAnimationFrame(()=>{u.scrollTop=u.scrollHeight}))},[e.length]);let g=e.length===0;return Q`
205
+ <div class="cw-messages" ref=${k} onScroll=${y}>
206
+ ${g&&Q`
207
+ <div class="cw-empty-state">
208
+ <svg class="cw-empty-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
209
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
210
+ </svg>
211
+ <h3>${D(f)}</h3>
212
+ <p>${D(l)}</p>
213
+ </div>
214
+ `}
215
+
216
+ ${!g&&n&&Q`
217
+ <div class="cw-load-more" onClick=${i}>
218
+ ${o?Q`<span class="cw-spinner"></span><span>Loading...</span>`:Q`<span>↑ Scroll up or click to load older messages</span>`}
219
+ </div>
220
+ `}
221
+
222
+ ${e.map((u,h)=>Q`
223
+ <${De}
224
+ key=${u.id}
225
+ msg=${u}
226
+ messageIndex=${h}
227
+ debugMode=${$}
228
+ markdownParser=${m}
229
+ onEdit=${c}
230
+ onRetry=${w}
231
+ isLoading=${t}
232
+ />
233
+ `)}
234
+
235
+ ${t&&Q`
236
+ <div class="cw-message-row">
237
+ <div class="cw-typing">
238
+ <span class="cw-spinner"></span>
239
+ <span>Thinking...</span>
240
+ </div>
241
+ </div>
242
+ `}
243
+ </div>
244
+ `}import{html as V}from"htm/preact";import{useState as ne,useRef as me,useEffect as ke}from"preact/hooks";var be=typeof window<"u"?window.SpeechRecognition||window.webkitSpeechRecognition:null;function Ke({onSend:e,onCancel:t,isLoading:n,placeholder:o,primaryColor:i,enableVoice:c=!0,enableFiles:w=!0}){let[$,m]=ne(""),[f,l]=ne([]),[k,p]=ne(!1),[y,g]=ne(!1),[u]=ne(()=>!!be),h=me(null),v=me(null),T=me(null),A=me(!1);ke(()=>{!n&&h.current&&h.current.focus()},[n]),ke(()=>{h.current&&(h.current.style.height="auto",h.current.style.height=Math.min(h.current.scrollHeight,150)+"px")},[$]),ke(()=>()=>{A.current=!1,T.current&&T.current.abort()},[]);let F=r=>{r.preventDefault(),($.trim()||f.length>0)&&!n&&(e($,f),m(""),l([]),h.current&&(h.current.style.height="auto"),v.current&&(v.current.value=""))},j=r=>{let I=Array.from(r.target.files||[]);I.length>0&&l(R=>[...R,...I])},U=r=>{l(I=>I.filter((R,a)=>a!==r))},N=r=>{r.preventDefault(),v.current&&!n&&v.current.click()},P=r=>{r.key==="Enter"&&!r.shiftKey&&(r.preventDefault(),F(r))},L=r=>{n&&t&&(r.preventDefault(),t())},z=()=>{if(!be||n)return;A.current=!0;let r=new be;r.continuous=!0,r.interimResults=!0,r.lang=navigator.language||"en-US";let I=$,R="";r.onstart=()=>{g(!0)},r.onresult=a=>{R="";for(let d=a.resultIndex;d<a.results.length;d++){let E=a.results[d][0].transcript;a.results[d].isFinal?I+=(I?" ":"")+E:R+=E}m(I+(R?" "+R:""))},r.onerror=a=>{if(a.error==="no-speech"||a.error==="aborted"){console.log("[ChatWidget] Speech recognition:",a.error,"- continuing...");return}console.warn("[ChatWidget] Speech recognition error:",a.error),A.current=!1,g(!1),m(I||$)},r.onend=()=>{if(A.current){console.log("[ChatWidget] Recognition paused, restarting...");try{r.start();return}catch(a){console.warn("[ChatWidget] Could not restart recognition:",a)}}g(!1),I&&m(I),T.current=null},T.current=r,r.start()},H=()=>{A.current=!1,T.current&&T.current.stop()},s=r=>{r.preventDefault(),y?H():z()},_=V`
245
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor">
246
+ <rect x="2" y="2" width="10" height="10" rx="1" />
247
+ </svg>
248
+ `,C=V`
249
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
250
+ <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"></path>
251
+ <path d="M19 10v2a7 7 0 0 1-14 0v-2"></path>
252
+ <line x1="12" y1="19" x2="12" y2="23"></line>
253
+ <line x1="8" y1="23" x2="16" y2="23"></line>
254
+ </svg>
255
+ `,S=V`
256
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
257
+ <path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
258
+ </svg>
259
+ `,b=c&&u,M=w;return V`
260
+ <form class="cw-input-form" onSubmit=${F}>
261
+ <input
262
+ type="file"
263
+ ref=${v}
264
+ style="display: none"
265
+ multiple
266
+ onChange=${j}
267
+ />
268
+ ${f.length>0&&V`
269
+ <div class="cw-file-chips">
270
+ ${f.map((r,I)=>V`
271
+ <div class="cw-file-chip" key=${I}>
272
+ <span class="cw-file-chip-icon">${pe(r.type)}</span>
273
+ <span class="cw-file-chip-name" title=${r.name}>${r.name.length>20?r.name.substring(0,17)+"...":r.name}</span>
274
+ <span class="cw-file-chip-size">(${ue(r.size)})</span>
275
+ <button
276
+ type="button"
277
+ class="cw-file-chip-remove"
278
+ onClick=${()=>U(I)}
279
+ title="Remove file"
280
+ >×</button>
281
+ </div>
282
+ `)}
283
+ </div>
284
+ `}
285
+ <textarea
286
+ ref=${h}
287
+ class="cw-input"
288
+ placeholder=${D(o)}
289
+ value=${$}
290
+ onInput=${r=>m(r.target.value)}
291
+ onKeyDown=${P}
292
+ disabled=${n}
293
+ rows="1"
294
+ />
295
+ ${M&&V`
296
+ <button
297
+ type="button"
298
+ class="cw-attach-btn"
299
+ onClick=${N}
300
+ disabled=${n}
301
+ title="Attach files"
302
+ >
303
+ ${S}
304
+ </button>
305
+ `}
306
+ ${b&&V`
307
+ <button
308
+ type="button"
309
+ class=${`cw-voice-btn ${y?"cw-voice-btn-recording":""}`}
310
+ onClick=${s}
311
+ disabled=${n}
312
+ title=${y?"Stop recording":"Voice input"}
313
+ >
314
+ ${C}
315
+ </button>
316
+ `}
317
+ <button
318
+ type=${n?"button":"submit"}
319
+ class=${`cw-send-btn ${n?"cw-send-btn-loading":""} ${n&&k?"cw-send-btn-stop":""}`}
320
+ style=${{backgroundColor:n&&k?"#dc2626":i}}
321
+ onClick=${L}
322
+ onMouseEnter=${()=>p(!0)}
323
+ onMouseLeave=${()=>p(!1)}
324
+ title=${n?"Stop":"Send"}
325
+ >
326
+ ${n?k?_:V`<span class="cw-spinner"></span>`:"\u27A4"}
327
+ </button>
328
+ </form>
329
+ `}import{html as fe}from"htm/preact";function Ne({isOpen:e,conversations:t,conversationsLoading:n,currentConversationId:o,onClose:i,onNewConversation:c,onSwitchConversation:w}){return fe`
330
+ <div class="cw-sidebar ${e?"cw-sidebar-open":""}">
331
+ <div class="cw-sidebar-header">
332
+ <span>Conversations</span>
333
+ <button class="cw-sidebar-close" onClick=${i}>✕</button>
334
+ </div>
335
+
336
+ <button class="cw-new-conversation" onClick=${c}>
337
+ <span>+ New Conversation</span>
338
+ </button>
339
+
340
+ <div class="cw-conversation-list">
341
+ ${n&&fe`
342
+ <div class="cw-sidebar-loading">
343
+ <span class="cw-spinner"></span>
344
+ </div>
345
+ `}
346
+
347
+ ${!n&&t.length===0&&fe`
348
+ <div class="cw-sidebar-empty">No conversations yet</div>
349
+ `}
350
+
351
+ ${t.map($=>fe`
352
+ <div
353
+ key=${$.id}
354
+ class="cw-conversation-item ${$.id===o?"cw-conversation-active":""}"
355
+ onClick=${()=>w($.id)}
356
+ >
357
+ <div class="cw-conversation-title">${D($.title||"Untitled")}</div>
358
+ <div class="cw-conversation-date">${Ie($.updatedAt||$.createdAt)}</div>
359
+ </div>
360
+ `)}
361
+ </div>
362
+ </div>
363
+
364
+ <div
365
+ class="cw-sidebar-overlay ${e?"cw-sidebar-overlay-visible":""}"
366
+ onClick=${i}
367
+ />
368
+ `}import{html as ge}from"htm/preact";import{useState as lt}from"preact/hooks";function He({availableModels:e,selectedModel:t,onSelectModel:n,disabled:o}){let[i,c]=lt(!1);if(!e||e.length===0)return null;let $=e.find(l=>l.id===t)?.name||"Select Model",m=()=>{o||c(!i)},f=l=>{n(l),c(!1)};return ge`
369
+ <div class="cw-model-selector">
370
+ <button
371
+ class="cw-model-btn"
372
+ onClick=${m}
373
+ disabled=${o}
374
+ title="Select Model"
375
+ >
376
+ <span class="cw-model-icon">🤖</span>
377
+ <span class="cw-model-name">${D($)}</span>
378
+ <span class="cw-model-chevron">${i?"\u25B2":"\u25BC"}</span>
379
+ </button>
380
+
381
+ ${i&&ge`
382
+ <div class="cw-model-dropdown">
383
+ ${e.map(l=>ge`
384
+ <button
385
+ key=${l.id}
386
+ class="cw-model-option ${l.id===t?"cw-model-option-selected":""}"
387
+ onClick=${()=>f(l.id)}
388
+ >
389
+ <span class="cw-model-option-name">${D(l.name)}</span>
390
+ <span class="cw-model-option-provider">${D(l.provider)}</span>
391
+ ${l.description&&ge`
392
+ <span class="cw-model-option-desc">${D(l.description)}</span>
393
+ `}
394
+ </button>
395
+ `)}
396
+ </div>
397
+ `}
398
+ </div>
399
+ `}import{html as q}from"htm/preact";import{useState as Be,useCallback as se}from"preact/hooks";var ct={not_started:"\u25CB",in_progress:"\u25D0",complete:"\u25CF",cancelled:"\u2298"},dt={not_started:"Not Started",in_progress:"In Progress",complete:"Complete",cancelled:"Cancelled"};function ut({task:e,onUpdate:t,onRemove:n,depth:o=0}){let[i,c]=Be(!1),[w,$]=Be(e.name),m=se(()=>{let p={not_started:"in_progress",in_progress:"complete",complete:"not_started",cancelled:"not_started"};t(e.id,{state:p[e.state]||"not_started"})},[e,t]),f=se(()=>{w.trim()&&w!==e.name&&t(e.id,{name:w.trim()}),c(!1)},[e,w,t]),l=se(p=>{p.key==="Enter"&&f(),p.key==="Escape"&&($(e.name),c(!1))},[f,e.name]),k=`cw-task-state-${e.state.replace("_","-")}`;return q`
400
+ <div class="cw-task-item ${k}" style=${{paddingLeft:`${o*16+8}px`}}>
401
+ <button
402
+ class="cw-task-state-btn"
403
+ onClick=${m}
404
+ title=${dt[e.state]}
405
+ >
406
+ ${ct[e.state]}
407
+ </button>
408
+
409
+ ${i?q`
410
+ <input
411
+ type="text"
412
+ class="cw-task-edit-input"
413
+ value=${w}
414
+ onInput=${p=>$(p.target.value)}
415
+ onBlur=${f}
416
+ onKeyDown=${l}
417
+ autoFocus
418
+ />
419
+ `:q`
420
+ <span
421
+ class="cw-task-name"
422
+ onClick=${()=>c(!0)}
423
+ title="Click to edit"
424
+ >
425
+ ${e.name}
426
+ </span>
427
+ `}
428
+
429
+ <button
430
+ class="cw-task-remove-btn"
431
+ onClick=${()=>n(e.id)}
432
+ title="Remove task"
433
+ >
434
+ ×
435
+ </button>
436
+ </div>
437
+ `}function Ue({tasks:e,progress:t,isLoading:n,error:o,onUpdate:i,onRemove:c,onClear:w,onRefresh:$}){let m=se(k=>{let p=new Map,y=[];return k.forEach(g=>{p.set(g.id,{...g,children:[]})}),k.forEach(g=>{let u=p.get(g.id);g.parent_id&&p.has(g.parent_id)?p.get(g.parent_id).children.push(u):y.push(u)}),y},[]),f=se((k,p=0)=>q`
438
+ <${ut}
439
+ key=${k.id}
440
+ task=${k}
441
+ depth=${p}
442
+ onUpdate=${i}
443
+ onRemove=${c}
444
+ />
445
+ ${k.children?.map(y=>f(y,p+1))}
446
+ `,[i,c]),l=m(e);return n&&e.length===0?q`<div class="cw-tasks-loading">Loading tasks...</div>`:q`
447
+ <div class="cw-tasks-container">
448
+ <div class="cw-tasks-header">
449
+ <div class="cw-tasks-progress">
450
+ <span class="cw-tasks-progress-text">
451
+ ${t.completed}/${t.total} complete
452
+ </span>
453
+ <div class="cw-tasks-progress-bar">
454
+ <div
455
+ class="cw-tasks-progress-fill"
456
+ style=${{width:`${t.percent_complete}%`}}
457
+ />
458
+ </div>
459
+ </div>
460
+ <div class="cw-tasks-actions">
461
+ <button class="cw-tasks-action-btn" onClick=${$} title="Refresh">↻</button>
462
+ ${e.length>0&&q`
463
+ <button class="cw-tasks-action-btn" onClick=${w} title="Clear all">🗑</button>
464
+ `}
465
+ </div>
466
+ </div>
467
+
468
+ ${o&&q`<div class="cw-tasks-error">${o}</div>`}
469
+
470
+ <div class="cw-tasks-list">
471
+ ${l.length===0?q`
472
+ <div class="cw-tasks-empty">
473
+ <p>No tasks yet</p>
474
+ <p class="cw-tasks-empty-hint">Tasks will appear here when the agent creates them</p>
475
+ </div>
476
+ `:l.map(k=>f(k))}
477
+ </div>
478
+ </div>
479
+ `}import{useState as Y,useCallback as X,useRef as We,useEffect as je}from"preact/hooks";function Je(e,t,n){let[o,i]=Y([]),[c,w]=Y(!1),[$,m]=Y(null),[f,l]=Y(()=>n?.get(e.conversationIdKey)||null),[k,p]=Y(!1),[y,g]=Y(!1),[u,h]=Y(0),v=We(null),T=We(null);je(()=>{f&&n?.set(e.conversationIdKey,f)},[f,e.conversationIdKey,n]);let A=X(async(s,_,C)=>{v.current&&v.current.close();let S=e.apiPaths.runEvents.replace("{runId}",s),b=`${e.backendUrl}${S}`;_&&(b+=`?anonymous_token=${encodeURIComponent(_)}`);let M=new EventSource(b);v.current=M;let r="";M.addEventListener("assistant.message",R=>{try{let a=JSON.parse(R.data);e.onEvent&&e.onEvent("assistant.message",a.payload);let d=a.payload.content;d&&(r+=d,i(E=>{let K=E[E.length-1];return K?.role==="assistant"&&K.id.startsWith("assistant-stream-")?[...E.slice(0,-1),{...K,content:r}]:[...E,{id:"assistant-stream-"+Date.now(),role:"assistant",content:r,timestamp:new Date,type:"message"}]}))}catch(a){console.error("[ChatWidget] Parse error:",a)}}),M.addEventListener("tool.call",R=>{try{let a=JSON.parse(R.data);e.onEvent&&e.onEvent("tool.call",a.payload),i(d=>[...d,{id:"tool-call-"+Date.now(),role:"assistant",content:`\u{1F527} ${a.payload.name}`,timestamp:new Date,type:"tool_call",metadata:{toolName:a.payload.name,arguments:a.payload.arguments,toolCallId:a.payload.id}}])}catch(a){console.error("[ChatWidget] Parse error:",a)}}),M.addEventListener("tool.result",R=>{try{let a=JSON.parse(R.data);e.onEvent&&e.onEvent("tool.result",a.payload);let d=a.payload.result,E=d?.error;i(K=>[...K,{id:"tool-result-"+Date.now(),role:"system",content:E?`\u274C ${d.error}`:"\u2713 Done",timestamp:new Date,type:"tool_result",metadata:{toolName:a.payload.name,result:d,toolCallId:a.payload.tool_call_id}}])}catch(a){console.error("[ChatWidget] Parse error:",a)}}),M.addEventListener("custom",R=>{try{let a=JSON.parse(R.data);e.onEvent&&e.onEvent("custom",a.payload),a.payload?.type==="ui_control"&&e.onUIControl&&e.onUIControl(a.payload),a.payload?.type==="agent_context"&&i(d=>[...d,{id:"agent-context-"+Date.now(),role:"system",content:`\u{1F517} ${a.payload.agent_name||"Sub-agent"} is now handling this request`,timestamp:new Date,type:"agent_context",metadata:{agentKey:a.payload.agent_key,agentName:a.payload.agent_name,action:a.payload.action}}])}catch(a){console.error("[ChatWidget] Parse error:",a)}}),M.addEventListener("sub_agent.start",R=>{try{let a=JSON.parse(R.data);e.onEvent&&e.onEvent("sub_agent.start",a.payload),i(d=>[...d,{id:"sub-agent-start-"+Date.now(),role:"system",content:`\u{1F517} Delegating to ${a.payload.agent_name||a.payload.sub_agent_key||"sub-agent"}...`,timestamp:new Date,type:"sub_agent_start",metadata:{subAgentKey:a.payload.sub_agent_key,agentName:a.payload.agent_name,invocationMode:a.payload.invocation_mode}}])}catch(a){console.error("[ChatWidget] Parse error:",a)}}),M.addEventListener("sub_agent.end",R=>{try{let a=JSON.parse(R.data);e.onEvent&&e.onEvent("sub_agent.end",a.payload),i(d=>[...d,{id:"sub-agent-end-"+Date.now(),role:"system",content:`\u2713 ${a.payload.agent_name||"Sub-agent"} completed`,timestamp:new Date,type:"sub_agent_end",metadata:{subAgentKey:a.payload.sub_agent_key,agentName:a.payload.agent_name}}])}catch(a){console.error("[ChatWidget] Parse error:",a)}});let I=R=>{try{let a=JSON.parse(R.data);if(e.onEvent&&e.onEvent(a.type,a.payload),a.type==="run.failed"){let d=a.payload.error||"Agent run failed";m(d),i(E=>[...E,{id:"error-"+Date.now(),role:"system",content:`\u274C Error: ${d}`,timestamp:new Date,type:"error"}])}}catch(a){console.error("[ChatWidget] Parse error:",a)}w(!1),M.close(),v.current=null,r&&C&&C(r)};M.addEventListener("run.succeeded",I),M.addEventListener("run.failed",I),M.addEventListener("run.cancelled",I),M.addEventListener("run.timed_out",I),M.onerror=()=>{w(!1),M.close(),v.current=null}},[e]),F=X(async(s,_={},C={})=>{if(!s.trim()||c)return;let S=[],b={};typeof _=="function"?b={onAssistantMessage:_}:Array.isArray(_)?(S=_,b=C):b=_||{};let{model:M,onAssistantMessage:r,supersedeFromMessageIndex:I}=b;w(!0),m(null);let R={id:de(),role:"user",content:s.trim(),timestamp:new Date,type:"message",files:S.length>0?S.map(a=>({name:a.name,size:a.size,type:a.type})):void 0};i(a=>[...a,R]);try{let a=await t.getOrCreateSession(),d;if(S.length>0){let B=e.apiCaseStyle!=="camel",_e=ie=>B?we(ie):ie,Z=new FormData;Z.append(_e("agentKey"),e.agentKey),f&&Z.append(_e("conversationId"),f),Z.append("messages",JSON.stringify([{role:"user",content:s.trim()}])),Z.append("metadata",JSON.stringify(B?{...e.metadata,journey_type:e.defaultJourneyType}:{...e.metadata,journeyType:e.defaultJourneyType})),M&&Z.append("model",M),S.forEach(ie=>{Z.append("files",ie)}),d=t.getFetchOptions({method:"POST",body:Z},a)}else{let B=t.transformRequest({agentKey:e.agentKey,conversationId:f,messages:[{role:"user",content:s.trim()}],metadata:{...e.metadata,journeyType:e.defaultJourneyType},...M&&{model:M},...I!==void 0&&{supersedeFromMessageIndex:I}});d=t.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(B)},a)}let E=await fetch(`${e.backendUrl}${e.apiPaths.runs}`,d),K=a;if(E.status===401){t.clearSession();let B=await t.getOrCreateSession(!0);B&&(K=B,S.length>0?d=t.getFetchOptions({method:"POST",body:d.body},B):d=t.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json"},body:d.body},B),E=await fetch(`${e.backendUrl}${e.apiPaths.runs}`,d))}if(!E.ok){let B=await E.json().catch(()=>({}));throw new Error(B.error||B.detail||`HTTP ${E.status}`)}let oe=await E.json(),re=t.transformResponse(oe);T.current=re.id,!f&&re.conversationId&&l(re.conversationId),await A(re.id,K,r)}catch(a){m(a.message||"Failed to send message"),w(!1)}finally{T.current=null}},[e,t,f,c,A]),j=X(async()=>{let s=T.current;if(!(!s||!c))try{let _=e.apiPaths.cancelRun?e.apiPaths.cancelRun.replace("{runId}",s):`${e.apiPaths.runs}${s}/cancel/`;(await fetch(`${e.backendUrl}${_}`,t.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json"}}))).ok&&(v.current&&(v.current.close(),v.current=null),w(!1),T.current=null,i(S=>[...S,{id:"cancelled-"+Date.now(),role:"system",content:"\u23F9 Run cancelled",timestamp:new Date,type:"cancelled"}]))}catch(_){console.error("[ChatWidget] Failed to cancel run:",_)}},[e,t,c]),U=X(()=>{i([]),l(null),m(null),p(!1),h(0),n?.set(e.conversationIdKey,null)},[e.conversationIdKey,n]),N=s=>{let _={id:de(),role:s.role,timestamp:s.timestamp?new Date(s.timestamp):new Date};if(s.role==="tool")return{..._,role:"system",content:"\u2713 Done",type:"tool_result",metadata:{result:s.content,toolCallId:s.toolCallId}};if(s.role==="assistant"&&s.toolCalls&&s.toolCalls.length>0)return s.toolCalls.map(S=>({id:de(),role:"assistant",content:`\u{1F527} ${S.function?.name||S.name||"tool"}`,timestamp:_.timestamp,type:"tool_call",metadata:{toolName:S.function?.name||S.name,arguments:S.function?.arguments||S.arguments,toolCallId:S.id}}));let C=typeof s.content=="string"?s.content:JSON.stringify(s.content);return s.role==="assistant"&&!C?.trim()?null:{..._,content:C,type:"message"}},P=X(async s=>{w(!0),i([]),l(s);try{let _=await t.getOrCreateSession(),S=`${e.backendUrl}${e.apiPaths.conversations}${s}/?limit=10&offset=0`,b=await fetch(S,t.getFetchOptions({method:"GET"},_));if(b.ok){let M=await b.json(),r=t.transformResponse(M);r.messages&&i(r.messages.flatMap(N).filter(Boolean)),p(r.hasMore||!1),h(r.messages?.length||0)}else b.status===404&&(l(null),n?.set(e.conversationIdKey,null))}catch(_){console.error("[ChatWidget] Failed to load conversation:",_)}finally{w(!1)}},[e,t,n]),L=X(async()=>{if(!(!f||y||!k)){g(!0);try{let s=await t.getOrCreateSession(),C=`${e.backendUrl}${e.apiPaths.conversations}${f}/?limit=10&offset=${u}`,S=await fetch(C,t.getFetchOptions({method:"GET"},s));if(S.ok){let b=await S.json(),M=t.transformResponse(b);if(M.messages?.length>0){let r=M.messages.flatMap(N).filter(Boolean);i(I=>[...r,...I]),h(I=>I+M.messages.length),p(M.hasMore||!1)}else p(!1)}}catch(s){console.error("[ChatWidget] Failed to load more messages:",s)}finally{g(!1)}}},[e,t,f,u,y,k]),z=X(async(s,_,C={})=>{if(c)return;let S=o[s];if(!S||S.role!=="user")return;let b=o.slice(0,s);i(b),await F(_,{...C,supersedeFromMessageIndex:s})},[o,c,F]),H=X(async(s,_={})=>{if(c)return;let C=o[s];if(!C)return;let S=s,b=C;if(C.role==="assistant"){for(let r=s-1;r>=0;r--)if(o[r].role==="user"){S=r,b=o[r];break}if(b.role!=="user")return}else if(C.role!=="user")return;let M=o.slice(0,S);i(M),await F(b.content,{..._,supersedeFromMessageIndex:S})},[o,c,F]);return je(()=>()=>{v.current&&v.current.close()},[]),{messages:o,isLoading:c,error:$,conversationId:f,hasMoreMessages:k,loadingMoreMessages:y,sendMessage:F,cancelRun:j,clearMessages:U,loadConversation:P,loadMoreMessages:L,setConversationId:l,editMessage:z,retryMessage:H}}import{useState as $e,useEffect as pt,useCallback as ze}from"preact/hooks";function Ve(e,t,n){let[o,i]=$e([]),[c,w]=$e(null),[$,m]=$e(null),[f,l]=$e(!1);pt(()=>{(async()=>{if(e.showModelSelector){l(!0);try{let g=await fetch(`${e.backendUrl}${e.apiPaths.models}`,t.getFetchOptions({method:"GET"}));if(g.ok){let u=await g.json(),h=u.models||[];i(h),m(u.default);let v=n?.get(e.modelKey);v&&h.some(T=>T.id===v)?w(v):w(u.default)}}catch(g){console.warn("[ChatWidget] Failed to load models:",g)}finally{l(!1)}}})()},[e.backendUrl,e.apiPaths.models,e.showModelSelector,e.modelKey,t,n]);let k=ze(y=>{w(y),n?.set(e.modelKey,y)},[e.modelKey,n]),p=ze(()=>o.find(y=>y.id===c)||null,[o,c]);return{availableModels:o,selectedModel:c,defaultModel:$,isLoading:f,selectModel:k,getSelectedModelInfo:p}}import{useState as Ce,useCallback as ee}from"preact/hooks";function qe(e,t){let[n,o]=Ce(null),[i,c]=Ce(!1),[w,$]=Ce(null),m=e.apiPaths?.tasks||"/api/agent/tasks/",f=ee(async()=>{c(!0),$(null);try{let u=`${e.backendUrl}${m}`,h=await fetch(u,t.getFetchOptions({method:"GET"}));if(h.ok){let v=await h.json();o(v)}else{let v=await h.json().catch(()=>({}));$(v.error||"Failed to load tasks")}}catch(u){console.error("[useTasks] Failed to load task list:",u),$("Failed to load tasks")}finally{c(!1)}},[e.backendUrl,m,t]),l=ee(async u=>{if(!n)return null;try{let h=`${e.backendUrl}${m}${n.id}/add_task/`,v=await fetch(h,t.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(u)}));if(v.ok){let T=await v.json();return await f(),T}else{let T=await v.json().catch(()=>({}));return $(T.error||"Failed to add task"),null}}catch(h){return console.error("[useTasks] Failed to add task:",h),$("Failed to add task"),null}},[e.backendUrl,m,n,t,f]),k=ee(async(u,h)=>{if(!n)return null;try{let v=`${e.backendUrl}${m}${n.id}/update_task/${u}/`,T=await fetch(v,t.getFetchOptions({method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(h)}));if(T.ok){let A=await T.json();return await f(),A}else{let A=await T.json().catch(()=>({}));return $(A.error||"Failed to update task"),null}}catch(v){return console.error("[useTasks] Failed to update task:",v),$("Failed to update task"),null}},[e.backendUrl,m,n,t,f]),p=ee(async u=>{if(!n)return!1;try{let h=`${e.backendUrl}${m}${n.id}/remove_task/${u}/`,v=await fetch(h,t.getFetchOptions({method:"DELETE"}));if(v.ok)return await f(),!0;{let T=await v.json().catch(()=>({}));return $(T.error||"Failed to remove task"),!1}}catch(h){return console.error("[useTasks] Failed to remove task:",h),$("Failed to remove task"),!1}},[e.backendUrl,m,n,t,f]),y=ee(async()=>{if(!n)return!1;try{let u=`${e.backendUrl}${m}${n.id}/clear/`,h=await fetch(u,t.getFetchOptions({method:"POST"}));if(h.ok)return await f(),!0;{let v=await h.json().catch(()=>({}));return $(v.error||"Failed to clear tasks"),!1}}catch(u){return console.error("[useTasks] Failed to clear tasks:",u),$("Failed to clear tasks"),!1}},[e.backendUrl,m,n,t,f]),g=ee(()=>$(null),[]);return{taskList:n,tasks:n?.tasks||[],progress:n?.progress||{total:0,completed:0,percent_complete:0},isLoading:i,error:w,loadTaskList:f,addTask:l,updateTask:k,removeTask:p,clearTasks:y,clearError:g}}function Ge(e,t,n){let o=l=>!l||typeof l!="object"||e.apiCaseStyle==="camel"?l:ce(l),i=l=>!l||typeof l!="object"||e.apiCaseStyle==="snake"?l:le(l),c=()=>e.authStrategy?e.authStrategy:e.authToken?"token":e.apiPaths.anonymousSession||e.anonymousSessionEndpoint?"anonymous":"none",w=(l=null)=>{let k=c(),p={},y=l||e.authToken||t().authToken;if(k==="token"&&y){let g=e.authHeader||"Authorization",u=e.authTokenPrefix!==void 0?e.authTokenPrefix:"Token";p[g]=u?`${u} ${y}`:y}else if(k==="jwt"&&y){let g=e.authHeader||"Authorization",u=e.authTokenPrefix!==void 0?e.authTokenPrefix:"Bearer";p[g]=u?`${u} ${y}`:y}else if(k==="anonymous"&&y){let g=e.authHeader||e.anonymousTokenHeader||"X-Anonymous-Token";p[g]=y}if(k==="session"){let g=Re(e.csrfCookieName);g&&(p["X-CSRFToken"]=g)}return p};return{getAuthStrategy:c,getAuthHeaders:w,getFetchOptions:(l={},k=null)=>{let p=c(),y={...l},g=w(k);return console.log("[ChatWidget] getFetchOptions - strategy:",p,"overrideToken:",k,"authHeaders:",g),y.headers={...y.headers,...g},p==="session"&&(y.credentials="include"),y},getOrCreateSession:async(l=!1)=>{let k=c(),p=t(),y=e.anonymousTokenKey||e.sessionTokenKey;if(k!=="anonymous")return e.authToken||p.authToken;if(!l){if(p.authToken)return p.authToken;let g=p.storage?.get(y);if(g)return n(u=>({...u,authToken:g})),g}try{let g=e.anonymousSessionEndpoint||e.apiPaths.anonymousSession,u=await fetch(`${e.backendUrl}${g}`,{method:"POST",headers:{"Content-Type":"application/json"}});if(u.ok){let h=await u.json();return n(v=>({...v,authToken:h.token})),p.storage?.set(y,h.token),h.token}}catch(g){console.warn("[ChatWidget] Failed to create session:",g)}return null},clearSession:()=>{let l=e.anonymousTokenKey||e.sessionTokenKey,k=t();n(p=>({...p,authToken:null})),k.storage?.set(l,null)},transformRequest:o,transformResponse:i}}function Ze({config:e,onStateChange:t,markdownParser:n,apiRef:o}){let[i,c]=W(e.embedded||e.forceOpen===!0),[w,$]=W(!1),[m,f]=W(!1),[l,k]=W(!1),[p,y]=W([]),[g,u]=W("chat"),[h,v]=W(!1),[T,A]=W(e.enableTTS),[F,j]=W(!1),[U,N]=W(null);ae(()=>{e.forceOpen!==void 0&&c(e.forceOpen)},[e.forceOpen]);let P=Xe(()=>xe(e.containerId),[e.containerId]),[L,z]=W(e.authToken||null),H=Xe(()=>Ge(e,()=>({authToken:L,storage:P}),K=>{let oe=K({authToken:L,storage:P});oe.authToken!==L&&z(oe.authToken)}),[e,L,P]),s=Je(e,H,P),_=Ve(e,H,P),C=qe(e,H);ae(()=>{for(let d=s.messages.length-1;d>=0;d--){let E=s.messages[d];if(E.type==="sub_agent_start"){N({key:E.metadata?.subAgentKey,name:E.metadata?.agentName});return}if(E.type==="sub_agent_end"){N(null);return}}},[s.messages]),ae(()=>{let d=P.get(e.conversationIdKey);d&&s.loadConversation(d)},[]),ae(()=>{t&&t({isOpen:i,isExpanded:w,debugMode:m,messages:s.messages,conversationId:s.conversationId,isLoading:s.isLoading,error:s.error})},[i,w,m,s.messages,s.conversationId,s.isLoading,s.error]);let S=te(async()=>{if(e.showConversationSidebar){v(!0);try{let d=`${e.backendUrl}${e.apiPaths.conversations}?agent_key=${encodeURIComponent(e.agentKey)}`,E=await fetch(d,H.getFetchOptions({method:"GET"}));if(E.ok){let K=await E.json();y(K.results||K)}}catch(d){console.error("[ChatWidget] Failed to load conversations:",d),y([])}finally{v(!1)}}},[e,H]),b=te(()=>{let d=!l;k(d),d&&S()},[l,S]),M=te(d=>{d!==s.conversationId&&s.loadConversation(d),k(!1)},[s]),r=te(()=>{s.clearMessages(),k(!1)},[s]),I=te(d=>{s.sendMessage(d,{model:_.selectedModel,onAssistantMessage:E=>{}})},[s,T,_.selectedModel]),R=te(d=>{u(d),d==="tasks"&&C.loadTaskList()},[C]);if(ae(()=>{o&&(o.current={open:()=>c(!0),close:()=>c(!1),send:d=>I(d),clearMessages:()=>s.clearMessages(),toggleTTS:()=>A(d=>!d),stopSpeech:()=>j(!1),setAuth:d=>{d.token!==void 0&&z(d.token)},clearAuth:()=>z(null)})},[s,o,I]),!e.embedded&&!i)return J`
480
+ <button
481
+ class="cw-fab"
482
+ style=${{backgroundColor:e.primaryColor}}
483
+ onClick=${()=>c(!0)}
484
+ >
485
+ <svg class="cw-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
486
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
487
+ </svg>
488
+ </button>
489
+ `;let a=["cw-widget",w&&"cw-widget-expanded",e.embedded&&"cw-widget-embedded"].filter(Boolean).join(" ");return J`
490
+ <div class=${a} style=${{"--cw-primary":e.primaryColor}}>
491
+ ${e.showConversationSidebar&&J`
492
+ <${Ne}
493
+ isOpen=${l}
494
+ conversations=${p}
495
+ conversationsLoading=${h}
496
+ currentConversationId=${s.conversationId}
497
+ onClose=${()=>k(!1)}
498
+ onNewConversation=${r}
499
+ onSwitchConversation=${M}
500
+ />
501
+ `}
502
+
503
+ <${Ae}
504
+ config=${e}
505
+ debugMode=${m}
506
+ isExpanded=${w}
507
+ isSpeaking=${F}
508
+ messagesCount=${s.messages.length}
509
+ isLoading=${s.isLoading}
510
+ currentAgent=${U}
511
+ onClose=${()=>c(!1)}
512
+ onToggleExpand=${()=>$(!w)}
513
+ onToggleDebug=${()=>f(!m)}
514
+ onToggleTTS=${()=>A(!T)}
515
+ onClear=${s.clearMessages}
516
+ onToggleSidebar=${b}
517
+ />
518
+
519
+ ${e.showTasksTab!==!1&&J`
520
+ <div class="cw-tabs">
521
+ <button
522
+ class=${`cw-tab ${g==="chat"?"cw-tab-active":""}`}
523
+ onClick=${()=>R("chat")}
524
+ >
525
+ Chat
526
+ </button>
527
+ <button
528
+ class=${`cw-tab ${g==="tasks"?"cw-tab-active":""}`}
529
+ onClick=${()=>R("tasks")}
530
+ >
531
+ Tasks ${C.progress.total>0?J`<span class="cw-tab-badge">${C.progress.completed}/${C.progress.total}</span>`:""}
532
+ </button>
533
+ </div>
534
+ `}
535
+
536
+ ${m&&J`<div class="cw-status-bar"><span>🐛 Debug</span></div>`}
537
+
538
+ ${g==="chat"?J`
539
+ <${Le}
540
+ messages=${s.messages}
541
+ isLoading=${s.isLoading}
542
+ hasMoreMessages=${s.hasMoreMessages}
543
+ loadingMoreMessages=${s.loadingMoreMessages}
544
+ onLoadMore=${s.loadMoreMessages}
545
+ onEditMessage=${s.editMessage}
546
+ onRetryMessage=${s.retryMessage}
547
+ debugMode=${m}
548
+ markdownParser=${n}
549
+ emptyStateTitle=${e.emptyStateTitle}
550
+ emptyStateMessage=${e.emptyStateMessage}
551
+ />
552
+
553
+ ${s.error&&J`<div class="cw-error-bar">${s.error}</div>`}
554
+
555
+ ${e.showModelSelector&&_.availableModels.length>0&&J`
556
+ <${He}
557
+ availableModels=${_.availableModels}
558
+ selectedModel=${_.selectedModel}
559
+ onSelectModel=${_.selectModel}
560
+ disabled=${s.isLoading}
561
+ />
562
+ `}
563
+
564
+ <${Ke}
565
+ onSend=${I}
566
+ onCancel=${s.cancelRun}
567
+ isLoading=${s.isLoading}
568
+ placeholder=${e.placeholder}
569
+ primaryColor=${e.primaryColor}
570
+ enableVoice=${e.enableVoice}
571
+ />
572
+ `:J`
573
+ <${Ue}
574
+ tasks=${C.tasks}
575
+ progress=${C.progress}
576
+ isLoading=${C.isLoading}
577
+ error=${C.error}
578
+ onUpdate=${C.updateTask}
579
+ onRemove=${C.removeTask}
580
+ onClear=${C.clearTasks}
581
+ onRefresh=${C.loadTaskList}
582
+ />
583
+ `}
584
+ </div>
585
+ `}var Qe={backendUrl:"http://localhost:8000",agentKey:"default-agent",title:"Chat Assistant",subtitle:"How can we help you today?",primaryColor:"#0066cc",position:"bottom-right",defaultJourneyType:"general",enableDebugMode:!0,enableAutoRun:!0,journeyTypes:{},customerPrompts:{},placeholder:"Type your message...",emptyStateTitle:"Start a Conversation",emptyStateMessage:"Send a message to get started.",authStrategy:null,authToken:null,authHeader:null,authTokenPrefix:null,anonymousSessionEndpoint:null,anonymousTokenKey:"chat_widget_anonymous_token",onAuthError:null,anonymousTokenHeader:"X-Anonymous-Token",conversationIdKey:"chat_widget_conversation_id",sessionTokenKey:"chat_widget_session_token",apiPaths:{anonymousSession:"/api/accounts/anonymous-session/",conversations:"/api/agent-runtime/conversations/",runs:"/api/agent-runtime/runs/",runEvents:"/api/agent-runtime/runs/{runId}/events/",simulateCustomer:"/api/agent-runtime/simulate-customer/",ttsVoices:"/api/tts/voices/",ttsSetVoice:"/api/tts/set-voice/",models:"/api/agent-runtime/models/"},apiCaseStyle:"auto",showConversationSidebar:!0,showClearButton:!0,showDebugButton:!0,showTTSButton:!0,showVoiceSettings:!0,showExpandButton:!0,showModelSelector:!1,enableVoice:!0,modelKey:"chat_widget_selected_model",autoRunDelay:1e3,autoRunMode:"automatic",enableTTS:!1,ttsProxyUrl:null,elevenLabsApiKey:null,ttsVoices:{assistant:null,user:null},ttsModel:"eleven_turbo_v2_5",ttsSettings:{stability:.5,similarity_boost:.75,style:0,use_speaker_boost:!0},availableVoices:[],onEvent:null,containerId:null,embedded:!1,metadata:{}};function Ye(e){let t={...Qe.apiPaths,...e.apiPaths||{}};return{...Qe,...e,apiPaths:t}}var ye=new Map,mt=0,x=null,Se=class{constructor(t={}){Me(this,"_handleStateChange",t=>{this._state=t});this.instanceId=`cw-${++mt}`,this.config=Ye(t),this.container=null,this._state={},this._apiRef={current:null},ye.set(this.instanceId,this)}init(){if(this.config.containerId){if(this.container=document.getElementById(this.config.containerId),!this.container)return console.error(`[ChatWidget] Container not found: ${this.config.containerId}`),this;this.container.classList.add("cw-container-embedded")}else this.container=document.createElement("div"),this.container.id=this.instanceId,this.container.className=`cw-container cw-position-${this.config.position}`,document.body.appendChild(this.container);return this._render(),console.log(`[ChatWidget] Instance ${this.instanceId} initialized`),this}_render(t={}){this.container&&et(ht`<${Ze}
586
+ config=${{...this.config,...t}}
587
+ onStateChange=${this._handleStateChange}
588
+ markdownParser=${Te._enhancedMarkdownParser}
589
+ apiRef=${this._apiRef}
590
+ />`,this.container)}destroy(){this.container&&(et(null,this.container),this.config.containerId?this.container.classList.remove("cw-container-embedded"):this.container.remove(),this.container=null),ye.delete(this.instanceId),console.log(`[ChatWidget] Instance ${this.instanceId} destroyed`)}open(){this._apiRef.current?this._apiRef.current.open():this._render({forceOpen:!0})}close(){this._apiRef.current?this._apiRef.current.close():this._render({forceOpen:!1})}send(t){this._apiRef.current&&this._apiRef.current.send(t)}clearMessages(){this._apiRef.current&&this._apiRef.current.clearMessages()}toggleTTS(){this._apiRef.current&&this._apiRef.current.toggleTTS()}stopSpeech(){this._apiRef.current&&this._apiRef.current.stopSpeech()}setAuth(t){this._apiRef.current&&this._apiRef.current.setAuth(t)}clearAuth(){this._apiRef.current&&this._apiRef.current.clearAuth()}getState(){return{...this._state}}getConfig(){return{...this.config}}updateMetadata(t){this.config.metadata={...this.config.metadata,...t},this._render(),console.log(`[ChatWidget] Instance ${this.instanceId} metadata updated:`,t)}updateConfig(t){this.config={...this.config,...t},this._render(),console.log(`[ChatWidget] Instance ${this.instanceId} config updated`)}};function tt(e={}){return new Se(e).init()}function ft(e={}){return x&&x.destroy(),x=tt(e),x}function gt(){x&&(x.destroy(),x=null)}function $t(){x&&x.open()}function yt(){x&&x.close()}function wt(e){x&&x.send(e)}function vt(){x&&x.clearMessages()}function kt(){x&&x.toggleTTS()}function bt(){x&&x.stopSpeech()}function Ct(e){x&&x.setAuth(e)}function St(){x&&x.clearAuth()}function Tt(){return x?x.getState():null}function _t(){return x?x.getConfig():null}var Te={createInstance:tt,getInstance:e=>ye.get(e),getAllInstances:()=>Array.from(ye.values()),init:ft,destroy:gt,open:$t,close:yt,send:wt,clearMessages:vt,toggleTTS:kt,stopSpeech:bt,setAuth:Ct,clearAuth:St,getState:Tt,getConfig:_t,_enhancedMarkdownParser:null};var An=Te;typeof window<"u"&&(window.ChatWidget=Te);export{Te as ChatWidget,An as default};