claudius-chat-widget 1.11.0 → 1.13.0

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.
package/dist/claudius.js CHANGED
@@ -1,9 +1,9 @@
1
- var Ee = Object.defineProperty;
2
- var Re = (e, t, r) => t in e ? Ee(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
- var G = (e, t, r) => Re(e, typeof t != "symbol" ? t + "" : t, r);
4
- import { jsx as i, jsxs as h, Fragment as Te } from "react/jsx-runtime";
5
- import { useMemo as Y, useState as k, useRef as C, useCallback as M, useEffect as H, forwardRef as Me, memo as J, useId as Ce } from "react";
6
- class U extends Error {
1
+ var Ce = Object.defineProperty;
2
+ var Ne = (e, t, r) => t in e ? Ce(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
3
+ var X = (e, t, r) => Ne(e, typeof t != "symbol" ? t + "" : t, r);
4
+ import { jsx as a, jsxs as g, Fragment as xe } from "react/jsx-runtime";
5
+ import { useMemo as se, useState as L, useRef as I, useCallback as O, useEffect as z, forwardRef as ke, memo as de, useId as Le } from "react";
6
+ class j extends Error {
7
7
  /**
8
8
  * Create a {@link ChatApiError}.
9
9
  *
@@ -12,18 +12,18 @@ class U extends Error {
12
12
  * @param code - Optional machine-readable error code (e.g. `"TIMEOUT"`, `"NETWORK_ERROR"`).
13
13
  * @param retryAfter - Seconds to wait before retrying, from the `Retry-After` header.
14
14
  */
15
- constructor(t, r, s, n) {
16
- super(t), this.status = r, this.code = s, this.retryAfter = n, this.name = "ChatApiError";
15
+ constructor(t, r, n, s) {
16
+ super(t), this.status = r, this.code = n, this.retryAfter = s, this.name = "ChatApiError";
17
17
  }
18
18
  }
19
- class ae extends Error {
19
+ class le extends Error {
20
20
  /** Creates a `DebounceError` with a fixed message. */
21
21
  constructor() {
22
22
  super("Request debounced"), this.name = "DebounceError";
23
23
  }
24
24
  }
25
- const Ne = 3e4;
26
- class Se {
25
+ const Ae = 3e4;
26
+ class Oe {
27
27
  /**
28
28
  * Create a chat client for the given Worker base URL.
29
29
  *
@@ -31,12 +31,12 @@ class Se {
31
31
  * @param options - Optional retry, debounce, and timeout settings.
32
32
  */
33
33
  constructor(t, r) {
34
- G(this, "baseUrl");
35
- G(this, "maxRetries");
36
- G(this, "debounceMs");
37
- G(this, "timeoutMs");
38
- G(this, "lastSendTime", 0);
39
- this.baseUrl = t, this.maxRetries = (r == null ? void 0 : r.maxRetries) ?? 2, this.debounceMs = (r == null ? void 0 : r.debounceMs) ?? 300, this.timeoutMs = (r == null ? void 0 : r.timeoutMs) ?? Ne;
34
+ X(this, "baseUrl");
35
+ X(this, "maxRetries");
36
+ X(this, "debounceMs");
37
+ X(this, "timeoutMs");
38
+ X(this, "lastSendTime", 0);
39
+ this.baseUrl = t, this.maxRetries = (r == null ? void 0 : r.maxRetries) ?? 2, this.debounceMs = (r == null ? void 0 : r.debounceMs) ?? 300, this.timeoutMs = (r == null ? void 0 : r.timeoutMs) ?? Ae;
40
40
  }
41
41
  /**
42
42
  * Send the conversation to the chat endpoint and return the assistant's
@@ -50,45 +50,212 @@ class Se {
50
50
  */
51
51
  async sendMessage(t) {
52
52
  if (this.debounceMs > 0 && Date.now() - this.lastSendTime < this.debounceMs)
53
- throw new ae();
53
+ throw new le();
54
54
  this.lastSendTime = Date.now();
55
55
  let r;
56
- for (let s = 0; s <= this.maxRetries; s++)
56
+ for (let n = 0; n <= this.maxRetries; n++)
57
57
  try {
58
- const n = await this.fetchWithTimeout(t);
59
- if (n.ok)
60
- return await n.json();
61
- const o = await n.json().catch(() => ({})), c = n.headers.get("Retry-After"), a = c ? Number(c) : void 0;
62
- if (r = new U(
63
- o.error ?? `Request failed with status ${n.status}`,
64
- n.status,
58
+ const s = await this.fetchWithTimeout(t);
59
+ if (s.ok)
60
+ return await s.json();
61
+ const o = await s.json().catch(() => ({})), i = s.headers.get("Retry-After"), l = i ? Number(i) : void 0;
62
+ if (r = new j(
63
+ o.error ?? `Request failed with status ${s.status}`,
64
+ s.status,
65
65
  o.code,
66
- a
67
- ), !this.isRetryable(n.status))
66
+ l
67
+ ), !this.isRetryable(s.status))
68
68
  throw r;
69
- if (s < this.maxRetries) {
70
- const u = this.getRetryDelay(n, s);
71
- await this.delay(u);
69
+ if (n < this.maxRetries) {
70
+ const c = this.getRetryDelay(s, n);
71
+ await this.delay(c);
72
72
  }
73
- } catch (n) {
74
- if (n instanceof U) {
75
- if (!this.isRetryable(n.status, n.code))
76
- throw n;
77
- if (r = n, s < this.maxRetries) {
78
- const o = this.getRetryDelay(null, s);
73
+ } catch (s) {
74
+ if (s instanceof j) {
75
+ if (!this.isRetryable(s.status, s.code))
76
+ throw s;
77
+ if (r = s, n < this.maxRetries) {
78
+ const o = this.getRetryDelay(null, n);
79
79
  await this.delay(o);
80
80
  }
81
- } else if (r = new U(
81
+ } else if (r = new j(
82
82
  "Failed to connect. Please try again.",
83
83
  0,
84
84
  "NETWORK_ERROR"
85
- ), s < this.maxRetries) {
86
- const o = this.getRetryDelay(null, s);
85
+ ), n < this.maxRetries) {
86
+ const o = this.getRetryDelay(null, n);
87
87
  await this.delay(o);
88
88
  }
89
89
  }
90
90
  throw r;
91
91
  }
92
+ /**
93
+ * Send the conversation to the streaming chat endpoint and resolve with the
94
+ * assistant's full reply once the stream completes. Text deltas are
95
+ * delivered through {@link ChatStreamOptions.onChunk} as they arrive.
96
+ *
97
+ * Falls back to {@link sendMessage} (non-streaming) when the browser can't
98
+ * read response streams or the Worker doesn't expose `/api/chat/stream`
99
+ * (HTTP 404/405), so callers never need their own feature detection.
100
+ *
101
+ * Failures before the first byte follow the same retry policy as
102
+ * {@link sendMessage}; once streaming has begun there are no automatic
103
+ * retries. Aborting via {@link ChatStreamOptions.signal} is not an error:
104
+ * the promise resolves with the partial reply and `aborted: true`.
105
+ *
106
+ * @param messages - The full conversation so far, oldest message first.
107
+ * @param options - Chunk callback and cancellation signal.
108
+ * @throws {@link DebounceError} when called within the debounce window.
109
+ * @throws {@link ChatApiError} when the request fails after all retries, or
110
+ * the stream errors or is interrupted mid-reply (code `"STREAM_ERROR"`).
111
+ */
112
+ async streamMessage(t, r = {}) {
113
+ var s;
114
+ if (typeof ReadableStream > "u")
115
+ return this.sendMessage(t);
116
+ if (this.debounceMs > 0 && Date.now() - this.lastSendTime < this.debounceMs)
117
+ throw new le();
118
+ this.lastSendTime = Date.now();
119
+ let n;
120
+ for (let o = 0; o <= this.maxRetries; o++) {
121
+ let i;
122
+ try {
123
+ i = await this.fetchStream(t, r.signal);
124
+ } catch (c) {
125
+ if ((s = r.signal) != null && s.aborted)
126
+ return { reply: "", aborted: !0 };
127
+ if (n = c instanceof j ? c : new j(
128
+ "Failed to connect. Please try again.",
129
+ 0,
130
+ "NETWORK_ERROR"
131
+ ), !this.isRetryable(n.status, n.code))
132
+ throw n;
133
+ o < this.maxRetries && await this.delay(this.getRetryDelay(null, o));
134
+ continue;
135
+ }
136
+ if (i.status === 404 || i.status === 405)
137
+ return this.lastSendTime = 0, this.sendMessage(t);
138
+ if (!i.ok) {
139
+ const c = await i.json().catch(() => ({})), u = i.headers.get("Retry-After");
140
+ if (n = new j(
141
+ c.error ?? `Request failed with status ${i.status}`,
142
+ i.status,
143
+ c.code,
144
+ u ? Number(u) : void 0
145
+ ), !this.isRetryable(i.status))
146
+ throw n;
147
+ o < this.maxRetries && await this.delay(this.getRetryDelay(i, o));
148
+ continue;
149
+ }
150
+ if (!(i.headers.get("Content-Type") ?? "").includes("text/event-stream"))
151
+ try {
152
+ return await i.json();
153
+ } catch {
154
+ return this.lastSendTime = 0, this.sendMessage(t);
155
+ }
156
+ return i.body ? this.readSseStream(i.body, r) : (this.lastSendTime = 0, this.sendMessage(t));
157
+ }
158
+ throw n;
159
+ }
160
+ /**
161
+ * Consumes an SSE body, invoking `onChunk` per `chunk` event, resolving on
162
+ * `done`, throwing on `error` events or an interrupted connection, and
163
+ * resolving with the partial text when the caller aborts.
164
+ */
165
+ async readSseStream(t, r) {
166
+ var d, x, N, R, T, p, v;
167
+ const n = t.getReader(), s = new TextDecoder();
168
+ let o = "", i = "";
169
+ const l = [];
170
+ let c;
171
+ const u = () => {
172
+ n.cancel().catch(() => {
173
+ });
174
+ };
175
+ (d = r.signal) == null || d.addEventListener("abort", u, { once: !0 });
176
+ try {
177
+ for (; ; ) {
178
+ let k;
179
+ try {
180
+ k = await n.read();
181
+ } catch (w) {
182
+ if ((x = r.signal) != null && x.aborted) break;
183
+ throw w;
184
+ }
185
+ if ((N = r.signal) != null && N.aborted || k.done) break;
186
+ o += s.decode(k.value, { stream: !0 });
187
+ let H;
188
+ for (; (H = o.indexOf(`
189
+
190
+ `)) !== -1; ) {
191
+ const w = o.slice(0, H);
192
+ o = o.slice(H + 2);
193
+ const f = Ie(w);
194
+ if (f) {
195
+ if (f.event === "chunk") {
196
+ const E = typeof f.data.text == "string" ? f.data.text : "";
197
+ E && (i += E, (R = r.onChunk) == null || R.call(r, E, i));
198
+ } else if (f.event === "tool") {
199
+ if (typeof f.data.name == "string") {
200
+ const E = f.data;
201
+ l.push(E), (T = r.onToolUse) == null || T.call(r, E, l);
202
+ }
203
+ } else if (f.event === "done") {
204
+ const E = Array.isArray(f.data.toolUses) ? f.data.toolUses : l;
205
+ c = {
206
+ reply: typeof f.data.reply == "string" ? f.data.reply : i,
207
+ sources: f.data.sources,
208
+ ...E.length > 0 ? { toolUses: E } : {}
209
+ };
210
+ } else if (f.event === "error")
211
+ throw new j(
212
+ typeof f.data.error == "string" ? f.data.error : "Something went wrong. Please try again.",
213
+ 0,
214
+ "STREAM_ERROR"
215
+ );
216
+ }
217
+ }
218
+ }
219
+ } finally {
220
+ (p = r.signal) == null || p.removeEventListener("abort", u), n.releaseLock();
221
+ }
222
+ if ((v = r.signal) != null && v.aborted)
223
+ return {
224
+ reply: i,
225
+ aborted: !0,
226
+ ...l.length > 0 ? { toolUses: l } : {}
227
+ };
228
+ if (c) return c;
229
+ throw new j(
230
+ "Connection interrupted. Please try again.",
231
+ 0,
232
+ "STREAM_ERROR"
233
+ );
234
+ }
235
+ async fetchStream(t, r) {
236
+ const n = new AbortController(), s = () => n.abort();
237
+ r == null || r.addEventListener("abort", s, { once: !0 });
238
+ let o = !1;
239
+ const i = this.timeoutMs > 0 ? setTimeout(() => {
240
+ o = !0, n.abort();
241
+ }, this.timeoutMs) : void 0;
242
+ try {
243
+ return await fetch(`${this.baseUrl}/api/chat/stream`, {
244
+ method: "POST",
245
+ headers: { "Content-Type": "application/json" },
246
+ body: JSON.stringify({ messages: t }),
247
+ signal: n.signal
248
+ });
249
+ } catch (l) {
250
+ throw o ? new j(
251
+ "Request timed out. Please try again.",
252
+ 0,
253
+ "TIMEOUT"
254
+ ) : l;
255
+ } finally {
256
+ i !== void 0 && clearTimeout(i), r == null || r.removeEventListener("abort", s);
257
+ }
258
+ }
92
259
  async fetchWithTimeout(t) {
93
260
  if (this.timeoutMs <= 0)
94
261
  return fetch(`${this.baseUrl}/api/chat`, {
@@ -96,7 +263,7 @@ class Se {
96
263
  headers: { "Content-Type": "application/json" },
97
264
  body: JSON.stringify({ messages: t })
98
265
  });
99
- const r = new AbortController(), s = setTimeout(() => r.abort(), this.timeoutMs);
266
+ const r = new AbortController(), n = setTimeout(() => r.abort(), this.timeoutMs);
100
267
  try {
101
268
  return await fetch(`${this.baseUrl}/api/chat`, {
102
269
  method: "POST",
@@ -104,14 +271,14 @@ class Se {
104
271
  body: JSON.stringify({ messages: t }),
105
272
  signal: r.signal
106
273
  });
107
- } catch (n) {
108
- throw r.signal.aborted ? new U(
274
+ } catch (s) {
275
+ throw r.signal.aborted ? new j(
109
276
  "Request timed out. Please try again.",
110
277
  0,
111
278
  "TIMEOUT"
112
- ) : n;
279
+ ) : s;
113
280
  } finally {
114
- clearTimeout(s);
281
+ clearTimeout(n);
115
282
  }
116
283
  }
117
284
  isRetryable(t, r) {
@@ -119,10 +286,10 @@ class Se {
119
286
  }
120
287
  getRetryDelay(t, r) {
121
288
  if (t && t.status === 429) {
122
- const s = t.headers.get("Retry-After");
123
- if (s) {
124
- const n = Number(s);
125
- return Math.min(n * 1e3, 6e4);
289
+ const n = t.headers.get("Retry-After");
290
+ if (n) {
291
+ const s = Number(n);
292
+ return Math.min(s * 1e3, 6e4);
126
293
  }
127
294
  }
128
295
  return r === 0 ? 1e3 : 3e3;
@@ -131,72 +298,87 @@ class Se {
131
298
  return new Promise((r) => setTimeout(r, t));
132
299
  }
133
300
  }
134
- function ue(e) {
301
+ function Ie(e) {
302
+ let t = "message";
303
+ const r = [];
304
+ for (const n of e.split(`
305
+ `))
306
+ n.startsWith("event:") ? t = n.slice(6).trim() : n.startsWith("data:") && r.push(n.slice(5).trimStart());
307
+ if (r.length === 0) return null;
308
+ try {
309
+ const n = JSON.parse(r.join(`
310
+ `));
311
+ return typeof n != "object" || n === null ? null : { event: t, data: n };
312
+ } catch {
313
+ return null;
314
+ }
315
+ }
316
+ function we(e) {
135
317
  return typeof e == "string" ? { content: e } : e;
136
318
  }
137
- function Q(e, t, r) {
319
+ function fe(e, t, r) {
138
320
  console.error(`[claudius] plugin "${e.name}" failed in ${t}:`, r);
139
321
  }
140
- async function Le(e, t, r) {
141
- let s = t;
142
- for (const n of e) {
143
- if (!n.onBeforeSend) continue;
322
+ async function De(e, t, r) {
323
+ let n = t;
324
+ for (const s of e) {
325
+ if (!s.onBeforeSend) continue;
144
326
  let o = null;
145
- const c = {
327
+ const i = {
146
328
  ...r,
147
- respondWith(a) {
329
+ respondWith(l) {
148
330
  o = {
149
331
  type: "respond",
150
- message: s,
151
- reply: ue(a)
332
+ message: n,
333
+ reply: we(l)
152
334
  };
153
335
  },
154
- abort(a) {
155
- o = { type: "abort", reason: a };
336
+ abort(l) {
337
+ o = { type: "abort", reason: l };
156
338
  }
157
339
  };
158
340
  try {
159
- const a = await n.onBeforeSend(s, c);
341
+ const l = await s.onBeforeSend(n, i);
160
342
  if (o) return o;
161
- a && (s = a);
162
- } catch (a) {
163
- Q(n, "onBeforeSend", a);
343
+ l && (n = l);
344
+ } catch (l) {
345
+ fe(s, "onBeforeSend", l);
164
346
  }
165
347
  }
166
- return { type: "send", message: s };
348
+ return { type: "send", message: n };
167
349
  }
168
- async function ke(e, t, r) {
169
- let s = t;
170
- for (const n of e)
171
- if (n.onAfterReceive)
350
+ async function _e(e, t, r) {
351
+ let n = t;
352
+ for (const s of e)
353
+ if (s.onAfterReceive)
172
354
  try {
173
- const o = await n.onAfterReceive(s, r);
174
- o && (s = o);
355
+ const o = await s.onAfterReceive(n, r);
356
+ o && (n = o);
175
357
  } catch (o) {
176
- Q(n, "onAfterReceive", o);
358
+ fe(s, "onAfterReceive", o);
177
359
  }
178
- return s;
360
+ return n;
179
361
  }
180
- async function Ae(e, t, r) {
181
- for (const s of e) {
182
- if (!s.onError) continue;
183
- let n = null;
362
+ async function je(e, t, r) {
363
+ for (const n of e) {
364
+ if (!n.onError) continue;
365
+ let s = null;
184
366
  const o = {
185
367
  ...r,
186
- respondWith(c) {
187
- n = ue(c);
368
+ respondWith(i) {
369
+ s = we(i);
188
370
  }
189
371
  };
190
372
  try {
191
- if (await s.onError(t, o), n) return n;
192
- } catch (c) {
193
- Q(s, "onError", c);
373
+ if (await n.onError(t, o), s) return s;
374
+ } catch (i) {
375
+ fe(n, "onError", i);
194
376
  }
195
377
  }
196
378
  return null;
197
379
  }
198
- const Oe = 200, Ie = "claudius:messages";
199
- function De(e, t) {
380
+ const He = 200, Be = "claudius:messages";
381
+ function $e(e, t) {
200
382
  let r;
201
383
  try {
202
384
  r = new URL(t).host;
@@ -205,238 +387,295 @@ function De(e, t) {
205
387
  }
206
388
  return `${e}:${r}`;
207
389
  }
208
- function Z() {
390
+ function ue() {
209
391
  try {
210
392
  return typeof sessionStorage < "u" ? sessionStorage : null;
211
393
  } catch {
212
394
  return null;
213
395
  }
214
396
  }
215
- function _e(e) {
216
- const t = Z();
397
+ function Pe(e) {
398
+ const t = ue();
217
399
  if (!t) return [];
218
400
  try {
219
401
  const r = t.getItem(e);
220
402
  if (!r) return [];
221
- const s = JSON.parse(r);
222
- return Array.isArray(s) ? s : [];
403
+ const n = JSON.parse(r);
404
+ return Array.isArray(n) ? n : [];
223
405
  } catch {
224
406
  return [];
225
407
  }
226
408
  }
227
- function He({
409
+ function Ue({
228
410
  apiUrl: e,
229
411
  persistMessages: t = !0,
230
- storageKeyPrefix: r = Ie,
231
- timeoutMs: s,
232
- translations: n,
233
- plugins: o
412
+ storageKeyPrefix: r = Be,
413
+ timeoutMs: n,
414
+ translations: s,
415
+ plugins: o,
416
+ streaming: i = !0
234
417
  }) {
235
- const c = Y(
236
- () => new Se(e, { debounceMs: 0, timeoutMs: s }),
237
- [e, s]
238
- ), a = De(r, e), u = t ? _e(a) : [], [l, d] = k(u), [R, p] = k(!1), [w, y] = k(null), [b, x] = k(!1), v = C(u.length), N = C(!1), E = C(u), I = C(o ?? []);
239
- I.current = o ?? [];
240
- const A = M(
241
- (f) => {
418
+ const l = se(
419
+ () => new Oe(e, { debounceMs: 0, timeoutMs: n }),
420
+ [e, n]
421
+ ), c = $e(r, e), u = t ? Pe(c) : [], [d, x] = L(u), [N, R] = L(!1), [T, p] = L(!1), [v, k] = L(
422
+ null
423
+ ), [H, w] = L(null), [f, E] = L(!1), F = I(u.length), W = I(!1), y = I(u), K = I(null), B = I(o ?? []);
424
+ B.current = o ?? [];
425
+ const _ = O(
426
+ (h) => {
242
427
  if (!t) return;
243
- const g = Z();
244
- if (g)
428
+ const A = ue();
429
+ if (A)
245
430
  try {
246
- const L = f.slice(-Oe);
247
- g.setItem(a, JSON.stringify(L));
431
+ const S = h.slice(-He);
432
+ A.setItem(c, JSON.stringify(S));
248
433
  } catch {
249
434
  }
250
435
  },
251
- [t, a]
252
- ), D = () => (v.current += 1, `msg-${v.current}`), S = M(
253
- (f, g) => {
254
- if (!n)
255
- return g ?? "Something went wrong. Please try again.";
256
- switch (f) {
436
+ [t, c]
437
+ ), m = () => (F.current += 1, `msg-${F.current}`), V = O(
438
+ (h, A) => {
439
+ if (!s)
440
+ return A ?? "Something went wrong. Please try again.";
441
+ switch (h) {
257
442
  case "TIMEOUT":
258
- return n.errorTimeout;
443
+ return s.errorTimeout;
259
444
  case "NETWORK_ERROR":
260
- return n.errorConnection;
445
+ return s.errorConnection;
261
446
  case "RATE_LIMITED":
262
- return g != null && g.includes("minute") ? n.errorRateLimitMinute : n.errorRateLimitHour;
447
+ return A != null && A.includes("minute") ? s.errorRateLimitMinute : s.errorRateLimitHour;
263
448
  case "VALIDATION_ERROR":
264
449
  case "CONFIG_ERROR":
265
450
  case "SERVICE_ERROR":
266
451
  case "UNKNOWN_ERROR":
267
452
  default:
268
- return g ?? n.errorGeneric;
453
+ return A ?? s.errorGeneric;
269
454
  }
270
455
  },
271
- [n]
272
- ), j = M((f) => !(f instanceof U) || f.code === "TIMEOUT" || f.code === "NETWORK_ERROR" || f.code === "RATE_LIMITED" || f.code === "SERVICE_ERROR" || f.code === "UNKNOWN_ERROR" || f.status >= 500 || f.status === 0, []), m = M(
273
- async (f) => {
274
- p(!0), N.current = !0, y(null), x(!1);
456
+ [s]
457
+ ), ee = O((h) => !(h instanceof j) || h.code === "TIMEOUT" || h.code === "NETWORK_ERROR" || h.code === "RATE_LIMITED" || h.code === "SERVICE_ERROR" || h.code === "UNKNOWN_ERROR" || h.status >= 500 || h.status === 0, []), J = O(
458
+ async (h) => {
459
+ R(!0), W.current = !0, w(null), E(!1);
460
+ const A = i && typeof l.streamMessage == "function";
461
+ let S = null;
462
+ const Y = (b) => {
463
+ if (S === null) {
464
+ S = m(), k(S);
465
+ const C = [
466
+ ...y.current,
467
+ { id: S, role: "assistant", content: "", ...b }
468
+ ];
469
+ y.current = C, x(C);
470
+ } else {
471
+ const C = S, M = y.current.map(
472
+ (P) => P.id === C ? { ...P, ...b } : P
473
+ );
474
+ y.current = M, x(M);
475
+ }
476
+ }, $ = () => {
477
+ if (S === null) return;
478
+ const b = S, C = y.current.filter((M) => M.id !== b);
479
+ y.current = C, x(C);
480
+ };
275
481
  try {
276
- const g = await c.sendMessage(f);
277
- let L = {
278
- id: D(),
482
+ let b, C, M, P = !1;
483
+ if (A) {
484
+ const G = new AbortController();
485
+ K.current = G, p(!0);
486
+ const q = await l.streamMessage(h, {
487
+ signal: G.signal,
488
+ onChunk: (ae, D) => Y({ content: D }),
489
+ onToolUse: (ae, D) => Y({ toolUses: [...D] })
490
+ });
491
+ b = q.reply, C = q.sources, M = q.toolUses, P = q.aborted ?? !1;
492
+ } else {
493
+ const G = await l.sendMessage(h);
494
+ b = G.reply, C = G.sources, M = G.toolUses;
495
+ }
496
+ if (P && !b) {
497
+ $();
498
+ return;
499
+ }
500
+ let U = {
501
+ id: S ?? m(),
279
502
  role: "assistant",
280
- content: g.reply,
281
- sources: g.sources
503
+ content: b,
504
+ sources: C,
505
+ toolUses: M
282
506
  };
283
- I.current.length > 0 && (L = await ke(
284
- I.current,
285
- L,
286
- { messages: f, apiUrl: e }
507
+ B.current.length > 0 && !P && (U = await _e(
508
+ B.current,
509
+ U,
510
+ { messages: h, apiUrl: e }
287
511
  ));
288
- const T = [...f, L];
289
- E.current = T, d(T), A(T);
290
- } catch (g) {
291
- if (g instanceof ae) return;
292
- if (I.current.length > 0) {
293
- const L = g instanceof Error ? g : new Error(String(g)), T = await Ae(I.current, L, {
294
- messages: f,
512
+ const Z = S !== null ? y.current.map(
513
+ (G) => G.id === U.id ? U : G
514
+ ) : [...h, U];
515
+ y.current = Z, x(Z), _(Z);
516
+ } catch (b) {
517
+ if (b instanceof le) return;
518
+ if (S !== null) {
519
+ _(y.current), b instanceof j ? w(V(b.code, b.message)) : w(
520
+ (s == null ? void 0 : s.errorConnection) ?? "Failed to connect. Please try again."
521
+ ), E(!1);
522
+ return;
523
+ }
524
+ if (B.current.length > 0) {
525
+ const C = b instanceof Error ? b : new Error(String(b)), M = await je(B.current, C, {
526
+ messages: h,
295
527
  apiUrl: e
296
528
  });
297
- if (T) {
298
- const B = {
299
- id: D(),
529
+ if (M) {
530
+ const P = {
531
+ id: m(),
300
532
  role: "assistant",
301
- content: T.content,
302
- sources: T.sources
303
- }, O = [...f, B];
304
- E.current = O, d(O), A(O), y(null), x(!1);
533
+ content: M.content,
534
+ sources: M.sources
535
+ }, U = [...h, P];
536
+ y.current = U, x(U), _(U), w(null), E(!1);
305
537
  return;
306
538
  }
307
539
  }
308
- g instanceof U ? y(S(g.code, g.message)) : y(
309
- (n == null ? void 0 : n.errorConnection) ?? "Failed to connect. Please try again."
310
- ), x(j(g));
540
+ b instanceof j ? w(V(b.code, b.message)) : w(
541
+ (s == null ? void 0 : s.errorConnection) ?? "Failed to connect. Please try again."
542
+ ), E(ee(b));
311
543
  } finally {
312
- p(!1), N.current = !1;
544
+ R(!1), W.current = !1, p(!1), k(null), K.current = null;
313
545
  }
314
546
  },
315
547
  [
316
548
  e,
317
- c,
318
- S,
319
- j,
320
- A,
321
- n
549
+ l,
550
+ V,
551
+ ee,
552
+ _,
553
+ i,
554
+ s
322
555
  ]
323
- ), P = M(
324
- async (f) => {
325
- const g = f.trim();
326
- if (!g || N.current) return;
327
- const L = {
328
- id: D(),
556
+ ), oe = O(() => {
557
+ var h;
558
+ (h = K.current) == null || h.abort();
559
+ }, []), ie = O(
560
+ async (h) => {
561
+ const A = h.trim();
562
+ if (!A || W.current) return;
563
+ const S = {
564
+ id: m(),
329
565
  role: "user",
330
- content: g
566
+ content: A
331
567
  };
332
- let T = L;
333
- if (I.current.length > 0) {
334
- const O = await Le(I.current, L, {
335
- messages: E.current,
568
+ let Y = S;
569
+ if (B.current.length > 0) {
570
+ const b = await De(B.current, S, {
571
+ messages: y.current,
336
572
  apiUrl: e
337
573
  });
338
- if (O.type === "abort") return;
339
- if (O.type === "respond") {
340
- const z = {
341
- id: D(),
574
+ if (b.type === "abort") return;
575
+ if (b.type === "respond") {
576
+ const C = {
577
+ id: m(),
342
578
  role: "assistant",
343
- content: O.reply.content,
344
- sources: O.reply.sources
345
- }, $ = [
346
- ...E.current,
347
- O.message,
348
- z
579
+ content: b.reply.content,
580
+ sources: b.reply.sources
581
+ }, M = [
582
+ ...y.current,
583
+ b.message,
584
+ C
349
585
  ];
350
- E.current = $, d($), A($), y(null), x(!1);
586
+ y.current = M, x(M), _(M), w(null), E(!1);
351
587
  return;
352
588
  }
353
- T = O.message;
589
+ Y = b.message;
354
590
  }
355
- const B = [...E.current, T];
356
- E.current = B, d(B), A(B), await m(B);
591
+ const $ = [...y.current, Y];
592
+ y.current = $, x($), _($), await J($);
357
593
  },
358
- [e, A, m]
359
- ), V = M(async () => {
360
- if (N.current) return;
361
- const f = E.current[E.current.length - 1];
362
- !f || f.role !== "user" || await m(E.current);
363
- }, [m]), K = M(() => {
364
- if (E.current = [], d([]), y(null), x(!1), t) {
365
- const f = Z();
366
- if (!f) return;
594
+ [e, _, J]
595
+ ), te = O(async () => {
596
+ if (W.current) return;
597
+ const h = y.current[y.current.length - 1];
598
+ !h || h.role !== "user" || await J(y.current);
599
+ }, [J]), re = O(() => {
600
+ if (y.current = [], x([]), w(null), E(!1), t) {
601
+ const h = ue();
602
+ if (!h) return;
367
603
  try {
368
- f.removeItem(a);
604
+ h.removeItem(c);
369
605
  } catch {
370
606
  }
371
607
  }
372
- }, [t, a]);
608
+ }, [t, c]);
373
609
  return {
374
- messages: l,
375
- isLoading: R,
376
- error: w,
377
- canRetry: b,
378
- sendMessage: P,
379
- retry: V,
380
- clearMessages: K
610
+ messages: d,
611
+ isLoading: N,
612
+ isStreaming: T,
613
+ streamingMessageId: v,
614
+ error: H,
615
+ canRetry: f,
616
+ sendMessage: ie,
617
+ stop: oe,
618
+ retry: te,
619
+ clearMessages: re
381
620
  };
382
621
  }
383
- function Be(e) {
384
- const [t, r] = k(() => typeof window > "u" ? !1 : window.matchMedia(e).matches);
385
- return H(() => {
386
- const s = window.matchMedia(e);
387
- r(s.matches);
388
- const n = (o) => r(o.matches);
389
- return s.addEventListener("change", n), () => s.removeEventListener("change", n);
622
+ function Ge(e) {
623
+ const [t, r] = L(() => typeof window > "u" ? !1 : window.matchMedia(e).matches);
624
+ return z(() => {
625
+ const n = window.matchMedia(e);
626
+ r(n.matches);
627
+ const s = (o) => r(o.matches);
628
+ return n.addEventListener("change", s), () => n.removeEventListener("change", s);
390
629
  }, [e]), t;
391
630
  }
392
- function F(e, t) {
631
+ function ne(e, t) {
393
632
  return e instanceof RegExp ? e.test(t) : t.toLowerCase().includes(e.toLowerCase());
394
633
  }
395
- function $e() {
396
- const e = document.documentElement, t = document.body, r = e.scrollTop || t.scrollTop || 0, s = Math.max(e.scrollHeight, t.scrollHeight), n = e.clientHeight || window.innerHeight, o = s - n;
634
+ function We() {
635
+ const e = document.documentElement, t = document.body, r = e.scrollTop || t.scrollTop || 0, n = Math.max(e.scrollHeight, t.scrollHeight), s = e.clientHeight || window.innerHeight, o = n - s;
397
636
  return o <= 0 ? 100 : r / o * 100;
398
637
  }
399
- function je({
638
+ function ze({
400
639
  triggers: e,
401
640
  enabled: t,
402
641
  onOpen: r,
403
- onGreeting: s
642
+ onGreeting: n
404
643
  }) {
405
- H(() => {
644
+ z(() => {
406
645
  if (!t || !e || e.length === 0) return;
407
- const n = /* @__PURE__ */ new Set(), o = [], c = typeof window < "u" ? window.location.href : "", a = (u, l) => {
408
- n.has(u) || (n.add(u), l === "open" ? r() : s(l.greeting));
646
+ const s = /* @__PURE__ */ new Set(), o = [], i = typeof window < "u" ? window.location.href : "", l = (c, u) => {
647
+ s.has(c) || (s.add(c), u === "open" ? r() : n(u.greeting));
409
648
  };
410
- return e.forEach((u, l) => {
411
- switch (u.on) {
649
+ return e.forEach((c, u) => {
650
+ switch (c.on) {
412
651
  case "url": {
413
- F(u.pattern, c) && a(l, u.action);
652
+ ne(c.pattern, i) && l(u, c.action);
414
653
  break;
415
654
  }
416
655
  case "time": {
417
- if (u.matchUrl && !F(u.matchUrl, c))
656
+ if (c.matchUrl && !ne(c.matchUrl, i))
418
657
  return;
419
658
  const d = window.setTimeout(
420
- () => a(l, u.action),
421
- Math.max(0, u.seconds * 1e3)
659
+ () => l(u, c.action),
660
+ Math.max(0, c.seconds * 1e3)
422
661
  );
423
662
  o.push(() => window.clearTimeout(d));
424
663
  break;
425
664
  }
426
665
  case "scroll": {
427
- if (u.matchUrl && !F(u.matchUrl, c))
666
+ if (c.matchUrl && !ne(c.matchUrl, i))
428
667
  return;
429
668
  const d = () => {
430
- $e() >= u.percent && a(l, u.action);
669
+ We() >= c.percent && l(u, c.action);
431
670
  };
432
671
  d(), window.addEventListener("scroll", d, { passive: !0 }), o.push(() => window.removeEventListener("scroll", d));
433
672
  break;
434
673
  }
435
674
  case "exit-intent": {
436
- if (u.matchUrl && !F(u.matchUrl, c))
675
+ if (c.matchUrl && !ne(c.matchUrl, i))
437
676
  return;
438
- const d = (R) => {
439
- R.clientY <= 0 && a(l, u.action);
677
+ const d = (x) => {
678
+ x.clientY <= 0 && l(u, c.action);
440
679
  };
441
680
  document.addEventListener("mouseleave", d), o.push(
442
681
  () => document.removeEventListener("mouseleave", d)
@@ -445,25 +684,25 @@ function je({
445
684
  }
446
685
  }
447
686
  }), () => {
448
- o.forEach((u) => u());
687
+ o.forEach((c) => c());
449
688
  };
450
- }, [e, t, r, s]);
689
+ }, [e, t, r, n]);
451
690
  }
452
- const Pe = {
691
+ const Fe = {
453
692
  "bottom-right": "bottom-6 right-6",
454
693
  "bottom-left": "bottom-6 left-6",
455
694
  "top-right": "top-6 right-6",
456
695
  "top-left": "top-6 left-6"
457
- }, Ge = Me(function({ isOpen: t, onClick: r, position: s = "bottom-right", translations: n }, o) {
458
- const c = t ? (n == null ? void 0 : n.closeChat) ?? "Close chat" : (n == null ? void 0 : n.openChat) ?? "Open chat";
459
- return /* @__PURE__ */ i(
696
+ }, Ve = ke(function({ isOpen: t, onClick: r, position: n = "bottom-right", translations: s }, o) {
697
+ const i = t ? (s == null ? void 0 : s.closeChat) ?? "Close chat" : (s == null ? void 0 : s.openChat) ?? "Open chat";
698
+ return /* @__PURE__ */ a(
460
699
  "button",
461
700
  {
462
701
  ref: o,
463
702
  onClick: r,
464
- "aria-label": c,
465
- className: `fixed ${Pe[s]} z-50 flex h-14 w-14 items-center justify-center rounded-claudius-full bg-claudius-accent text-claudius-accent-text shadow-claudius-floating transition-transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-claudius-accent focus:ring-offset-2`,
466
- children: t ? /* @__PURE__ */ h(
703
+ "aria-label": i,
704
+ className: `fixed ${Fe[n]} z-50 flex h-14 w-14 items-center justify-center rounded-claudius-full bg-claudius-accent text-claudius-accent-text shadow-claudius-floating transition-transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-claudius-accent focus:ring-offset-2`,
705
+ children: t ? /* @__PURE__ */ g(
467
706
  "svg",
468
707
  {
469
708
  width: "24",
@@ -476,11 +715,11 @@ const Pe = {
476
715
  strokeLinejoin: "round",
477
716
  "aria-hidden": "true",
478
717
  children: [
479
- /* @__PURE__ */ i("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
480
- /* @__PURE__ */ i("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
718
+ /* @__PURE__ */ a("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
719
+ /* @__PURE__ */ a("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
481
720
  ]
482
721
  }
483
- ) : /* @__PURE__ */ i(
722
+ ) : /* @__PURE__ */ a(
484
723
  "svg",
485
724
  {
486
725
  width: "24",
@@ -492,25 +731,25 @@ const Pe = {
492
731
  strokeLinecap: "round",
493
732
  strokeLinejoin: "round",
494
733
  "aria-hidden": "true",
495
- children: /* @__PURE__ */ i("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
734
+ children: /* @__PURE__ */ a("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
496
735
  }
497
736
  )
498
737
  }
499
738
  );
500
- }), Ue = J(function({
739
+ }), Ye = de(function({
501
740
  count: t,
502
741
  isActive: r,
503
- onClick: s
742
+ onClick: n
504
743
  }) {
505
- return /* @__PURE__ */ h(
744
+ return /* @__PURE__ */ g(
506
745
  "button",
507
746
  {
508
- onClick: s,
747
+ onClick: n,
509
748
  "aria-label": "View sources",
510
749
  title: "View sources",
511
750
  className: `group relative flex h-7 w-7 items-center justify-center rounded-claudius-full transition-colors ${r ? "bg-claudius-accent text-claudius-accent-text" : "text-claudius-text-muted hover:bg-claudius-surface-muted hover:text-claudius-text"}`,
512
751
  children: [
513
- /* @__PURE__ */ h(
752
+ /* @__PURE__ */ g(
514
753
  "svg",
515
754
  {
516
755
  width: "14",
@@ -523,19 +762,19 @@ const Pe = {
523
762
  strokeLinejoin: "round",
524
763
  "aria-hidden": "true",
525
764
  children: [
526
- /* @__PURE__ */ i("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
527
- /* @__PURE__ */ i("polyline", { points: "14 2 14 8 20 8" }),
528
- /* @__PURE__ */ i("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
529
- /* @__PURE__ */ i("line", { x1: "16", y1: "17", x2: "8", y2: "17" })
765
+ /* @__PURE__ */ a("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
766
+ /* @__PURE__ */ a("polyline", { points: "14 2 14 8 20 8" }),
767
+ /* @__PURE__ */ a("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
768
+ /* @__PURE__ */ a("line", { x1: "16", y1: "17", x2: "8", y2: "17" })
530
769
  ]
531
770
  }
532
771
  ),
533
- /* @__PURE__ */ i("span", { className: "absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-claudius-full bg-claudius-accent px-1 text-[10px] font-bold text-claudius-accent-text", children: t })
772
+ /* @__PURE__ */ a("span", { className: "absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-claudius-full bg-claudius-accent px-1 text-[10px] font-bold text-claudius-accent-text", children: t })
534
773
  ]
535
774
  }
536
775
  );
537
- }), We = ["http:", "https:"];
538
- function le(e) {
776
+ }), Ke = ["http:", "https:"];
777
+ function ve(e) {
539
778
  if (!e || typeof e != "string")
540
779
  return null;
541
780
  const t = e.trim();
@@ -543,16 +782,117 @@ function le(e) {
543
782
  return null;
544
783
  try {
545
784
  const r = new URL(t);
546
- return We.includes(r.protocol) ? t : null;
785
+ return Ke.includes(r.protocol) ? t : null;
547
786
  } catch {
548
787
  return null;
549
788
  }
550
789
  }
551
- const ne = /(https?:\/\/[^\s)]+)/, se = /(\*\*[^*]+\*\*)/, oe = /(\*[^*]+\*)/;
552
- function ze(e, t) {
553
- const r = e.match(/[.,;:!?'"]+$/), s = r ? e.slice(0, -r[0].length) : e, n = r ? r[0] : "", o = le(s);
554
- return o ? /* @__PURE__ */ h(Te, { children: [
555
- /* @__PURE__ */ h(
790
+ function qe(e) {
791
+ const t = e.lastIndexOf(`
792
+ `), r = t === -1 ? "" : e.slice(0, t + 1);
793
+ let n = t === -1 ? e : e.slice(t + 1);
794
+ return n = Ze(n), n = Qe(n), r + n;
795
+ }
796
+ function Je(e) {
797
+ const t = [];
798
+ for (let r = 0; r < e.length - 1; r++)
799
+ e[r] === "*" && e[r + 1] === "*" && (t.push(r), r++);
800
+ return t;
801
+ }
802
+ function Xe(e) {
803
+ const t = [];
804
+ for (let r = 0; r < e.length; r++)
805
+ if (e[r] === "*") {
806
+ if (e[r + 1] === "*") {
807
+ r++;
808
+ continue;
809
+ }
810
+ t.push(r);
811
+ }
812
+ return t;
813
+ }
814
+ function Ze(e) {
815
+ const t = Je(e);
816
+ if (t.length % 2 === 0) return e;
817
+ const r = t[t.length - 1], n = e.slice(r + 2);
818
+ return n.trim() === "" ? e.slice(0, r) + n : e + "**";
819
+ }
820
+ function Qe(e) {
821
+ const t = Xe(e);
822
+ if (t.length % 2 === 0) return e;
823
+ const r = t[t.length - 1], n = e.slice(r + 1);
824
+ return n.trim() === "" ? e.slice(0, r) + n : e + "*";
825
+ }
826
+ function et({
827
+ toolUse: e,
828
+ usedLabel: t,
829
+ detailsLabel: r
830
+ }) {
831
+ const [n, s] = L(!1), o = e.input !== void 0 || e.result !== void 0;
832
+ return /* @__PURE__ */ g("div", { className: "text-xs text-claudius-text-muted", children: [
833
+ /* @__PURE__ */ g(
834
+ "button",
835
+ {
836
+ type: "button",
837
+ disabled: !o,
838
+ onClick: () => s((i) => !i),
839
+ "aria-expanded": o ? n : void 0,
840
+ className: "flex items-center gap-1.5 rounded-claudius-full border border-claudius-border bg-claudius-surface px-2 py-0.5 hover:opacity-80 disabled:cursor-default disabled:hover:opacity-100",
841
+ children: [
842
+ /* @__PURE__ */ a(
843
+ "svg",
844
+ {
845
+ width: "11",
846
+ height: "11",
847
+ viewBox: "0 0 24 24",
848
+ fill: "none",
849
+ stroke: "currentColor",
850
+ strokeWidth: "2",
851
+ strokeLinecap: "round",
852
+ strokeLinejoin: "round",
853
+ "aria-hidden": "true",
854
+ children: /* @__PURE__ */ a("path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" })
855
+ }
856
+ ),
857
+ /* @__PURE__ */ g("span", { children: [
858
+ t,
859
+ " ",
860
+ /* @__PURE__ */ a("span", { className: "font-mono text-claudius-text", children: e.name }),
861
+ e.isError && /* @__PURE__ */ a("span", { className: "text-claudius-error", children: " ✕" })
862
+ ] }),
863
+ o && /* @__PURE__ */ g(xe, { children: [
864
+ /* @__PURE__ */ a("span", { className: "sr-only", children: r }),
865
+ /* @__PURE__ */ a(
866
+ "svg",
867
+ {
868
+ width: "10",
869
+ height: "10",
870
+ viewBox: "0 0 24 24",
871
+ fill: "none",
872
+ stroke: "currentColor",
873
+ strokeWidth: "2",
874
+ strokeLinecap: "round",
875
+ strokeLinejoin: "round",
876
+ "aria-hidden": "true",
877
+ className: n ? "rotate-180" : void 0,
878
+ children: /* @__PURE__ */ a("polyline", { points: "6 9 12 15 18 9" })
879
+ }
880
+ )
881
+ ] })
882
+ ]
883
+ }
884
+ ),
885
+ n && o && /* @__PURE__ */ g("div", { className: "mt-1 overflow-x-auto rounded-claudius-sm border border-claudius-border bg-claudius-field p-2 font-mono", children: [
886
+ e.input !== void 0 && /* @__PURE__ */ a("pre", { className: "whitespace-pre-wrap break-all", children: JSON.stringify(e.input, null, 2) }),
887
+ e.result !== void 0 && /* @__PURE__ */ a("pre", { className: "mt-1 whitespace-pre-wrap break-all border-t border-claudius-border pt-1", children: e.result })
888
+ ] })
889
+ ] });
890
+ }
891
+ const me = /(https?:\/\/[^\s)]+)/, ge = /(\*\*[^*]+\*\*)/, pe = /(\*[^*]+\*)/;
892
+ function tt(e, t) {
893
+ const r = e.match(/[.,;:!?'"]+$/), n = r ? e.slice(0, -r[0].length) : e, s = r ? r[0] : "", o = ve(n);
894
+ return o ? /* @__PURE__ */ g(xe, { children: [
895
+ /* @__PURE__ */ g(
556
896
  "a",
557
897
  {
558
898
  href: o,
@@ -561,114 +901,148 @@ function ze(e, t) {
561
901
  className: "underline font-medium hover:opacity-80 text-claudius-link",
562
902
  children: [
563
903
  o.replace(/^https?:\/\//, ""),
564
- /* @__PURE__ */ i("span", { className: "sr-only", children: " (opens in a new tab)" })
904
+ /* @__PURE__ */ a("span", { className: "sr-only", children: " (opens in a new tab)" })
565
905
  ]
566
906
  },
567
907
  t
568
908
  ),
569
- n
909
+ s
570
910
  ] }) : e;
571
911
  }
572
- function Fe(e, t) {
573
- const r = e.split(se), s = [];
574
- return r.forEach((n, o) => {
575
- if (se.test(n)) {
576
- const c = n.slice(2, -2);
577
- s.push(/* @__PURE__ */ i("strong", { children: c }, `${t}-b${o}`));
912
+ function rt(e, t) {
913
+ const r = e.split(ge), n = [];
914
+ return r.forEach((s, o) => {
915
+ if (ge.test(s)) {
916
+ const i = s.slice(2, -2);
917
+ n.push(/* @__PURE__ */ a("strong", { children: i }, `${t}-b${o}`));
578
918
  } else
579
- n.split(oe).forEach((a, u) => {
580
- if (oe.test(a)) {
581
- const l = a.slice(1, -1);
582
- s.push(/* @__PURE__ */ i("em", { children: l }, `${t}-b${o}-i${u}`));
919
+ s.split(pe).forEach((l, c) => {
920
+ if (pe.test(l)) {
921
+ const u = l.slice(1, -1);
922
+ n.push(/* @__PURE__ */ a("em", { children: u }, `${t}-b${o}-i${c}`));
583
923
  } else
584
- a.split(ne).forEach((d, R) => {
585
- ne.test(d) ? s.push(
586
- ze(d, `${t}-b${o}-i${u}-u${R}`)
587
- ) : d && s.push(d);
924
+ l.split(me).forEach((d, x) => {
925
+ me.test(d) ? n.push(
926
+ tt(d, `${t}-b${o}-i${c}-u${x}`)
927
+ ) : d && n.push(d);
588
928
  });
589
929
  });
590
- }), s;
930
+ }), n;
591
931
  }
592
- function Ye(e) {
932
+ function nt(e) {
593
933
  const t = e.split(`
594
934
  `);
595
- return t.map((r, s) => /* @__PURE__ */ h("span", { children: [
596
- Fe(r, `l${s}`),
597
- s < t.length - 1 && /* @__PURE__ */ i("br", {})
598
- ] }, s));
935
+ return t.map((r, n) => /* @__PURE__ */ g("span", { children: [
936
+ rt(r, `l${n}`),
937
+ n < t.length - 1 && /* @__PURE__ */ a("br", {})
938
+ ] }, n));
599
939
  }
600
- const Ve = J(function({
940
+ const st = de(function({
601
941
  role: t,
602
942
  content: r,
943
+ isStreaming: n = !1,
603
944
  sources: s,
604
- onSourceClick: n,
605
- isSourceActive: o
945
+ toolUses: o,
946
+ toolUsedLabel: i = "Used tool:",
947
+ toolDetailsLabel: l = "Tool details",
948
+ onSourceClick: c,
949
+ isSourceActive: u
606
950
  }) {
607
- const c = t === "user";
608
- return /* @__PURE__ */ h("div", { className: `${c ? "ml-auto" : "mr-auto"} max-w-[85%]`, children: [
609
- /* @__PURE__ */ i(
951
+ const d = t === "user", x = n ? qe(r) : r, N = d || r !== "" || !(o != null && o.length);
952
+ return /* @__PURE__ */ g("div", { className: `${d ? "ml-auto" : "mr-auto"} max-w-[85%]`, children: [
953
+ N && /* @__PURE__ */ a(
610
954
  "div",
611
955
  {
612
- className: `rounded-claudius-bubble px-4 py-2.5 text-sm leading-relaxed font-body ${c ? "bg-claudius-user-bubble text-claudius-user-bubble-text rounded-br-claudius-tail" : "bg-claudius-assistant-bubble text-claudius-assistant-bubble-text rounded-bl-claudius-tail"}`,
613
- children: Ye(r)
956
+ className: `rounded-claudius-bubble px-4 py-2.5 text-sm leading-relaxed font-body ${d ? "bg-claudius-user-bubble text-claudius-user-bubble-text rounded-br-claudius-tail" : "bg-claudius-assistant-bubble text-claudius-assistant-bubble-text rounded-bl-claudius-tail"}`,
957
+ children: nt(x)
614
958
  }
615
959
  ),
616
- !c && s && s.length > 0 && n && /* @__PURE__ */ i("div", { className: "mt-1", children: /* @__PURE__ */ i(
617
- Ue,
960
+ !d && o && o.length > 0 && /* @__PURE__ */ a("div", { className: "mt-1 space-y-1", children: o.map((R, T) => /* @__PURE__ */ a(
961
+ et,
962
+ {
963
+ toolUse: R,
964
+ usedLabel: i,
965
+ detailsLabel: l
966
+ },
967
+ `${R.name}-${T}`
968
+ )) }),
969
+ !d && s && s.length > 0 && c && /* @__PURE__ */ a("div", { className: "mt-1", children: /* @__PURE__ */ a(
970
+ Ye,
618
971
  {
619
972
  count: s.length,
620
- isActive: o ?? !1,
621
- onClick: n
973
+ isActive: u ?? !1,
974
+ onClick: c
622
975
  }
623
976
  ) })
624
977
  ] });
625
- }), X = 2e3, Ke = 1800;
626
- function qe({
978
+ }), ce = 2e3, ot = 1800;
979
+ function it({
627
980
  onSend: e,
628
981
  isLoading: t,
629
- placeholder: r,
630
- translations: s
982
+ isStreaming: r = !1,
983
+ onStop: n,
984
+ placeholder: s,
985
+ translations: o
631
986
  }) {
632
- const [n, o] = k(""), c = C(null), a = n.length, u = a >= Ke, l = a >= X, d = r ?? (s == null ? void 0 : s.placeholder) ?? "Type your message...", R = (s == null ? void 0 : s.sendMessage) ?? "Send message", p = (s == null ? void 0 : s.typeYourMessage) ?? "Type your message";
633
- return H(() => {
634
- var b;
635
- t || (b = c.current) == null || b.focus();
636
- }, [t]), /* @__PURE__ */ h(
987
+ const [i, l] = L(""), c = I(null), u = i.length, d = u >= ot, x = u >= ce, N = s ?? (o == null ? void 0 : o.placeholder) ?? "Type your message...", R = (o == null ? void 0 : o.sendMessage) ?? "Send message", T = (o == null ? void 0 : o.stopGenerating) ?? "Stop generating", p = (o == null ? void 0 : o.typeYourMessage) ?? "Type your message", v = r && !!n;
988
+ return z(() => {
989
+ var w;
990
+ t || (w = c.current) == null || w.focus();
991
+ }, [t]), /* @__PURE__ */ g(
637
992
  "form",
638
993
  {
639
- onSubmit: (b) => {
640
- b.preventDefault();
641
- const x = n.trim();
642
- !x || l || (e(x), o(""));
994
+ onSubmit: (w) => {
995
+ w.preventDefault();
996
+ const f = i.trim();
997
+ !f || x || (e(f), l(""));
643
998
  },
644
999
  className: "border-t border-claudius-border bg-claudius-surface p-3",
645
1000
  children: [
646
- /* @__PURE__ */ h("div", { className: "flex gap-2", children: [
647
- /* @__PURE__ */ i(
1001
+ /* @__PURE__ */ g("div", { className: "flex gap-2", children: [
1002
+ /* @__PURE__ */ a(
648
1003
  "input",
649
1004
  {
650
1005
  ref: c,
651
1006
  type: "text",
652
- value: n,
653
- onChange: (b) => {
654
- const x = b.target.value;
655
- x.length <= X && o(x);
1007
+ value: i,
1008
+ onChange: (w) => {
1009
+ const f = w.target.value;
1010
+ f.length <= ce && l(f);
656
1011
  },
657
- placeholder: d,
1012
+ placeholder: N,
658
1013
  disabled: t,
659
1014
  "aria-label": p,
660
- "aria-describedby": u ? "char-count" : void 0,
1015
+ "aria-describedby": d ? "char-count" : void 0,
661
1016
  className: "flex-1 rounded-claudius-sm border border-claudius-border bg-claudius-field px-3 py-2 text-sm font-body text-claudius-text placeholder:text-claudius-text-muted focus:border-claudius-accent focus:outline-none focus:ring-1 focus:ring-claudius-accent disabled:opacity-50"
662
1017
  }
663
1018
  ),
664
- /* @__PURE__ */ i(
1019
+ v ? /* @__PURE__ */ a(
1020
+ "button",
1021
+ {
1022
+ type: "button",
1023
+ onClick: n,
1024
+ "aria-label": T,
1025
+ className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-claudius-sm bg-claudius-accent text-claudius-accent-text transition-colors hover:opacity-90",
1026
+ children: /* @__PURE__ */ a(
1027
+ "svg",
1028
+ {
1029
+ width: "16",
1030
+ height: "16",
1031
+ viewBox: "0 0 24 24",
1032
+ fill: "currentColor",
1033
+ "aria-hidden": "true",
1034
+ children: /* @__PURE__ */ a("rect", { x: "6", y: "6", width: "12", height: "12", rx: "1.5" })
1035
+ }
1036
+ )
1037
+ }
1038
+ ) : /* @__PURE__ */ a(
665
1039
  "button",
666
1040
  {
667
1041
  type: "submit",
668
- disabled: t || l,
1042
+ disabled: t || x,
669
1043
  "aria-label": R,
670
1044
  className: "flex h-11 w-11 shrink-0 items-center justify-center rounded-claudius-sm bg-claudius-accent text-claudius-accent-text transition-colors hover:opacity-90 disabled:opacity-50",
671
- children: /* @__PURE__ */ h(
1045
+ children: /* @__PURE__ */ g(
672
1046
  "svg",
673
1047
  {
674
1048
  width: "16",
@@ -681,24 +1055,24 @@ function qe({
681
1055
  strokeLinejoin: "round",
682
1056
  "aria-hidden": "true",
683
1057
  children: [
684
- /* @__PURE__ */ i("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
685
- /* @__PURE__ */ i("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
1058
+ /* @__PURE__ */ a("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
1059
+ /* @__PURE__ */ a("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
686
1060
  ]
687
1061
  }
688
1062
  )
689
1063
  }
690
1064
  )
691
1065
  ] }),
692
- u && /* @__PURE__ */ h(
1066
+ d && /* @__PURE__ */ g(
693
1067
  "div",
694
1068
  {
695
1069
  id: "char-count",
696
- className: `mt-1 text-xs text-right ${l ? "text-claudius-error" : "text-claudius-text-muted"}`,
1070
+ className: `mt-1 text-xs text-right ${x ? "text-claudius-error" : "text-claudius-text-muted"}`,
697
1071
  "aria-live": "polite",
698
1072
  children: [
699
- a,
1073
+ u,
700
1074
  "/",
701
- X
1075
+ ce
702
1076
  ]
703
1077
  }
704
1078
  )
@@ -706,40 +1080,40 @@ function qe({
706
1080
  }
707
1081
  );
708
1082
  }
709
- const Xe = ["blog", "page", "external"], Ze = {
1083
+ const at = ["blog", "page", "external"], ct = {
710
1084
  blog: "Blog",
711
1085
  page: "Page",
712
1086
  external: "External"
713
1087
  };
714
- function Je(e) {
1088
+ function lt(e) {
715
1089
  try {
716
1090
  return new URL(e).hostname;
717
1091
  } catch {
718
1092
  return e;
719
1093
  }
720
1094
  }
721
- const Qe = J(function({
1095
+ const ut = de(function({
722
1096
  sources: t,
723
1097
  onClose: r
724
1098
  }) {
725
- const s = Xe.map((o) => ({
1099
+ const n = at.map((o) => ({
726
1100
  type: o,
727
- label: Ze[o],
728
- items: t.filter((c) => c.type === o)
729
- })).filter((o) => o.items.length > 0), n = t.length === 1 ? "1 source found" : `${t.length} sources found`;
730
- return /* @__PURE__ */ h("div", { className: "absolute inset-y-0 left-0 z-10 flex w-[280px] flex-col border-r-2 border-claudius-border bg-claudius-surface rounded-r-claudius-lg transition-transform duration-200 ease-out", children: [
731
- /* @__PURE__ */ h("div", { className: "flex items-center justify-between border-b border-claudius-border px-4 py-3", children: [
732
- /* @__PURE__ */ h("div", { children: [
733
- /* @__PURE__ */ i("h3", { className: "text-sm font-heading font-semibold text-claudius-text", children: "Sources" }),
734
- /* @__PURE__ */ i("p", { className: "text-xs text-claudius-text-muted", children: n })
1101
+ label: ct[o],
1102
+ items: t.filter((i) => i.type === o)
1103
+ })).filter((o) => o.items.length > 0), s = t.length === 1 ? "1 source found" : `${t.length} sources found`;
1104
+ return /* @__PURE__ */ g("div", { className: "absolute inset-y-0 left-0 z-10 flex w-[280px] flex-col border-r-2 border-claudius-border bg-claudius-surface rounded-r-claudius-lg transition-transform duration-200 ease-out", children: [
1105
+ /* @__PURE__ */ g("div", { className: "flex items-center justify-between border-b border-claudius-border px-4 py-3", children: [
1106
+ /* @__PURE__ */ g("div", { children: [
1107
+ /* @__PURE__ */ a("h3", { className: "text-sm font-heading font-semibold text-claudius-text", children: "Sources" }),
1108
+ /* @__PURE__ */ a("p", { className: "text-xs text-claudius-text-muted", children: s })
735
1109
  ] }),
736
- /* @__PURE__ */ i(
1110
+ /* @__PURE__ */ a(
737
1111
  "button",
738
1112
  {
739
1113
  onClick: r,
740
1114
  "aria-label": "Close sources",
741
1115
  className: "flex h-7 w-7 items-center justify-center rounded-claudius-full text-claudius-text-muted transition-colors hover:bg-claudius-surface-muted hover:text-claudius-text",
742
- children: /* @__PURE__ */ h(
1116
+ children: /* @__PURE__ */ g(
743
1117
  "svg",
744
1118
  {
745
1119
  width: "14",
@@ -752,45 +1126,45 @@ const Qe = J(function({
752
1126
  strokeLinejoin: "round",
753
1127
  "aria-hidden": "true",
754
1128
  children: [
755
- /* @__PURE__ */ i("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
756
- /* @__PURE__ */ i("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1129
+ /* @__PURE__ */ a("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1130
+ /* @__PURE__ */ a("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
757
1131
  ]
758
1132
  }
759
1133
  )
760
1134
  }
761
1135
  )
762
1136
  ] }),
763
- /* @__PURE__ */ i("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-4", children: s.map((o) => /* @__PURE__ */ h("div", { children: [
764
- /* @__PURE__ */ i("h4", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-claudius-text-muted", children: o.label }),
765
- /* @__PURE__ */ i("div", { className: "space-y-2", children: o.items.map((c) => {
766
- const a = le(c.url);
767
- return a ? /* @__PURE__ */ h(
1137
+ /* @__PURE__ */ a("div", { className: "flex-1 overflow-y-auto px-3 py-3 space-y-4", children: n.map((o) => /* @__PURE__ */ g("div", { children: [
1138
+ /* @__PURE__ */ a("h4", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-claudius-text-muted", children: o.label }),
1139
+ /* @__PURE__ */ a("div", { className: "space-y-2", children: o.items.map((i) => {
1140
+ const l = ve(i.url);
1141
+ return l ? /* @__PURE__ */ g(
768
1142
  "a",
769
1143
  {
770
- href: a,
1144
+ href: l,
771
1145
  target: "_blank",
772
1146
  rel: "noopener noreferrer",
773
1147
  className: "block rounded-claudius-md border-2 border-claudius-border bg-claudius-surface-muted p-3 transition-colors hover:bg-claudius-border",
774
1148
  children: [
775
- /* @__PURE__ */ i("p", { className: "truncate text-sm font-medium text-claudius-text", children: c.title }),
776
- /* @__PURE__ */ i("p", { className: "mt-0.5 text-xs text-claudius-text-muted", children: Je(a) })
1149
+ /* @__PURE__ */ a("p", { className: "truncate text-sm font-medium text-claudius-text", children: i.title }),
1150
+ /* @__PURE__ */ a("p", { className: "mt-0.5 text-xs text-claudius-text-muted", children: lt(l) })
777
1151
  ]
778
1152
  },
779
- a
1153
+ l
780
1154
  ) : null;
781
1155
  }) })
782
1156
  ] }, o.type)) })
783
1157
  ] });
784
1158
  });
785
- function et({
1159
+ function dt({
786
1160
  title: e,
787
1161
  subtitle: t,
788
1162
  titleId: r,
789
- closeLabel: s,
790
- onClose: n
1163
+ closeLabel: n,
1164
+ onClose: s
791
1165
  }) {
792
- return /* @__PURE__ */ h("div", { className: "flex items-center gap-3 bg-claudius-accent px-5 py-4", children: [
793
- /* @__PURE__ */ i(
1166
+ return /* @__PURE__ */ g("div", { className: "flex items-center gap-3 bg-claudius-accent px-5 py-4", children: [
1167
+ /* @__PURE__ */ a(
794
1168
  "div",
795
1169
  {
796
1170
  "aria-hidden": "true",
@@ -798,8 +1172,8 @@ function et({
798
1172
  children: e.charAt(0).toUpperCase()
799
1173
  }
800
1174
  ),
801
- /* @__PURE__ */ h("div", { className: "flex-1", children: [
802
- /* @__PURE__ */ i(
1175
+ /* @__PURE__ */ g("div", { className: "flex-1", children: [
1176
+ /* @__PURE__ */ a(
803
1177
  "h2",
804
1178
  {
805
1179
  id: r,
@@ -807,15 +1181,15 @@ function et({
807
1181
  children: e
808
1182
  }
809
1183
  ),
810
- /* @__PURE__ */ i("p", { className: "text-xs text-claudius-accent-text", children: t })
1184
+ /* @__PURE__ */ a("p", { className: "text-xs text-claudius-accent-text", children: t })
811
1185
  ] }),
812
- /* @__PURE__ */ i(
1186
+ /* @__PURE__ */ a(
813
1187
  "button",
814
1188
  {
815
- onClick: n,
816
- "aria-label": s,
1189
+ onClick: s,
1190
+ "aria-label": n,
817
1191
  className: "flex h-10 w-10 items-center justify-center rounded-claudius-full text-claudius-accent-text-muted transition-colors hover:bg-claudius-accent-soft hover:text-claudius-accent-text",
818
- children: /* @__PURE__ */ h(
1192
+ children: /* @__PURE__ */ g(
819
1193
  "svg",
820
1194
  {
821
1195
  width: "18",
@@ -828,8 +1202,8 @@ function et({
828
1202
  strokeLinejoin: "round",
829
1203
  "aria-hidden": "true",
830
1204
  children: [
831
- /* @__PURE__ */ i("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
832
- /* @__PURE__ */ i("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1205
+ /* @__PURE__ */ a("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1206
+ /* @__PURE__ */ a("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
833
1207
  ]
834
1208
  }
835
1209
  )
@@ -837,19 +1211,19 @@ function et({
837
1211
  )
838
1212
  ] });
839
1213
  }
840
- function tt({
1214
+ function ft({
841
1215
  message: e,
842
1216
  retryLabel: t,
843
1217
  onRetry: r
844
1218
  }) {
845
- return /* @__PURE__ */ h(
1219
+ return /* @__PURE__ */ g(
846
1220
  "div",
847
1221
  {
848
1222
  role: "alert",
849
1223
  className: "mx-auto flex max-w-[90%] flex-col items-center gap-2 rounded-claudius-sm bg-claudius-error-surface px-3 py-2 text-center text-xs text-claudius-error",
850
1224
  children: [
851
- /* @__PURE__ */ i("span", { children: e }),
852
- r && /* @__PURE__ */ i(
1225
+ /* @__PURE__ */ a("span", { children: e }),
1226
+ r && /* @__PURE__ */ a(
853
1227
  "button",
854
1228
  {
855
1229
  type: "button",
@@ -862,68 +1236,68 @@ function tt({
862
1236
  }
863
1237
  );
864
1238
  }
865
- function rt({ label: e }) {
866
- return /* @__PURE__ */ i(
1239
+ function ht({ label: e }) {
1240
+ return /* @__PURE__ */ a(
867
1241
  "div",
868
1242
  {
869
1243
  role: "status",
870
1244
  "aria-live": "polite",
871
1245
  "aria-label": e,
872
1246
  className: "mr-auto flex max-w-[85%]",
873
- children: /* @__PURE__ */ h("div", { className: "flex gap-1 rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-3", children: [
874
- /* @__PURE__ */ i("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:0ms]" }),
875
- /* @__PURE__ */ i("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:150ms]" }),
876
- /* @__PURE__ */ i("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:300ms]" })
1247
+ children: /* @__PURE__ */ g("div", { className: "flex gap-1 rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-3", children: [
1248
+ /* @__PURE__ */ a("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:0ms]" }),
1249
+ /* @__PURE__ */ a("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:150ms]" }),
1250
+ /* @__PURE__ */ a("span", { className: "h-2 w-2 motion-safe:animate-bounce rounded-claudius-full bg-claudius-text-muted [animation-delay:300ms]" })
877
1251
  ] })
878
1252
  }
879
1253
  );
880
1254
  }
881
- function nt(e, t, r) {
882
- const [s, n] = k(0), o = C(0), c = C(0), a = C(0), u = C(!1);
883
- return H(() => {
884
- const l = e.current;
885
- if (!r || !l) return;
886
- const d = (w) => {
887
- if (l.scrollTop > 0) {
888
- u.current = !1;
1255
+ function mt(e, t, r) {
1256
+ const [n, s] = L(0), o = I(0), i = I(0), l = I(0), c = I(!1);
1257
+ return z(() => {
1258
+ const u = e.current;
1259
+ if (!r || !u) return;
1260
+ const d = (R) => {
1261
+ if (u.scrollTop > 0) {
1262
+ c.current = !1;
889
1263
  return;
890
1264
  }
891
- u.current = !0, c.current = w.touches[0].clientY, a.current = Date.now();
892
- }, R = (w) => {
893
- if (!u.current) return;
894
- let y = w.touches[0].clientY - c.current;
895
- y < 0 && (y = y * 0.3), o.current = y, n(y);
896
- }, p = () => {
897
- if (!u.current) return;
898
- u.current = !1;
899
- const w = o.current, y = (Date.now() - a.current) / 1e3, b = l.getBoundingClientRect().height, x = y > 0.05 && w > 0 && w / y > 500, v = w > b * 0.3;
900
- x || v ? t() : (o.current = 0, n(0));
1265
+ c.current = !0, i.current = R.touches[0].clientY, l.current = Date.now();
1266
+ }, x = (R) => {
1267
+ if (!c.current) return;
1268
+ let T = R.touches[0].clientY - i.current;
1269
+ T < 0 && (T = T * 0.3), o.current = T, s(T);
1270
+ }, N = () => {
1271
+ if (!c.current) return;
1272
+ c.current = !1;
1273
+ const R = o.current, T = (Date.now() - l.current) / 1e3, p = u.getBoundingClientRect().height, v = T > 0.05 && R > 0 && R / T > 500, k = R > p * 0.3;
1274
+ v || k ? t() : (o.current = 0, s(0));
901
1275
  };
902
- return l.addEventListener("touchstart", d, { passive: !0 }), l.addEventListener("touchmove", R, { passive: !0 }), l.addEventListener("touchend", p), () => {
903
- l.removeEventListener("touchstart", d), l.removeEventListener("touchmove", R), l.removeEventListener("touchend", p);
1276
+ return u.addEventListener("touchstart", d, { passive: !0 }), u.addEventListener("touchmove", x, { passive: !0 }), u.addEventListener("touchend", N), () => {
1277
+ u.removeEventListener("touchstart", d), u.removeEventListener("touchmove", x), u.removeEventListener("touchend", N);
904
1278
  };
905
- }, [e, t, r]), { offsetY: s };
1279
+ }, [e, t, r]), { offsetY: n };
906
1280
  }
907
- const st = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
908
- function ot(e, t) {
909
- H(() => {
1281
+ const gt = 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
1282
+ function pt(e, t) {
1283
+ z(() => {
910
1284
  const r = e.current;
911
1285
  if (!r) return;
912
- const s = (n) => {
913
- if (n.key !== "Tab") return;
1286
+ const n = (s) => {
1287
+ if (s.key !== "Tab") return;
914
1288
  const o = Array.from(
915
- r.querySelectorAll(st)
916
- ).filter((l) => !l.hasAttribute("aria-hidden"));
1289
+ r.querySelectorAll(gt)
1290
+ ).filter((u) => !u.hasAttribute("aria-hidden"));
917
1291
  if (o.length === 0) return;
918
- const c = o[0], a = o[o.length - 1], u = document.activeElement;
919
- n.shiftKey && u === c ? (n.preventDefault(), a.focus()) : !n.shiftKey && u === a && (n.preventDefault(), c.focus());
1292
+ const i = o[0], l = o[o.length - 1], c = document.activeElement;
1293
+ s.shiftKey && c === i ? (s.preventDefault(), l.focus()) : !s.shiftKey && c === l && (s.preventDefault(), i.focus());
920
1294
  };
921
- return r.addEventListener("keydown", s), () => r.removeEventListener("keydown", s);
1295
+ return r.addEventListener("keydown", n), () => r.removeEventListener("keydown", n);
922
1296
  }, [e, t]);
923
1297
  }
924
- const it = /\*\*([^*]+)\*\*/g, ct = /\*([^*]+)\*/g, at = /https?:\/\/[^\s)]+/g;
925
- function ut(e) {
926
- return e.replace(it, "$1").replace(ct, "$1").replace(at, (t) => {
1298
+ const bt = /\*\*([^*]+)\*\*/g, yt = /\*([^*]+)\*/g, xt = /https?:\/\/[^\s)]+/g;
1299
+ function wt(e) {
1300
+ return e.replace(bt, "$1").replace(yt, "$1").replace(xt, (t) => {
927
1301
  try {
928
1302
  return new URL(t).hostname;
929
1303
  } catch {
@@ -931,131 +1305,145 @@ function ut(e) {
931
1305
  }
932
1306
  });
933
1307
  }
934
- const lt = {
1308
+ const vt = {
935
1309
  "bottom-right": "bottom-24 right-3 sm:right-6",
936
1310
  "bottom-left": "bottom-24 left-3 sm:left-6",
937
1311
  "top-right": "top-24 right-3 sm:right-6",
938
1312
  "top-left": "top-24 left-3 sm:left-6"
939
1313
  };
940
- function dt({
1314
+ function Rt({
941
1315
  messages: e,
942
1316
  isLoading: t,
943
- error: r,
944
- canRetry: s = !1,
945
- onSend: n,
946
- onRetry: o,
947
- onClose: c,
948
- title: a = "Chat",
949
- subtitle: u = "Ask me anything",
950
- welcomeMessage: l = "Hi! How can I help you today?",
951
- placeholder: d,
952
- position: R = "bottom-right",
1317
+ isStreaming: r = !1,
1318
+ streamingMessageId: n = null,
1319
+ error: s,
1320
+ canRetry: o = !1,
1321
+ onSend: i,
1322
+ onStop: l,
1323
+ onRetry: c,
1324
+ onClose: u,
1325
+ title: d = "Chat",
1326
+ subtitle: x = "Ask me anything",
1327
+ welcomeMessage: N = "Hi! How can I help you today?",
1328
+ placeholder: R,
1329
+ position: T = "bottom-right",
953
1330
  translations: p,
954
- isMobile: w = !1
1331
+ isMobile: v = !1
955
1332
  }) {
956
- const y = Ce(), b = C(null), x = C(null), [v, N] = k(null);
957
- ot(b, !0);
958
- const { offsetY: E } = nt(
959
- x,
960
- c,
961
- w
962
- ), I = E !== 0, A = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : !1;
963
- H(() => {
964
- const m = x.current;
1333
+ const k = Le(), H = I(null), w = I(null), [f, E] = L(null);
1334
+ pt(H, !0);
1335
+ const { offsetY: F } = mt(
1336
+ w,
1337
+ u,
1338
+ v
1339
+ ), W = F !== 0, y = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(prefers-reduced-motion: reduce)").matches : !1;
1340
+ z(() => {
1341
+ const m = w.current;
965
1342
  m && (m.scrollTop = m.scrollHeight);
966
- }, [e, t]), H(() => {
967
- const m = (P) => {
968
- P.key === "Escape" && !P.isComposing && c();
1343
+ }, [e, t]), z(() => {
1344
+ const m = (V) => {
1345
+ V.key === "Escape" && !V.isComposing && u();
969
1346
  };
970
1347
  return document.addEventListener("keydown", m), () => document.removeEventListener("keydown", m);
971
- }, [c]);
972
- const D = (p == null ? void 0 : p.closeChat) ?? "Close chat", S = (p == null ? void 0 : p.chatMessages) ?? "Chat messages", j = [...e].reverse().find((m) => m.role === "assistant");
973
- return /* @__PURE__ */ h(
1348
+ }, [u]);
1349
+ const K = (p == null ? void 0 : p.closeChat) ?? "Close chat", B = (p == null ? void 0 : p.chatMessages) ?? "Chat messages", _ = [...e].reverse().find((m) => m.role === "assistant");
1350
+ return /* @__PURE__ */ g(
974
1351
  "div",
975
1352
  {
976
- ref: b,
1353
+ ref: H,
977
1354
  role: "dialog",
978
- "aria-modal": w ? "true" : void 0,
979
- "aria-labelledby": y,
980
- className: w ? "claudius-bottom-sheet fixed inset-x-0 bottom-0 z-50 flex h-[90vh] w-full flex-col overflow-hidden rounded-t-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body" : `fixed ${lt[R]} z-50 flex h-[min(500px,calc(100vh-7rem))] w-[calc(100vw-1.5rem)] max-w-[380px] sm:max-w-[400px] md:max-w-[440px] flex-col overflow-hidden rounded-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body`,
981
- style: w && !A ? { transform: `translateY(${Math.max(0, E)}px)` } : void 0,
982
- "data-dragging": I || void 0,
1355
+ "aria-modal": v ? "true" : void 0,
1356
+ "aria-labelledby": k,
1357
+ className: v ? "claudius-bottom-sheet fixed inset-x-0 bottom-0 z-50 flex h-[90vh] w-full flex-col overflow-hidden rounded-t-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body" : `fixed ${vt[T]} z-50 flex h-[min(500px,calc(100vh-7rem))] w-[calc(100vw-1.5rem)] max-w-[380px] sm:max-w-[400px] md:max-w-[440px] flex-col overflow-hidden rounded-claudius-lg bg-claudius-surface shadow-claudius-elevated font-body`,
1358
+ style: v && !y ? { transform: `translateY(${Math.max(0, F)}px)` } : void 0,
1359
+ "data-dragging": W || void 0,
983
1360
  children: [
984
- w && /* @__PURE__ */ i("div", { className: "flex justify-center py-2", "aria-hidden": "true", children: /* @__PURE__ */ i("div", { className: "h-1 w-8 rounded-claudius-full bg-claudius-border" }) }),
985
- /* @__PURE__ */ i(
986
- et,
1361
+ v && /* @__PURE__ */ a("div", { className: "flex justify-center py-2", "aria-hidden": "true", children: /* @__PURE__ */ a("div", { className: "h-1 w-8 rounded-claudius-full bg-claudius-border" }) }),
1362
+ /* @__PURE__ */ a(
1363
+ dt,
987
1364
  {
988
- title: a,
989
- subtitle: u,
990
- titleId: y,
991
- closeLabel: D,
992
- onClose: c
1365
+ title: d,
1366
+ subtitle: x,
1367
+ titleId: k,
1368
+ closeLabel: K,
1369
+ onClose: u
993
1370
  }
994
1371
  ),
995
- /* @__PURE__ */ h("div", { className: "relative flex-1 overflow-hidden", children: [
996
- v && /* @__PURE__ */ i(
997
- Qe,
1372
+ /* @__PURE__ */ g("div", { className: "relative flex-1 overflow-hidden", children: [
1373
+ f && /* @__PURE__ */ a(
1374
+ ut,
998
1375
  {
999
- sources: v.sources,
1000
- onClose: () => N(null)
1376
+ sources: f.sources,
1377
+ onClose: () => E(null)
1001
1378
  }
1002
1379
  ),
1003
- /* @__PURE__ */ h(
1380
+ /* @__PURE__ */ g(
1004
1381
  "div",
1005
1382
  {
1006
- ref: x,
1383
+ ref: w,
1007
1384
  role: "log",
1008
- "aria-label": S,
1385
+ "aria-label": B,
1009
1386
  className: "h-full space-y-3 overflow-y-auto px-4 py-4",
1010
1387
  children: [
1011
- e.length === 0 && !r && /* @__PURE__ */ i("div", { className: "mr-auto flex max-w-[85%]", children: /* @__PURE__ */ i("div", { className: "rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-2.5 text-sm leading-relaxed text-claudius-assistant-bubble-text", children: l }) }),
1012
- e.map((m) => /* @__PURE__ */ i(
1013
- Ve,
1388
+ e.length === 0 && !s && /* @__PURE__ */ a("div", { className: "mr-auto flex max-w-[85%]", children: /* @__PURE__ */ a("div", { className: "rounded-claudius-bubble rounded-bl-claudius-tail bg-claudius-assistant-bubble px-4 py-2.5 text-sm leading-relaxed text-claudius-assistant-bubble-text", children: N }) }),
1389
+ e.map((m) => /* @__PURE__ */ a(
1390
+ st,
1014
1391
  {
1015
1392
  role: m.role,
1016
1393
  content: m.content,
1394
+ isStreaming: m.id === n,
1017
1395
  sources: m.sources,
1018
- isSourceActive: (v == null ? void 0 : v.messageId) === m.id,
1396
+ toolUses: m.toolUses,
1397
+ toolUsedLabel: p == null ? void 0 : p.toolUsed,
1398
+ toolDetailsLabel: p == null ? void 0 : p.toolDetails,
1399
+ isSourceActive: (f == null ? void 0 : f.messageId) === m.id,
1019
1400
  onSourceClick: () => {
1020
- (v == null ? void 0 : v.messageId) === m.id ? N(null) : m.sources && m.sources.length > 0 && N({ messageId: m.id, sources: m.sources });
1401
+ (f == null ? void 0 : f.messageId) === m.id ? E(null) : m.sources && m.sources.length > 0 && E({ messageId: m.id, sources: m.sources });
1021
1402
  }
1022
1403
  },
1023
1404
  m.id
1024
1405
  )),
1025
- t && /* @__PURE__ */ i(
1026
- rt,
1406
+ t && /* Once streamed tokens are rendering in a bubble, the typing
1407
+ indicator is redundant — show it only until the first token.
1408
+ A tool-only placeholder (no text yet) keeps the indicator. */
1409
+ !(n !== null && e.some(
1410
+ (m) => m.id === n && m.content.length > 0
1411
+ )) && /* @__PURE__ */ a(
1412
+ ht,
1027
1413
  {
1028
1414
  label: (p == null ? void 0 : p.typingIndicator) ?? "Assistant is typing"
1029
1415
  }
1030
1416
  ),
1031
- r && /* @__PURE__ */ i(
1032
- tt,
1417
+ s && /* @__PURE__ */ a(
1418
+ ft,
1033
1419
  {
1034
- message: r,
1420
+ message: s,
1035
1421
  retryLabel: (p == null ? void 0 : p.errorRetry) ?? "Retry",
1036
- onRetry: s && o && !t ? o : void 0
1422
+ onRetry: o && c && !t ? c : void 0
1037
1423
  }
1038
1424
  )
1039
1425
  ]
1040
1426
  }
1041
1427
  )
1042
1428
  ] }),
1043
- /* @__PURE__ */ i(
1429
+ /* @__PURE__ */ a(
1044
1430
  "div",
1045
1431
  {
1046
1432
  "data-claudius-live": "assistant",
1047
1433
  "aria-live": "polite",
1048
1434
  "aria-atomic": "true",
1049
1435
  className: "sr-only",
1050
- children: j ? ut(j.content) : ""
1436
+ children: _ && _.id !== n ? wt(_.content) : ""
1051
1437
  }
1052
1438
  ),
1053
- /* @__PURE__ */ i(
1054
- qe,
1439
+ /* @__PURE__ */ a(
1440
+ it,
1055
1441
  {
1056
- onSend: n,
1442
+ onSend: i,
1057
1443
  isLoading: t,
1058
- placeholder: d,
1444
+ isStreaming: r,
1445
+ onStop: l,
1446
+ placeholder: R,
1059
1447
  translations: p
1060
1448
  }
1061
1449
  )
@@ -1063,21 +1451,21 @@ function dt({
1063
1451
  }
1064
1452
  );
1065
1453
  }
1066
- function ft({
1454
+ function Et({
1067
1455
  message: e,
1068
1456
  position: t,
1069
1457
  onOpen: r,
1070
- onDismiss: s,
1071
- dismissLabel: n
1458
+ onDismiss: n,
1459
+ dismissLabel: s
1072
1460
  }) {
1073
- const o = t.startsWith("bottom"), c = t.endsWith("right"), a = [
1461
+ const o = t.startsWith("bottom"), i = t.endsWith("right"), l = [
1074
1462
  "claudius-greeting-bubble",
1075
1463
  "fixed z-40 max-w-xs",
1076
1464
  o ? "bottom-20" : "top-20",
1077
- c ? "right-4" : "left-4"
1465
+ i ? "right-4" : "left-4"
1078
1466
  ].join(" ");
1079
- return /* @__PURE__ */ h("div", { className: a, role: "status", "aria-live": "polite", children: [
1080
- /* @__PURE__ */ i(
1467
+ return /* @__PURE__ */ g("div", { className: l, role: "status", "aria-live": "polite", children: [
1468
+ /* @__PURE__ */ a(
1081
1469
  "button",
1082
1470
  {
1083
1471
  type: "button",
@@ -1086,21 +1474,21 @@ function ft({
1086
1474
  children: e
1087
1475
  }
1088
1476
  ),
1089
- /* @__PURE__ */ i(
1477
+ /* @__PURE__ */ a(
1090
1478
  "button",
1091
1479
  {
1092
1480
  type: "button",
1093
- onClick: (u) => {
1094
- u.stopPropagation(), s();
1481
+ onClick: (c) => {
1482
+ c.stopPropagation(), n();
1095
1483
  },
1096
- "aria-label": n,
1484
+ "aria-label": s,
1097
1485
  className: "absolute right-1 top-1 flex h-6 w-6 items-center justify-center rounded-claudius-full text-claudius-text-muted hover:bg-claudius-surface-muted focus:outline-none focus:ring-2 focus:ring-claudius-accent",
1098
- children: /* @__PURE__ */ i("span", { "aria-hidden": "true", children: "×" })
1486
+ children: /* @__PURE__ */ a("span", { "aria-hidden": "true", children: "×" })
1099
1487
  }
1100
1488
  )
1101
1489
  ] });
1102
1490
  }
1103
- const de = {
1491
+ const Re = {
1104
1492
  // ChatWindow
1105
1493
  title: "Chat",
1106
1494
  subtitle: "Ask me anything",
@@ -1111,6 +1499,9 @@ const de = {
1111
1499
  // ChatInput
1112
1500
  placeholder: "Type your message...",
1113
1501
  sendMessage: "Send message",
1502
+ stopGenerating: "Stop generating",
1503
+ toolUsed: "Used tool:",
1504
+ toolDetails: "Tool details",
1114
1505
  typeYourMessage: "Type your message",
1115
1506
  // ChatToggleButton
1116
1507
  openChat: "Open chat",
@@ -1123,11 +1514,11 @@ const de = {
1123
1514
  errorRateLimitMinute: "Too many requests. Please wait a minute.",
1124
1515
  errorRateLimitHour: "Hourly limit reached. Please try again later.",
1125
1516
  errorRetry: "Retry"
1126
- }, ht = de;
1127
- function $t(e) {
1128
- return { ...ht, ...e };
1517
+ }, Tt = Re;
1518
+ function qt(e) {
1519
+ return { ...Tt, ...e };
1129
1520
  }
1130
- const mt = {
1521
+ const Mt = {
1131
1522
  // ChatWindow
1132
1523
  title: "Chat",
1133
1524
  subtitle: "Pregúntame lo que quieras",
@@ -1138,6 +1529,9 @@ const mt = {
1138
1529
  // ChatInput
1139
1530
  placeholder: "Escribe tu mensaje...",
1140
1531
  sendMessage: "Enviar mensaje",
1532
+ stopGenerating: "Detener la respuesta",
1533
+ toolUsed: "Herramienta usada:",
1534
+ toolDetails: "Detalles de la herramienta",
1141
1535
  typeYourMessage: "Escribe tu mensaje",
1142
1536
  // ChatToggleButton
1143
1537
  openChat: "Abrir chat",
@@ -1150,7 +1544,7 @@ const mt = {
1150
1544
  errorRateLimitMinute: "Demasiadas solicitudes. Espera un minuto.",
1151
1545
  errorRateLimitHour: "Has alcanzado el límite por hora. Inténtalo más tarde.",
1152
1546
  errorRetry: "Reintentar"
1153
- }, gt = {
1547
+ }, St = {
1154
1548
  // ChatWindow
1155
1549
  title: "Chat",
1156
1550
  subtitle: "Posez-moi vos questions",
@@ -1161,6 +1555,9 @@ const mt = {
1161
1555
  // ChatInput
1162
1556
  placeholder: "Saisissez votre message...",
1163
1557
  sendMessage: "Envoyer le message",
1558
+ stopGenerating: "Arrêter la génération",
1559
+ toolUsed: "Outil utilisé :",
1560
+ toolDetails: "Détails de l'outil",
1164
1561
  typeYourMessage: "Saisissez votre message",
1165
1562
  // ChatToggleButton
1166
1563
  openChat: "Ouvrir le chat",
@@ -1173,7 +1570,7 @@ const mt = {
1173
1570
  errorRateLimitMinute: "Trop de requêtes. Veuillez patienter une minute.",
1174
1571
  errorRateLimitHour: "Limite horaire atteinte. Veuillez réessayer plus tard.",
1175
1572
  errorRetry: "Réessayer"
1176
- }, pt = {
1573
+ }, Ct = {
1177
1574
  // ChatWindow
1178
1575
  title: "Chat",
1179
1576
  subtitle: "Fragen Sie mich alles",
@@ -1184,6 +1581,9 @@ const mt = {
1184
1581
  // ChatInput
1185
1582
  placeholder: "Geben Sie Ihre Nachricht ein...",
1186
1583
  sendMessage: "Nachricht senden",
1584
+ stopGenerating: "Generierung stoppen",
1585
+ toolUsed: "Verwendetes Tool:",
1586
+ toolDetails: "Tool-Details",
1187
1587
  typeYourMessage: "Geben Sie Ihre Nachricht ein",
1188
1588
  // ChatToggleButton
1189
1589
  openChat: "Chat öffnen",
@@ -1196,28 +1596,28 @@ const mt = {
1196
1596
  errorRateLimitMinute: "Zu viele Anfragen. Bitte warten Sie eine Minute.",
1197
1597
  errorRateLimitHour: "Stündliches Limit erreicht. Bitte versuchen Sie es später erneut.",
1198
1598
  errorRetry: "Erneut versuchen"
1199
- }, fe = {
1200
- en: de,
1201
- es: mt,
1202
- fr: gt,
1203
- de: pt
1599
+ }, Ee = {
1600
+ en: Re,
1601
+ es: Mt,
1602
+ fr: St,
1603
+ de: Ct
1204
1604
  };
1205
- function ie(e) {
1605
+ function be(e) {
1206
1606
  if (!e) return;
1207
1607
  const t = e.toLowerCase().split("-")[0];
1208
- return Object.prototype.hasOwnProperty.call(fe, t) ? t : void 0;
1608
+ return Object.prototype.hasOwnProperty.call(Ee, t) ? t : void 0;
1209
1609
  }
1210
- function bt() {
1211
- const e = typeof document < "u" ? ie(document.documentElement.lang) : void 0;
1610
+ function Nt() {
1611
+ const e = typeof document < "u" ? be(document.documentElement.lang) : void 0;
1212
1612
  if (e) return e;
1213
- const t = typeof navigator < "u" ? ie(navigator.language) : void 0;
1613
+ const t = typeof navigator < "u" ? be(navigator.language) : void 0;
1214
1614
  return t || "en";
1215
1615
  }
1216
- function yt(e = {}) {
1217
- const { locale: t, translations: r } = e, s = fe[t ?? bt()];
1218
- return r ? { ...s, ...r } : { ...s };
1616
+ function kt(e = {}) {
1617
+ const { locale: t, translations: r } = e, n = Ee[t ?? Nt()];
1618
+ return r ? { ...n, ...r } : { ...n };
1219
1619
  }
1220
- const ce = [
1620
+ const ye = [
1221
1621
  "accent",
1222
1622
  "accentText",
1223
1623
  "accentSoft",
@@ -1237,11 +1637,11 @@ const ce = [
1237
1637
  "errorText",
1238
1638
  "link",
1239
1639
  "scrim"
1240
- ], xt = ["sm", "md", "lg", "full", "tail"], wt = [
1640
+ ], Lt = ["sm", "md", "lg", "full", "tail"], At = [
1241
1641
  "elevated",
1242
1642
  "floating",
1243
1643
  "floatingHover"
1244
- ], vt = ["heading", "body"], he = {
1644
+ ], Ot = ["heading", "body"], Te = {
1245
1645
  default: {
1246
1646
  name: "default"
1247
1647
  },
@@ -1326,249 +1726,264 @@ const ce = [
1326
1726
  }
1327
1727
  }
1328
1728
  };
1329
- function Et(e) {
1330
- return Object.prototype.hasOwnProperty.call(he, e);
1729
+ function It(e) {
1730
+ return Object.prototype.hasOwnProperty.call(Te, e);
1331
1731
  }
1332
- const Rt = /* @__PURE__ */ new Set(["light", "dark", "auto"]);
1333
- function Tt(e) {
1732
+ const Dt = /* @__PURE__ */ new Set(["light", "dark", "auto"]);
1733
+ function _t(e) {
1334
1734
  if (e === void 0)
1335
1735
  return { mode: "light" };
1336
1736
  if (typeof e == "string") {
1337
- if (Rt.has(e))
1737
+ if (Dt.has(e))
1338
1738
  return { mode: e };
1339
- if (Et(e)) {
1340
- const t = he[e];
1739
+ if (It(e)) {
1740
+ const t = Te[e];
1341
1741
  return { mode: t.colorScheme ?? "light", theme: t };
1342
1742
  }
1343
1743
  return { mode: "light", url: e };
1344
1744
  }
1345
1745
  return { mode: e.colorScheme ?? "light", theme: e };
1346
1746
  }
1347
- function Mt(e) {
1747
+ function jt(e) {
1348
1748
  return e.replace(/[A-Z]/g, (t) => `-${t.toLowerCase()}`);
1349
1749
  }
1350
- function Ct(e, t) {
1750
+ function Ht(e, t) {
1351
1751
  console.warn(
1352
1752
  `[Claudius] Ignoring unknown theme token "${t}" in "${e}"`
1353
1753
  );
1354
1754
  }
1355
- function W(e, t, r, s, n, o = "") {
1356
- if (n)
1357
- for (const [c, a] of Object.entries(n)) {
1358
- if (!s.includes(c)) {
1359
- Ct(t, c);
1755
+ function Q(e, t, r, n, s, o = "") {
1756
+ if (s)
1757
+ for (const [i, l] of Object.entries(s)) {
1758
+ if (!n.includes(i)) {
1759
+ Ht(t, i);
1360
1760
  continue;
1361
1761
  }
1362
- typeof a == "string" && (e[`${r}${Mt(c)}${o}`] = a);
1762
+ typeof l == "string" && (e[`${r}${jt(i)}${o}`] = l);
1363
1763
  }
1364
1764
  }
1365
- function Nt(e) {
1765
+ function Bt(e) {
1366
1766
  const t = {};
1367
- W(t, "colors", "--cl-color-", ce, e.colors);
1368
- for (const [r, s] of Object.entries({ ...t }))
1369
- t[`${r}-dark`] = s;
1370
- return W(
1767
+ Q(t, "colors", "--cl-color-", ye, e.colors);
1768
+ for (const [r, n] of Object.entries({ ...t }))
1769
+ t[`${r}-dark`] = n;
1770
+ return Q(
1371
1771
  t,
1372
1772
  "colorsDark",
1373
1773
  "--cl-color-",
1374
- ce,
1774
+ ye,
1375
1775
  e.colorsDark,
1376
1776
  "-dark"
1377
- ), W(t, "radii", "--cl-radius-", xt, e.radii), W(t, "shadows", "--cl-shadow-", wt, e.shadows), W(t, "fonts", "--cl-font-", vt, e.fonts), t;
1777
+ ), Q(t, "radii", "--cl-radius-", Lt, e.radii), Q(t, "shadows", "--cl-shadow-", At, e.shadows), Q(t, "fonts", "--cl-font-", Ot, e.fonts), t;
1378
1778
  }
1379
- function St(e) {
1779
+ function $t(e) {
1380
1780
  return typeof e == "object" && e !== null && !Array.isArray(e);
1381
1781
  }
1382
- function Lt(e) {
1383
- const t = Y(() => Tt(e), [e]), [r, s] = k(null), n = t.url;
1384
- H(() => {
1385
- if (s(null), !n) return;
1386
- const u = new AbortController();
1387
- return fetch(n, { signal: u.signal }).then((l) => {
1388
- if (!l.ok)
1389
- throw new Error(`HTTP ${l.status}`);
1390
- return l.json();
1391
- }).then((l) => {
1392
- if (!St(l))
1782
+ function Pt(e) {
1783
+ const t = se(() => _t(e), [e]), [r, n] = L(null), s = t.url;
1784
+ z(() => {
1785
+ if (n(null), !s) return;
1786
+ const c = new AbortController();
1787
+ return fetch(s, { signal: c.signal }).then((u) => {
1788
+ if (!u.ok)
1789
+ throw new Error(`HTTP ${u.status}`);
1790
+ return u.json();
1791
+ }).then((u) => {
1792
+ if (!$t(u))
1393
1793
  throw new Error("theme JSON must be an object");
1394
- s(l);
1395
- }).catch((l) => {
1396
- u.signal.aborted || console.error(`[Claudius] Failed to load theme from ${n}:`, l);
1397
- }), () => u.abort();
1398
- }, [n]);
1399
- const o = t.theme ?? r ?? null, c = (r == null ? void 0 : r.colorScheme) ?? t.mode, a = Y(
1400
- () => o ? Nt(o) : {},
1794
+ n(u);
1795
+ }).catch((u) => {
1796
+ c.signal.aborted || console.error(`[Claudius] Failed to load theme from ${s}:`, u);
1797
+ }), () => c.abort();
1798
+ }, [s]);
1799
+ const o = t.theme ?? r ?? null, i = (r == null ? void 0 : r.colorScheme) ?? t.mode, l = se(
1800
+ () => o ? Bt(o) : {},
1401
1801
  [o]
1402
1802
  );
1403
- return { mode: c, cssVars: a };
1803
+ return { mode: i, cssVars: l };
1404
1804
  }
1405
- const me = "claudius:triggers:dismissed";
1406
- function kt() {
1805
+ const Me = "claudius:triggers:dismissed";
1806
+ function Ut() {
1407
1807
  if (typeof window > "u") return !1;
1408
1808
  try {
1409
- return window.sessionStorage.getItem(me) === "1";
1809
+ return window.sessionStorage.getItem(Me) === "1";
1410
1810
  } catch {
1411
1811
  return !1;
1412
1812
  }
1413
1813
  }
1414
- function At() {
1814
+ function Gt() {
1415
1815
  if (!(typeof window > "u"))
1416
1816
  try {
1417
- window.sessionStorage.setItem(me, "1");
1817
+ window.sessionStorage.setItem(Me, "1");
1418
1818
  } catch {
1419
1819
  }
1420
1820
  }
1421
- function jt({
1821
+ function Jt({
1422
1822
  apiUrl: e,
1423
1823
  title: t,
1424
1824
  subtitle: r,
1425
- welcomeMessage: s,
1426
- placeholder: n,
1825
+ welcomeMessage: n,
1826
+ placeholder: s,
1427
1827
  persistMessages: o,
1428
- storageKeyPrefix: c,
1429
- requestTimeoutMs: a,
1430
- theme: u = "light",
1431
- accentColor: l,
1828
+ storageKeyPrefix: i,
1829
+ requestTimeoutMs: l,
1830
+ theme: c = "light",
1831
+ accentColor: u,
1432
1832
  position: d = "bottom-right",
1433
- locale: R,
1434
- translations: p,
1435
- triggers: w,
1436
- plugins: y
1833
+ locale: x,
1834
+ translations: N,
1835
+ triggers: R,
1836
+ plugins: T,
1837
+ streaming: p = !0
1437
1838
  }) {
1438
- const [b, x] = k(!1), [v, N] = k(null), [E, I] = k(kt), A = C(!1), D = Be("(max-width: 639px)"), S = Y(
1439
- () => yt({ locale: R, translations: p }),
1440
- [R, p]
1441
- ), { messages: j, isLoading: m, error: P, canRetry: V, sendMessage: K, retry: f } = He({
1839
+ const [v, k] = L(!1), [H, w] = L(null), [f, E] = L(Ut), F = I(!1), W = Ge("(max-width: 639px)"), y = se(
1840
+ () => kt({ locale: x, translations: N }),
1841
+ [x, N]
1842
+ ), {
1843
+ messages: K,
1844
+ isLoading: B,
1845
+ isStreaming: _,
1846
+ streamingMessageId: m,
1847
+ error: V,
1848
+ canRetry: ee,
1849
+ sendMessage: J,
1850
+ stop: oe,
1851
+ retry: ie
1852
+ } = Ue({
1442
1853
  apiUrl: e,
1443
1854
  persistMessages: o,
1444
- storageKeyPrefix: c,
1445
- timeoutMs: a,
1446
- translations: S,
1447
- plugins: y
1448
- }), g = C(null), L = C(b), { mode: T, cssVars: B } = Lt(u), [O, z] = k(!1);
1449
- H(() => {
1450
- if (T !== "auto") return;
1451
- const _ = window.matchMedia("(prefers-color-scheme: dark)");
1452
- z(_.matches);
1453
- const re = (ve) => z(ve.matches);
1454
- return _.addEventListener("change", re), () => _.removeEventListener("change", re);
1455
- }, [T]), H(() => {
1456
- var _;
1457
- L.current && !b && ((_ = g.current) == null || _.focus()), L.current = b;
1458
- }, [b]);
1459
- const $ = M(() => {
1460
- I(!0), At();
1461
- }, []), ee = M(() => {
1462
- x(!1), A.current && (A.current = !1, $());
1463
- }, [$]), ge = M(() => {
1464
- x((_) => !_);
1465
- }, []), q = M(() => {
1466
- A.current = !0, N(null), x(!0);
1467
- }, []), pe = M((_) => {
1468
- N(_);
1469
- }, []), be = M(() => {
1470
- N(null), q();
1471
- }, [q]), ye = M(() => {
1472
- N(null), $();
1855
+ storageKeyPrefix: i,
1856
+ timeoutMs: l,
1857
+ translations: y,
1858
+ plugins: T,
1859
+ streaming: p
1860
+ }), te = I(null), re = I(v), { mode: h, cssVars: A } = Pt(c), [S, Y] = L(!1);
1861
+ z(() => {
1862
+ if (h !== "auto") return;
1863
+ const D = window.matchMedia("(prefers-color-scheme: dark)");
1864
+ Y(D.matches);
1865
+ const he = (Se) => Y(Se.matches);
1866
+ return D.addEventListener("change", he), () => D.removeEventListener("change", he);
1867
+ }, [h]), z(() => {
1868
+ var D;
1869
+ re.current && !v && ((D = te.current) == null || D.focus()), re.current = v;
1870
+ }, [v]);
1871
+ const $ = O(() => {
1872
+ E(!0), Gt();
1873
+ }, []), b = O(() => {
1874
+ k(!1), F.current && (F.current = !1, $());
1875
+ }, [$]), C = O(() => {
1876
+ k((D) => !D);
1877
+ }, []), M = O(() => {
1878
+ F.current = !0, w(null), k(!0);
1879
+ }, []), P = O((D) => {
1880
+ w(D);
1881
+ }, []), U = O(() => {
1882
+ w(null), M();
1883
+ }, [M]), Z = O(() => {
1884
+ w(null), $();
1473
1885
  }, [$]);
1474
- je({
1475
- triggers: w,
1476
- enabled: !E && !b,
1477
- onOpen: q,
1478
- onGreeting: pe
1886
+ ze({
1887
+ triggers: R,
1888
+ enabled: !f && !v,
1889
+ onOpen: M,
1890
+ onGreeting: P
1479
1891
  });
1480
- const xe = T === "dark" || T === "auto" && O, te = {
1481
- ...B,
1482
- ...l ? {
1483
- "--cl-color-accent": l,
1484
- "--cl-color-accent-dark": l
1892
+ const G = h === "dark" || h === "auto" && S, q = {
1893
+ ...A,
1894
+ ...u ? {
1895
+ "--cl-color-accent": u,
1896
+ "--cl-color-accent-dark": u
1485
1897
  } : {}
1486
- }, we = Object.keys(te).length > 0 ? te : void 0;
1898
+ }, ae = Object.keys(q).length > 0 ? q : void 0;
1487
1899
  return (
1488
1900
  // Outer div carries theme token vars; the inner div carries the dark-mode
1489
1901
  // attribute so the [data-claudius-dark] token reassignments in styles.css
1490
1902
  // beat inherited (inline) light values.
1491
- /* @__PURE__ */ i("div", { className: "claudius-root", style: we, children: /* @__PURE__ */ h("div", { "data-claudius-dark": xe ? "true" : "false", children: [
1492
- b && D && /* @__PURE__ */ i(
1903
+ /* @__PURE__ */ a("div", { className: "claudius-root", style: ae, children: /* @__PURE__ */ g("div", { "data-claudius-dark": G ? "true" : "false", children: [
1904
+ v && W && /* @__PURE__ */ a(
1493
1905
  "div",
1494
1906
  {
1495
1907
  className: "claudius-scrim fixed inset-0 z-40 bg-claudius-scrim",
1496
- onClick: ee,
1908
+ onClick: b,
1497
1909
  "aria-hidden": "true"
1498
1910
  }
1499
1911
  ),
1500
- b && /* @__PURE__ */ i(
1501
- dt,
1912
+ v && /* @__PURE__ */ a(
1913
+ Rt,
1502
1914
  {
1503
- messages: j,
1504
- isLoading: m,
1505
- error: P,
1506
- canRetry: V,
1507
- onSend: K,
1508
- onRetry: f,
1509
- onClose: ee,
1510
- title: t ?? S.title,
1511
- subtitle: r ?? S.subtitle,
1512
- welcomeMessage: s ?? S.welcomeMessage,
1513
- placeholder: n ?? S.placeholder,
1915
+ messages: K,
1916
+ isLoading: B,
1917
+ isStreaming: _,
1918
+ streamingMessageId: m,
1919
+ error: V,
1920
+ canRetry: ee,
1921
+ onSend: J,
1922
+ onStop: oe,
1923
+ onRetry: ie,
1924
+ onClose: b,
1925
+ title: t ?? y.title,
1926
+ subtitle: r ?? y.subtitle,
1927
+ welcomeMessage: n ?? y.welcomeMessage,
1928
+ placeholder: s ?? y.placeholder,
1514
1929
  position: d,
1515
- translations: S,
1516
- isMobile: D
1930
+ translations: y,
1931
+ isMobile: W
1517
1932
  }
1518
1933
  ),
1519
- !(b && D) && /* @__PURE__ */ i(
1520
- Ge,
1934
+ !(v && W) && /* @__PURE__ */ a(
1935
+ Ve,
1521
1936
  {
1522
- ref: g,
1523
- isOpen: b,
1524
- onClick: ge,
1937
+ ref: te,
1938
+ isOpen: v,
1939
+ onClick: C,
1525
1940
  position: d,
1526
- translations: S
1941
+ translations: y
1527
1942
  }
1528
1943
  ),
1529
- !b && v && /* @__PURE__ */ i(
1530
- ft,
1944
+ !v && H && /* @__PURE__ */ a(
1945
+ Et,
1531
1946
  {
1532
- message: v,
1947
+ message: H,
1533
1948
  position: d,
1534
- onOpen: be,
1535
- onDismiss: ye,
1536
- dismissLabel: S.dismissGreeting
1949
+ onOpen: U,
1950
+ onDismiss: Z,
1951
+ dismissLabel: y.dismissGreeting
1537
1952
  }
1538
1953
  )
1539
1954
  ] }) })
1540
1955
  );
1541
1956
  }
1542
- function Pt(e) {
1543
- const { onEvent: t, includeContent: r = !0 } = e, s = (n) => r ? n : "";
1957
+ function Xt(e) {
1958
+ const { onEvent: t, includeContent: r = !0 } = e, n = (s) => r ? s : "";
1544
1959
  return {
1545
1960
  name: "analytics",
1546
- onBeforeSend(n) {
1961
+ onBeforeSend(s) {
1547
1962
  t({
1548
1963
  type: "message_sent",
1549
1964
  role: "user",
1550
- content: s(n.content),
1551
- chars: n.content.length
1965
+ content: n(s.content),
1966
+ chars: s.content.length
1552
1967
  });
1553
1968
  },
1554
- onAfterReceive(n) {
1969
+ onAfterReceive(s) {
1555
1970
  t({
1556
1971
  type: "message_received",
1557
1972
  role: "assistant",
1558
- content: s(n.content),
1559
- chars: n.content.length
1973
+ content: n(s.content),
1974
+ chars: s.content.length
1560
1975
  });
1561
1976
  },
1562
- onError(n) {
1977
+ onError(s) {
1563
1978
  t({
1564
1979
  type: "chat_error",
1565
- message: n.message,
1566
- code: n.code
1980
+ message: s.message,
1981
+ code: s.code
1567
1982
  });
1568
1983
  }
1569
1984
  };
1570
1985
  }
1571
- const Ot = [
1986
+ const Wt = [
1572
1987
  // Email
1573
1988
  /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g,
1574
1989
  // US SSN (before the looser card pattern so it wins on 9-digit groups)
@@ -1578,59 +1993,59 @@ const Ot = [
1578
1993
  // Phone: optional +1, area code, 7 digits with common separators
1579
1994
  /\b(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}\b/g
1580
1995
  ];
1581
- function It(e, t, r) {
1996
+ function zt(e, t, r) {
1582
1997
  return t.reduce(
1583
1998
  // Reset lastIndex defensively: a shared global regex is stateful.
1584
- (s, n) => (n.lastIndex = 0, s.replace(n, r)),
1999
+ (n, s) => (s.lastIndex = 0, n.replace(s, r)),
1585
2000
  e
1586
2001
  );
1587
2002
  }
1588
- function Gt(e = {}) {
2003
+ function Zt(e = {}) {
1589
2004
  const {
1590
- patterns: t = Ot,
2005
+ patterns: t = Wt,
1591
2006
  replacement: r = "[redacted]",
1592
- redactReplies: s = !1
1593
- } = e, n = (o) => {
1594
- const c = It(o.content, t, r);
1595
- if (c !== o.content)
1596
- return { ...o, content: c };
2007
+ redactReplies: n = !1
2008
+ } = e, s = (o) => {
2009
+ const i = zt(o.content, t, r);
2010
+ if (i !== o.content)
2011
+ return { ...o, content: i };
1597
2012
  };
1598
2013
  return {
1599
2014
  name: "redact-pii",
1600
- onBeforeSend: n,
1601
- onAfterReceive: s ? n : void 0
2015
+ onBeforeSend: s,
2016
+ onAfterReceive: n ? s : void 0
1602
2017
  };
1603
2018
  }
1604
- function Dt(e, t, r) {
2019
+ function Ft(e, t, r) {
1605
2020
  return typeof e == "function" ? e(t) : e instanceof RegExp ? e.test(t) : r ? t.includes(e) : t.toLowerCase().includes(e.toLowerCase());
1606
2021
  }
1607
- function Ut(e) {
2022
+ function Qt(e) {
1608
2023
  const { rules: t, caseSensitive: r = !1 } = e;
1609
2024
  return {
1610
2025
  name: "canned-responses",
1611
- onBeforeSend(s, n) {
2026
+ onBeforeSend(n, s) {
1612
2027
  for (const o of t)
1613
- if (Dt(o.match, s.content, r)) {
1614
- n.respondWith(o.reply);
2028
+ if (Ft(o.match, n.content, r)) {
2029
+ s.respondWith(o.reply);
1615
2030
  return;
1616
2031
  }
1617
2032
  }
1618
2033
  };
1619
2034
  }
1620
2035
  export {
1621
- Se as ChatApiClient,
1622
- U as ChatApiError,
1623
- jt as ChatWidget,
1624
- Ot as DEFAULT_PII_PATTERNS,
1625
- ae as DebounceError,
1626
- he as builtinThemes,
1627
- $t as createTranslations,
1628
- ht as defaultTranslations,
1629
- bt as detectLocale,
1630
- fe as locales,
1631
- Pt as pluginAnalytics,
1632
- Ut as pluginCannedResponses,
1633
- Gt as pluginRedactPII,
1634
- It as redactText,
1635
- yt as resolveTranslations
2036
+ Oe as ChatApiClient,
2037
+ j as ChatApiError,
2038
+ Jt as ChatWidget,
2039
+ Wt as DEFAULT_PII_PATTERNS,
2040
+ le as DebounceError,
2041
+ Te as builtinThemes,
2042
+ qt as createTranslations,
2043
+ Tt as defaultTranslations,
2044
+ Nt as detectLocale,
2045
+ Ee as locales,
2046
+ Xt as pluginAnalytics,
2047
+ Qt as pluginCannedResponses,
2048
+ Zt as pluginRedactPII,
2049
+ zt as redactText,
2050
+ kt as resolveTranslations
1636
2051
  };