@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 st=Object.defineProperty;var at=(e,t,n)=>t in e?st(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Je=(e,t,n)=>(at(e,typeof t!="symbol"?t+"":t,n),n);import{html as J}from"htm/preact";import{useState as U,useEffect as ce,useCallback as te,useMemo as et}from"preact/compat";import{html as q}from"htm/preact";function ze(e){return e.replace(/_([a-z])/g,(t,n)=>n.toUpperCase())}function me(e){return e.replace(/[A-Z]/g,t=>`_${t.toLowerCase()}`)}function ne(e){return Array.isArray(e)?e.map(ne):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([t,n])=>[ze(t),ne(n)])):e}function se(e){return Array.isArray(e)?e.map(se):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([t,n])=>[me(t),se(n)])):e}function ae(){return"msg-"+Date.now()+"-"+Math.random().toString(36).substr(2,9)}function O(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}function ke(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 be(e,t=null){if(t)return t(e);let n=O(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 Ce(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 Se(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 oe(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 re(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 Te({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:D,showExpandButton:j,enableTTS:B,elevenLabsApiKey:N,ttsProxyUrl:P}=e,L=N||P;return q`
2
+ <div class="cw-header" style=${{backgroundColor:g}}>
3
+ ${h&&q`
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">${O(y)}</span>
19
+ ${w&&q`
20
+ <span class="cw-current-agent" title="Currently active agent">
21
+ <span class="cw-agent-indicator">🤖</span>
22
+ <span class="cw-agent-name">${O(w.name||w.key)}</span>
23
+ </span>
24
+ `}
25
+ </div>
26
+
27
+ <div class="cw-header-actions">
28
+ ${v&&q`
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&&q`
38
+ <button
39
+ class="cw-header-btn ${t?"cw-btn-active":""}"
40
+ onClick=${f}
41
+ title="Debug"
42
+ >🐛</button>
43
+ `}
44
+
45
+ ${D&&L&&q`
46
+ <button
47
+ class="cw-header-btn ${B?"cw-btn-active":""}"
48
+ onClick=${l}
49
+ title="TTS"
50
+ >${B?"\u{1F50A}":"\u{1F507}"}</button>
51
+ `}
52
+
53
+ ${j&&!u&&q`
54
+ <button
55
+ class="cw-header-btn"
56
+ onClick=${m}
57
+ title=${n?"Minimize":"Expand"}
58
+ >${n?"\u2296":"\u2295"}</button>
59
+ `}
60
+
61
+ ${!u&&q`
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 Ge,useEffect as qe}from"preact/compat";import{html as F}from"htm/preact";import{useState as fe,useRef as ot,useEffect as rt}from"preact/compat";function Me({msg:e,show:t,onToggle:n}){return t?F`
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
+ `:F`
76
+ <button
77
+ class="cw-debug-payload-btn"
78
+ onClick=${n}
79
+ title="Show message payload"
80
+ >{ }</button>
81
+ `}function Ve({onEdit:e,onRetry:t,isLoading:n,position:o,showEdit:i=!0}){return n?null:F`
82
+ <div class="cw-message-actions cw-message-actions-${o||"left"}">
83
+ ${i&&F`
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]=fe(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")},[]),F`
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 _e({msg:e,debugMode:t,markdownParser:n,onEdit:o,onRetry:i,isLoading:c,messageIndex:w}){let[$,m]=fe(!1),[f,l]=fe(!1),[k,p]=fe(!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",D=e.type==="agent_context";if(g&&!t)return null;if(T||A||D)return F`
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&&F`
136
+ <span class="cw-agent-context-name">${e.metadata.agentName}</span>
137
+ `}
138
+ ${t&&F`<${Me} msg=${e} show=${f} onToggle=${()=>l(!f)} />`}
139
+ </div>
140
+ `;if(u||h){let b=e.metadata?.arguments||e.metadata?.result,_=r=>{if(typeof r=="string")try{return JSON.stringify(JSON.parse(r),null,2)}catch{return r}return JSON.stringify(r,null,2)};return F`
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&&F`<span class="cw-tool-expand">${$?"\u25BC":"\u25B6"}</span>`}
145
+ </span>
146
+ ${$&&b&&F`
147
+ <pre class="cw-tool-details">${O(_(u?e.metadata.arguments:e.metadata.result))}</pre>
148
+ `}
149
+ ${t&&F`<${Me} 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(" "),B=`cw-message-row ${y?"cw-message-row-user":""}`,N=e.role==="assistant"?be(e.content,n):O(e.content),P=e.files&&e.files.length>0,L=()=>P?F`
152
+ <div class="cw-message-attachments">
153
+ ${e.files.map(b=>b.type&&b.type.startsWith("image/")?F`
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
+ `:F`
158
+ <a class="cw-attachment-file" href=${b.url} target="_blank" title=${b.name}>
159
+ <span class="cw-attachment-icon">${re(b.type)}</span>
160
+ <span class="cw-attachment-info">
161
+ <span class="cw-attachment-name">${b.name}</span>
162
+ <span class="cw-attachment-size">${oe(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 F`
168
+ <div class=${B} 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 F`
177
+ <div class="${B} ${s||C?"cw-message-row-with-actions":""}">
178
+ ${L()}
179
+ ${s&&F`
180
+ <div class="cw-user-actions-wrapper">
181
+ <${Ve}
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&&F`
192
+ <div class=${j} dangerouslySetInnerHTML=${{__html:N}} />
193
+ `}
194
+ ${C&&F`
195
+ <${Ve}
196
+ onRetry=${H}
197
+ isLoading=${c}
198
+ position="right"
199
+ showEdit=${!1}
200
+ />
201
+ `}
202
+ ${t&&F`<${Me} msg=${e} show=${f} onToggle=${()=>l(!f)} />`}
203
+ </div>
204
+ `}function xe({messages:e,isLoading:t,hasMoreMessages:n,loadingMoreMessages:o,onLoadMore:i,onEditMessage:c,onRetryMessage:w,debugMode:$,markdownParser:m,emptyStateTitle:f,emptyStateMessage:l}){let k=Ge(null),p=Ge(!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})}};qe(()=>{let u=k.current;u&&p.current&&requestAnimationFrame(()=>{u.scrollTop=u.scrollHeight})},[e,t]),qe(()=>{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>${O(f)}</h3>
212
+ <p>${O(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
+ <${_e}
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 ie,useRef as ge,useEffect as Ie}from"preact/compat";var Ee=typeof window<"u"?window.SpeechRecognition||window.webkitSpeechRecognition:null;function Re({onSend:e,onCancel:t,isLoading:n,placeholder:o,primaryColor:i,enableVoice:c=!0,enableFiles:w=!0}){let[$,m]=ie(""),[f,l]=ie([]),[k,p]=ie(!1),[y,g]=ie(!1),[u]=ie(()=>!!Ee),h=ge(null),v=ge(null),T=ge(null),A=ge(!1);Ie(()=>{!n&&h.current&&h.current.focus()},[n]),Ie(()=>{h.current&&(h.current.style.height="auto",h.current.style.height=Math.min(h.current.scrollHeight,150)+"px")},[$]),Ie(()=>()=>{A.current=!1,T.current&&T.current.abort()},[]);let D=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 x=Array.from(r.target.files||[]);x.length>0&&l(R=>[...R,...x])},B=r=>{l(x=>x.filter((R,a)=>a!==r))},N=r=>{r.preventDefault(),v.current&&!n&&v.current.click()},P=r=>{r.key==="Enter"&&!r.shiftKey&&(r.preventDefault(),D(r))},L=r=>{n&&t&&(r.preventDefault(),t())},z=()=>{if(!Ee||n)return;A.current=!0;let r=new Ee;r.continuous=!0,r.interimResults=!0,r.lang=navigator.language||"en-US";let x=$,R="";r.onstart=()=>{g(!0)},r.onresult=a=>{R="";for(let d=a.resultIndex;d<a.results.length;d++){let I=a.results[d][0].transcript;a.results[d].isFinal?x+=(x?" ":"")+I:R+=I}m(x+(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(x||$)},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),x&&m(x),T.current=null},T.current=r,r.start()},H=()=>{A.current=!1,T.current&&T.current.stop()},s=r=>{r.preventDefault(),y?H():z()},M=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,_=w;return V`
260
+ <form class="cw-input-form" onSubmit=${D}>
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,x)=>V`
271
+ <div class="cw-file-chip" key=${x}>
272
+ <span class="cw-file-chip-icon">${re(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">(${oe(r.size)})</span>
275
+ <button
276
+ type="button"
277
+ class="cw-file-chip-remove"
278
+ onClick=${()=>B(x)}
279
+ title="Remove file"
280
+ >×</button>
281
+ </div>
282
+ `)}
283
+ </div>
284
+ `}
285
+ <textarea
286
+ ref=${h}
287
+ class="cw-input"
288
+ placeholder=${O(o)}
289
+ value=${$}
290
+ onInput=${r=>m(r.target.value)}
291
+ onKeyDown=${P}
292
+ disabled=${n}
293
+ rows="1"
294
+ />
295
+ ${_&&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?M:V`<span class="cw-spinner"></span>`:"\u27A4"}
327
+ </button>
328
+ </form>
329
+ `}import{html as $e}from"htm/preact";function Ae({isOpen:e,conversations:t,conversationsLoading:n,currentConversationId:o,onClose:i,onNewConversation:c,onSwitchConversation:w}){return $e`
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&&$e`
342
+ <div class="cw-sidebar-loading">
343
+ <span class="cw-spinner"></span>
344
+ </div>
345
+ `}
346
+
347
+ ${!n&&t.length===0&&$e`
348
+ <div class="cw-sidebar-empty">No conversations yet</div>
349
+ `}
350
+
351
+ ${t.map($=>$e`
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">${O($.title||"Untitled")}</div>
358
+ <div class="cw-conversation-date">${ke($.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 ye}from"htm/preact";import{useState as lt}from"preact/compat";function Fe({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 ye`
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">${O($)}</span>
378
+ <span class="cw-model-chevron">${i?"\u25B2":"\u25BC"}</span>
379
+ </button>
380
+
381
+ ${i&&ye`
382
+ <div class="cw-model-dropdown">
383
+ ${e.map(l=>ye`
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">${O(l.name)}</span>
390
+ <span class="cw-model-option-provider">${O(l.provider)}</span>
391
+ ${l.description&&ye`
392
+ <span class="cw-model-option-desc">${O(l.description)}</span>
393
+ `}
394
+ </button>
395
+ `)}
396
+ </div>
397
+ `}
398
+ </div>
399
+ `}import{html as G}from"htm/preact";import{useState as Xe,useCallback as le}from"preact/compat";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]=Xe(!1),[w,$]=Xe(e.name),m=le(()=>{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=le(()=>{w.trim()&&w!==e.name&&t(e.id,{name:w.trim()}),c(!1)},[e,w,t]),l=le(p=>{p.key==="Enter"&&f(),p.key==="Escape"&&($(e.name),c(!1))},[f,e.name]),k=`cw-task-state-${e.state.replace("_","-")}`;return G`
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?G`
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
+ `:G`
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 Oe({tasks:e,progress:t,isLoading:n,error:o,onUpdate:i,onRemove:c,onClear:w,onRefresh:$}){let m=le(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=le((k,p=0)=>G`
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?G`<div class="cw-tasks-loading">Loading tasks...</div>`:G`
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&&G`
463
+ <button class="cw-tasks-action-btn" onClick=${w} title="Clear all">🗑</button>
464
+ `}
465
+ </div>
466
+ </div>
467
+
468
+ ${o&&G`<div class="cw-tasks-error">${o}</div>`}
469
+
470
+ <div class="cw-tasks-list">
471
+ ${l.length===0?G`
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 Ze,useEffect as Qe}from"preact/compat";function De(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=Ze(null),T=Ze(null);Qe(()=>{f&&n?.set(e.conversationIdKey,f)},[f,e.conversationIdKey,n]);let A=X(async(s,M,C)=>{v.current&&v.current.close();let S=e.apiPaths.runEvents.replace("{runId}",s),b=`${e.backendUrl}${S}`;M&&(b+=`?anonymous_token=${encodeURIComponent(M)}`);let _=new EventSource(b);v.current=_;let r="";_.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(I=>{let K=I[I.length-1];return K?.role==="assistant"&&K.id.startsWith("assistant-stream-")?[...I.slice(0,-1),{...K,content:r}]:[...I,{id:"assistant-stream-"+Date.now(),role:"assistant",content:r,timestamp:new Date,type:"message"}]}))}catch(a){console.error("[ChatWidget] Parse error:",a)}}),_.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)}}),_.addEventListener("tool.result",R=>{try{let a=JSON.parse(R.data);e.onEvent&&e.onEvent("tool.result",a.payload);let d=a.payload.result,I=d?.error;i(K=>[...K,{id:"tool-result-"+Date.now(),role:"system",content:I?`\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)}}),_.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)}}),_.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)}}),_.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 x=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(I=>[...I,{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),_.close(),v.current=null,r&&C&&C(r)};_.addEventListener("run.succeeded",x),_.addEventListener("run.failed",x),_.addEventListener("run.cancelled",x),_.addEventListener("run.timed_out",x),_.onerror=()=>{w(!1),_.close(),v.current=null}},[e]),D=X(async(s,M={},C={})=>{if(!s.trim()||c)return;let S=[],b={};typeof M=="function"?b={onAssistantMessage:M}:Array.isArray(M)?(S=M,b=C):b=M||{};let{model:_,onAssistantMessage:r,supersedeFromMessageIndex:x}=b;w(!0),m(null);let R={id:ae(),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 W=e.apiCaseStyle!=="camel",je=he=>W?me(he):he,Z=new FormData;Z.append(je("agentKey"),e.agentKey),f&&Z.append(je("conversationId"),f),Z.append("messages",JSON.stringify([{role:"user",content:s.trim()}])),Z.append("metadata",JSON.stringify(W?{...e.metadata,journey_type:e.defaultJourneyType}:{...e.metadata,journeyType:e.defaultJourneyType})),_&&Z.append("model",_),S.forEach(he=>{Z.append("files",he)}),d=t.getFetchOptions({method:"POST",body:Z},a)}else{let W=t.transformRequest({agentKey:e.agentKey,conversationId:f,messages:[{role:"user",content:s.trim()}],metadata:{...e.metadata,journeyType:e.defaultJourneyType},..._&&{model:_},...x!==void 0&&{supersedeFromMessageIndex:x}});d=t.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(W)},a)}let I=await fetch(`${e.backendUrl}${e.apiPaths.runs}`,d),K=a;if(I.status===401){t.clearSession();let W=await t.getOrCreateSession(!0);W&&(K=W,S.length>0?d=t.getFetchOptions({method:"POST",body:d.body},W):d=t.getFetchOptions({method:"POST",headers:{"Content-Type":"application/json"},body:d.body},W),I=await fetch(`${e.backendUrl}${e.apiPaths.runs}`,d))}if(!I.ok){let W=await I.json().catch(()=>({}));throw new Error(W.error||W.detail||`HTTP ${I.status}`)}let ue=await I.json(),pe=t.transformResponse(ue);T.current=pe.id,!f&&pe.conversationId&&l(pe.conversationId),await A(pe.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 M=e.apiPaths.cancelRun?e.apiPaths.cancelRun.replace("{runId}",s):`${e.apiPaths.runs}${s}/cancel/`;(await fetch(`${e.backendUrl}${M}`,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(M){console.error("[ChatWidget] Failed to cancel run:",M)}},[e,t,c]),B=X(()=>{i([]),l(null),m(null),p(!1),h(0),n?.set(e.conversationIdKey,null)},[e.conversationIdKey,n]),N=s=>{let M={id:ae(),role:s.role,timestamp:s.timestamp?new Date(s.timestamp):new Date};if(s.role==="tool")return{...M,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:ae(),role:"assistant",content:`\u{1F527} ${S.function?.name||S.name||"tool"}`,timestamp:M.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:{...M,content:C,type:"message"}},P=X(async s=>{w(!0),i([]),l(s);try{let M=await t.getOrCreateSession(),S=`${e.backendUrl}${e.apiPaths.conversations}${s}/?limit=10&offset=0`,b=await fetch(S,t.getFetchOptions({method:"GET"},M));if(b.ok){let _=await b.json(),r=t.transformResponse(_);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(M){console.error("[ChatWidget] Failed to load conversation:",M)}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(),_=t.transformResponse(b);if(_.messages?.length>0){let r=_.messages.flatMap(N).filter(Boolean);i(x=>[...r,...x]),h(x=>x+_.messages.length),p(_.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,M,C={})=>{if(c)return;let S=o[s];if(!S||S.role!=="user")return;let b=o.slice(0,s);i(b),await D(M,{...C,supersedeFromMessageIndex:s})},[o,c,D]),H=X(async(s,M={})=>{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 _=o.slice(0,S);i(_),await D(b.content,{...M,supersedeFromMessageIndex:S})},[o,c,D]);return Qe(()=>()=>{v.current&&v.current.close()},[]),{messages:o,isLoading:c,error:$,conversationId:f,hasMoreMessages:k,loadingMoreMessages:y,sendMessage:D,cancelRun:j,clearMessages:B,loadConversation:P,loadMoreMessages:L,setConversationId:l,editMessage:z,retryMessage:H}}import{useState as we,useEffect as pt,useCallback as Ye}from"preact/compat";function Pe(e,t,n){let[o,i]=we([]),[c,w]=we(null),[$,m]=we(null),[f,l]=we(!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=Ye(y=>{w(y),n?.set(e.modelKey,y)},[e.modelKey,n]),p=Ye(()=>o.find(y=>y.id===c)||null,[o,c]);return{availableModels:o,selectedModel:c,defaultModel:$,isLoading:f,selectModel:k,getSelectedModelInfo:p}}import{useState as Le,useCallback as ee}from"preact/compat";function Ke(e,t){let[n,o]=Le(null),[i,c]=Le(!1),[w,$]=Le(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 Ne(e,t,n){let o=l=>!l||typeof l!="object"||e.apiCaseStyle==="camel"?l:se(l),i=l=>!l||typeof l!="object"||e.apiCaseStyle==="snake"?l:ne(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=Se(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 de({config:e,onStateChange:t,markdownParser:n,apiRef:o}){let[i,c]=U(e.embedded||e.forceOpen===!0),[w,$]=U(!1),[m,f]=U(!1),[l,k]=U(!1),[p,y]=U([]),[g,u]=U("chat"),[h,v]=U(!1),[T,A]=U(e.enableTTS),[D,j]=U(!1),[B,N]=U(null);ce(()=>{e.forceOpen!==void 0&&c(e.forceOpen)},[e.forceOpen]);let P=et(()=>Ce(e.containerId),[e.containerId]),[L,z]=U(e.authToken||null),H=et(()=>Ne(e,()=>({authToken:L,storage:P}),K=>{let ue=K({authToken:L,storage:P});ue.authToken!==L&&z(ue.authToken)}),[e,L,P]),s=De(e,H,P),M=Pe(e,H,P),C=Ke(e,H);ce(()=>{for(let d=s.messages.length-1;d>=0;d--){let I=s.messages[d];if(I.type==="sub_agent_start"){N({key:I.metadata?.subAgentKey,name:I.metadata?.agentName});return}if(I.type==="sub_agent_end"){N(null);return}}},[s.messages]),ce(()=>{let d=P.get(e.conversationIdKey);d&&s.loadConversation(d)},[]),ce(()=>{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)}`,I=await fetch(d,H.getFetchOptions({method:"GET"}));if(I.ok){let K=await I.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]),_=te(d=>{d!==s.conversationId&&s.loadConversation(d),k(!1)},[s]),r=te(()=>{s.clearMessages(),k(!1)},[s]),x=te(d=>{s.sendMessage(d,{model:M.selectedModel,onAssistantMessage:I=>{}})},[s,T,M.selectedModel]),R=te(d=>{u(d),d==="tasks"&&C.loadTaskList()},[C]);if(ce(()=>{o&&(o.current={open:()=>c(!0),close:()=>c(!1),send:d=>x(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,x]),!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
+ <${Ae}
493
+ isOpen=${l}
494
+ conversations=${p}
495
+ conversationsLoading=${h}
496
+ currentConversationId=${s.conversationId}
497
+ onClose=${()=>k(!1)}
498
+ onNewConversation=${r}
499
+ onSwitchConversation=${_}
500
+ />
501
+ `}
502
+
503
+ <${Te}
504
+ config=${e}
505
+ debugMode=${m}
506
+ isExpanded=${w}
507
+ isSpeaking=${D}
508
+ messagesCount=${s.messages.length}
509
+ isLoading=${s.isLoading}
510
+ currentAgent=${B}
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
+ <${xe}
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&&M.availableModels.length>0&&J`
556
+ <${Fe}
557
+ availableModels=${M.availableModels}
558
+ selectedModel=${M.selectedModel}
559
+ onSelectModel=${M.selectModel}
560
+ disabled=${s.isLoading}
561
+ />
562
+ `}
563
+
564
+ <${Re}
565
+ onSend=${x}
566
+ onCancel=${s.cancelRun}
567
+ isLoading=${s.isLoading}
568
+ placeholder=${e.placeholder}
569
+ primaryColor=${e.primaryColor}
570
+ enableVoice=${e.enableVoice}
571
+ />
572
+ `:J`
573
+ <${Oe}
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 He={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 We(e){let t={...He.apiPaths,...e.apiPaths||{}};return{...He,...e,apiPaths:t}}import{render as tt}from"preact/compat";import{html as ht}from"htm/preact";var ve=new Map,mt=0,E=null,Be=class{constructor(t={}){Je(this,"_handleStateChange",t=>{this._state=t});this.instanceId=`cw-${++mt}`,this.config=We(t),this.container=null,this._state={},this._apiRef={current:null},ve.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&&tt(ht`<${de}
586
+ config=${{...this.config,...t}}
587
+ onStateChange=${this._handleStateChange}
588
+ markdownParser=${Ue._enhancedMarkdownParser}
589
+ apiRef=${this._apiRef}
590
+ />`,this.container)}destroy(){this.container&&(tt(null,this.container),this.config.containerId?this.container.classList.remove("cw-container-embedded"):this.container.remove(),this.container=null),ve.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 nt(e={}){return new Be(e).init()}function ft(e={}){return E&&E.destroy(),E=nt(e),E}function gt(){E&&(E.destroy(),E=null)}function $t(){E&&E.open()}function yt(){E&&E.close()}function wt(e){E&&E.send(e)}function vt(){E&&E.clearMessages()}function kt(){E&&E.toggleTTS()}function bt(){E&&E.stopSpeech()}function Ct(e){E&&E.setAuth(e)}function St(){E&&E.clearAuth()}function Tt(){return E?E.getState():null}function Mt(){return E?E.getConfig():null}var Ue={createInstance:nt,getInstance:e=>ve.get(e),getAllInstances:()=>Array.from(ve.values()),init:ft,destroy:gt,open:$t,close:yt,send:wt,clearMessages:vt,toggleTTS:kt,stopSpeech:bt,setAuth:Ct,clearAuth:St,getState:Tt,getConfig:Mt,_enhancedMarkdownParser:null};typeof window<"u"&&(window.ChatWidget=Ue);var Dn=de;export{de as ChatWidget,Ue as ChatWidgetAPI,He as DEFAULT_CONFIG,Te as Header,Re as InputForm,_e as Message,xe as MessageList,Fe as ModelSelector,Ae as Sidebar,Oe as TaskList,me as camelToSnake,Ne as createApiClient,Ce as createStorage,Dn as default,ke as formatDate,oe as formatFileSize,ae as generateId,Se as getCSRFToken,re as getFileTypeIcon,ne as keysToCamel,se as keysToSnake,We as mergeConfig,be as parseMarkdown,ze as snakeToCamel,De as useChat,Pe as useModels,Ke as useTasks};