@icanbwell/baileyai-chat-ui 0.2.1-pre.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.
@@ -0,0 +1,988 @@
1
+ import { memo as e, useCallback as t, useEffect as n, useMemo as r, useRef as i, useState as a } from "react";
2
+ import o from "react-markdown";
3
+ import s from "remark-gfm";
4
+ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
5
+ import * as d from "@radix-ui/react-tooltip";
6
+ //#region src/utils/pseudoToolCalls.ts
7
+ var f = /<(search_tools|call_tool)>([\s\S]*?)<\/\1>/g, p = /<name>([\s\S]*?)<\/name>/, m = /<arguments>([\s\S]*?)<\/arguments>/;
8
+ function h(e) {
9
+ let t = p.exec(e)?.[1]?.trim() || "unknown_tool", n = m.exec(e)?.[1]?.trim();
10
+ return n ? {
11
+ name: t,
12
+ args: n
13
+ } : { name: t };
14
+ }
15
+ function g(e) {
16
+ let t = [], n = e.replace(f, (e, n, r) => (t.push(n === "call_tool" ? h(r) : {
17
+ name: "search_tools",
18
+ args: r.trim()
19
+ }), ""));
20
+ return t.length === 0 ? {
21
+ cleanedText: n,
22
+ matches: t
23
+ } : {
24
+ cleanedText: n.replace(/\n{3,}/g, "\n\n"),
25
+ matches: t
26
+ };
27
+ }
28
+ //#endregion
29
+ //#region src/logic/sse.ts
30
+ function _(e) {
31
+ if (!e.startsWith("data: ")) return e;
32
+ let t = "";
33
+ for (let n of e.split("\n")) {
34
+ if (!n.startsWith("data: ")) continue;
35
+ let e = n.slice(6);
36
+ if (e === "[DONE]") break;
37
+ try {
38
+ let n = JSON.parse(e);
39
+ n?.type === "response.output_text.delta" && n.delta && (t += n.delta);
40
+ } catch {}
41
+ }
42
+ return t || null;
43
+ }
44
+ function v(e) {
45
+ let t = e.replace(/\r\n/g, "\n").split("\n\n"), n = t.pop() ?? "", r = [], i = !1;
46
+ for (let e of t) {
47
+ let t = e.split("\n").filter((e) => e.length > 0), n = "message", a = [];
48
+ for (let e of t) e.startsWith("event:") ? n = e.slice(6).trim() : e.startsWith("data:") && a.push(e.slice(5).trim());
49
+ if (a.length === 0) continue;
50
+ let o = a.join("\n");
51
+ if (o === "[DONE]") {
52
+ i = !0;
53
+ continue;
54
+ }
55
+ let s;
56
+ try {
57
+ s = JSON.parse(o);
58
+ } catch {
59
+ s = void 0;
60
+ }
61
+ let c = s;
62
+ if (n === "error") {
63
+ let e = typeof c?.message == "string" ? c.message : o;
64
+ r.push({
65
+ type: "error",
66
+ message: e
67
+ });
68
+ } else if (c?.type === "response.output_text.delta" && typeof c.delta == "string") {
69
+ let e = _(c.delta);
70
+ e && r.push({
71
+ type: "response.output_text.delta",
72
+ delta: e
73
+ });
74
+ } else c && typeof c.type == "string" ? r.push(c) : n !== "message" && r.push({
75
+ type: "info",
76
+ message: `${n}: ${o}`
77
+ });
78
+ }
79
+ return {
80
+ events: r,
81
+ remainder: n,
82
+ done: i
83
+ };
84
+ }
85
+ //#endregion
86
+ //#region src/logic/useBaileyChat.ts
87
+ var y = 200, b = 15e4, x = (e, t, n) => {
88
+ if (e === 401 || e === 403) return "Bailey isn't reachable with your current login.";
89
+ let r = `Bailey request failed (status ${e ?? "network error"}).`, i = (n || t || "").trim();
90
+ return i ? `${r} ${i.length > y ? `${i.slice(0, y)}…` : i}` : r;
91
+ }, S = ({ transport: e, model: r, instructions: o, tools: s = [], toolChoice: c, firstUserMessagePrefix: l, onAssistantMessageComplete: u, idleTimeoutMs: d = b }) => {
92
+ let [f, p] = a([]), [m, h] = a([]), [_, y] = a(null), [S, C] = a("idle"), [w, T] = a(null), E = i(null), D = i(""), O = i(0), k = i([]);
93
+ n(() => {
94
+ k.current = f;
95
+ }, [f]);
96
+ let A = i(/* @__PURE__ */ new Map()), j = i(/* @__PURE__ */ new Map()), M = i(null), N = t(() => {
97
+ M.current !== null && (clearTimeout(M.current), M.current = null);
98
+ }, []), P = t((e) => {
99
+ N(), M.current = setTimeout(() => {
100
+ e.abort(new DOMException("The assistant took too long to respond. Please try again.", "TimeoutError"));
101
+ }, d);
102
+ }, [N, d]), F = t((e, t, n) => {
103
+ let r = (e) => {
104
+ n.push(e), h((t) => [...t, e]);
105
+ };
106
+ if (t.type === "response.output_text.delta") {
107
+ if (!t.delta) return !1;
108
+ let n = A.current.get(e) ?? {
109
+ raw: "",
110
+ emittedCount: 0
111
+ };
112
+ n.raw += t.delta;
113
+ let { cleanedText: i, matches: a } = g(n.raw), o = i.trim(), s = a.slice(n.emittedCount);
114
+ if (n.emittedCount = a.length, A.current.set(e, n), j.current.set(e, o), p((t) => t.map((t) => t.id === e ? {
115
+ ...t,
116
+ content: o
117
+ } : t)), s.length > 0) {
118
+ let e = Date.now(), t = O.current;
119
+ s.forEach((n) => r({
120
+ kind: "pseudo_tool_call",
121
+ name: n.name,
122
+ args: n.args,
123
+ at: e,
124
+ turnSentAt: t
125
+ }));
126
+ }
127
+ return !0;
128
+ }
129
+ if (t.type === "response.output_item.added" || t.type === "response.output_item.done") {
130
+ let e = t.item;
131
+ if (e.type === "function_call" || e.type === "mcp_call") {
132
+ let n = Date.now(), i = O.current, a = e.name || "unknown_tool";
133
+ return r(t.type === "response.output_item.added" ? {
134
+ kind: "tool_start",
135
+ name: a,
136
+ args: e.arguments,
137
+ at: n,
138
+ turnSentAt: i
139
+ } : {
140
+ kind: "tool_end",
141
+ name: a,
142
+ args: e.arguments,
143
+ at: n,
144
+ turnSentAt: i,
145
+ output: e.output,
146
+ isError: e.is_error,
147
+ runtimeSeconds: e.runtime_seconds
148
+ }), !0;
149
+ }
150
+ return !1;
151
+ }
152
+ return t.type === "task.progress" ? (r({
153
+ kind: "progress",
154
+ status: t.status,
155
+ message: t.message,
156
+ at: Date.now(),
157
+ turnSentAt: O.current
158
+ }), !0) : t.type === "response.output_text.done" || t.type === "response.created" || t.type === "response.completed" ? !1 : t.type === "info" ? (r({
159
+ kind: "info",
160
+ message: t.message,
161
+ at: Date.now(),
162
+ turnSentAt: O.current
163
+ }), !0) : (r({
164
+ kind: "raw",
165
+ eventType: t.type,
166
+ raw: JSON.stringify(t),
167
+ at: Date.now(),
168
+ turnSentAt: O.current
169
+ }), !0);
170
+ }, []), I = t(async (t) => {
171
+ C("streaming"), T(null);
172
+ let n = crypto.randomUUID();
173
+ p((e) => [...e, {
174
+ id: n,
175
+ role: "assistant",
176
+ content: "",
177
+ streaming: !0
178
+ }]);
179
+ let i = Date.now();
180
+ O.current = i;
181
+ let a = t.map((e, t) => t === 0 && e.role === "user" && l ? {
182
+ role: e.role,
183
+ content: `${l}${e.content}`
184
+ } : {
185
+ role: e.role,
186
+ content: e.content
187
+ });
188
+ y({
189
+ model: r,
190
+ systemPrompt: o,
191
+ messages: a,
192
+ tools: s,
193
+ toolChoice: c,
194
+ stream: !0,
195
+ sentAt: i,
196
+ streamStats: {
197
+ chunkCount: 0,
198
+ firstChunkAt: null,
199
+ lastChunkAt: null
200
+ }
201
+ });
202
+ let d = new AbortController();
203
+ E.current = d, P(d);
204
+ let f = "", m = null, g = !1, _ = !1, b = [], S = (e, t) => {
205
+ C("error"), T(e);
206
+ let n = {
207
+ kind: "error",
208
+ message: e,
209
+ at: Date.now(),
210
+ turnSentAt: i,
211
+ ...t
212
+ };
213
+ b.push(n), h((e) => [...e, n]);
214
+ }, w = (e, t) => {
215
+ e.forEach((e) => {
216
+ if (e.type === "error") {
217
+ m = e.message;
218
+ let t = {
219
+ kind: "error",
220
+ message: e.message,
221
+ at: Date.now(),
222
+ turnSentAt: i
223
+ };
224
+ b.push(t), h((e) => [...e, t]);
225
+ return;
226
+ }
227
+ e.type === "response.output_text.delta" && e.delta && (_ = !0), F(n, e, b) && (g = !0);
228
+ }), t && p((e) => e.map((e) => e.id === n ? {
229
+ ...e,
230
+ streaming: !1
231
+ } : e));
232
+ };
233
+ try {
234
+ let { status: t, text: l, errorMessage: p } = await e.streamChat({
235
+ model: r,
236
+ instructions: o,
237
+ input: a,
238
+ tools: s,
239
+ toolChoice: c,
240
+ signal: d.signal,
241
+ onChunk: (e) => {
242
+ P(d), f += e;
243
+ let { events: t, remainder: n, done: r } = v(f);
244
+ f = n, w(t, r);
245
+ let a = Date.now();
246
+ y((e) => e && e.sentAt === i ? {
247
+ ...e,
248
+ streamStats: {
249
+ chunkCount: e.streamStats.chunkCount + 1,
250
+ firstChunkAt: e.streamStats.firstChunkAt ?? a,
251
+ lastChunkAt: a
252
+ }
253
+ } : e);
254
+ },
255
+ onRequestId: (e) => {
256
+ y((t) => t && t.sentAt === i ? {
257
+ ...t,
258
+ requestId: e
259
+ } : t);
260
+ }
261
+ });
262
+ if (f.trim()) {
263
+ let { events: e, done: t } = v(`${f}\n\n`);
264
+ f = "", w(e, t);
265
+ }
266
+ if (m) {
267
+ C("error"), T(m);
268
+ return;
269
+ }
270
+ if (t === void 0 || t >= 400) {
271
+ S(x(t, l, p), {
272
+ httpStatus: t,
273
+ rawBody: l || void 0
274
+ });
275
+ return;
276
+ }
277
+ if (!g) {
278
+ S("Bailey returned an empty response.");
279
+ return;
280
+ }
281
+ if (!_) {
282
+ S("Bailey ran some tools but didn't return an answer. Try asking again.");
283
+ return;
284
+ }
285
+ C("idle");
286
+ let h = j.current.get(n) ?? "";
287
+ y((e) => e && e.sentAt === i ? {
288
+ ...e,
289
+ response: { content: h }
290
+ } : e), u && await u({
291
+ id: n,
292
+ role: "assistant",
293
+ content: h,
294
+ streaming: !1
295
+ }, b);
296
+ } catch (e) {
297
+ let t = e;
298
+ if (t?.name === "TimeoutError") {
299
+ S(t.message, { source: "client-timeout" });
300
+ return;
301
+ }
302
+ if (t?.name === "AbortError") {
303
+ C("idle");
304
+ return;
305
+ }
306
+ S(t?.message || "Bailey request failed.");
307
+ } finally {
308
+ N(), A.current.delete(n), j.current.delete(n), p((e) => e.flatMap((e) => e.id === n ? e.content ? [{
309
+ ...e,
310
+ streaming: !1
311
+ }] : [] : [e]));
312
+ }
313
+ }, [
314
+ e,
315
+ r,
316
+ o,
317
+ s,
318
+ c,
319
+ l,
320
+ u,
321
+ F,
322
+ P,
323
+ N
324
+ ]);
325
+ return {
326
+ messages: f,
327
+ traceEvents: m,
328
+ lastRequest: _,
329
+ status: S,
330
+ error: w,
331
+ send: t((e) => {
332
+ let t = e.trim();
333
+ if (!t) return;
334
+ D.current = t;
335
+ let n = [...k.current, {
336
+ id: crypto.randomUUID(),
337
+ role: "user",
338
+ content: t
339
+ }];
340
+ k.current = n, p(n), I(n);
341
+ }, [I]),
342
+ stop: t(() => {
343
+ E.current?.abort();
344
+ }, []),
345
+ retryLast: t(() => {
346
+ if (!D.current) return;
347
+ let e = k.current, t = e[e.length - 1], n = t && t.role === "assistant" ? e.slice(0, -1) : e;
348
+ k.current = n, p(n), I(n);
349
+ }, [I]),
350
+ clearTrace: t(() => h([]), []),
351
+ clearError: t(() => {
352
+ T(null), C((e) => e === "error" ? "idle" : e);
353
+ }, [])
354
+ };
355
+ };
356
+ //#endregion
357
+ //#region src/utils/prompt.ts
358
+ function C(...e) {
359
+ return e.filter((e) => !!(e && e.trim())).join("\n\n");
360
+ }
361
+ //#endregion
362
+ //#region src/utils/toolCalls.ts
363
+ var w = "call_tool", T = "a tool";
364
+ function E(e, t) {
365
+ let n = {
366
+ name: e === w ? T : e,
367
+ args: null,
368
+ viaCallTool: !1
369
+ };
370
+ if (!t) return n;
371
+ let r;
372
+ try {
373
+ r = JSON.parse(t);
374
+ } catch {
375
+ return n;
376
+ }
377
+ if (typeof r != "object" || !r) return n;
378
+ let i = r;
379
+ if (e === w) {
380
+ let e = typeof i.name == "string" ? i.name : void 0;
381
+ if (!e) return n;
382
+ let t = i.arguments;
383
+ return {
384
+ name: e,
385
+ args: typeof t == "object" && t ? t : null,
386
+ viaCallTool: !0
387
+ };
388
+ }
389
+ return {
390
+ name: e,
391
+ args: i,
392
+ viaCallTool: !1
393
+ };
394
+ }
395
+ //#endregion
396
+ //#region src/utils/safeMarkdownUrl.ts
397
+ var D = /^(https?|mailto):/i, O = (e) => e.replace(/[\t\n\r]/g, "").trim(), k = (e) => {
398
+ let t = O(e);
399
+ return !/^[a-z][a-z0-9+.-]*:/i.test(t) || D.test(t);
400
+ }, A = 5, j = (e) => e.type === "text" ? e.value ?? "" : (e.children ?? []).map(j).join(""), M = (e) => {
401
+ if (e.tagName === "a" && e.properties?.href) return e.properties.href;
402
+ for (let t of e.children ?? []) {
403
+ let e = M(t);
404
+ if (e) return e;
405
+ }
406
+ }, N = (e, t) => (e.children ?? []).find((e) => e.tagName === t), P = (e) => {
407
+ let t = j(e), n = M(e);
408
+ return n ? {
409
+ text: t,
410
+ href: n
411
+ } : { text: t };
412
+ }, F = (e) => (e.children ?? []).filter((e) => e.type === "element").map(P), I = (e) => {
413
+ if (e.tagName !== "table") return null;
414
+ let t = N(e, "thead"), n = t && N(t, "tr");
415
+ return {
416
+ headers: n ? F(n).map((e) => e.text) : [],
417
+ rows: (N(e, "tbody")?.children ?? []).filter((e) => e.tagName === "tr").map(F)
418
+ };
419
+ }, L = (e) => e.length > 5, ee = "When a chart would help answer a question (e.g. plotting a trend over time), include a fenced code block tagged `chartjs` containing a JSON object with this exact shape: {\"type\": \"bar\" | \"line\" | \"pie\" | \"doughnut\" | \"scatter\", \"title\"?: string, \"data\": {\"labels\": string[], \"datasets\": [{\"label\": string, \"data\": number[]}]}}. For \"scatter\" charts, omit \"labels\" and give each dataset \"data\" as an array of {\"x\": number, \"y\": number} points instead of a number array. \"pie\" and \"doughnut\" charts must have exactly one dataset. Do not include any other fields (no \"options\", no colors) — the app handles styling. Example:\n```chartjs\n{\"type\": \"line\", \"title\": \"BP readings\", \"data\": {\"labels\": [\"Jul 14\", \"Jul 21\", \"Jul 28\"], \"datasets\": [{\"label\": \"Systolic\", \"data\": [120, 118, 122]}]}}\n```", te = [
420
+ "bar",
421
+ "line",
422
+ "pie",
423
+ "doughnut",
424
+ "scatter"
425
+ ], ne = 8, re = 50, ie = 8, ae = 500, oe = (e) => typeof e == "object" && !!e && typeof e.x == "number" && typeof e.y == "number", R = (e) => {
426
+ let t;
427
+ try {
428
+ t = JSON.parse(e);
429
+ } catch {
430
+ return null;
431
+ }
432
+ if (typeof t != "object" || !t) return null;
433
+ let n = t;
434
+ if (typeof n.type != "string" || !te.includes(n.type)) return null;
435
+ let r = n.type;
436
+ if (n.title !== void 0 && typeof n.title != "string") return null;
437
+ let i = n.title;
438
+ if (typeof n.data != "object" || n.data === null) return null;
439
+ let a = n.data;
440
+ if (!Array.isArray(a.datasets) || a.datasets.length < 1 || a.datasets.length > ne || (r === "pie" || r === "doughnut") && a.datasets.length !== 1) return null;
441
+ for (let e of a.datasets) if (typeof e != "object" || !e || typeof e.label != "string" || !Array.isArray(e.data)) return null;
442
+ let o = a.datasets;
443
+ if (r === "scatter") {
444
+ for (let e of o) if (e.data.length < 1 || e.data.length > ae || !e.data.every(oe)) return null;
445
+ return {
446
+ type: r,
447
+ title: i,
448
+ data: { datasets: o }
449
+ };
450
+ }
451
+ if (!Array.isArray(a.labels) || !a.labels.every((e) => typeof e == "string")) return null;
452
+ let s = a.labels, c = r === "pie" || r === "doughnut" ? ie : re;
453
+ if (s.length < 1 || s.length > c) return null;
454
+ for (let e of o) if (e.data.length !== s.length || !e.data.every((e) => typeof e == "number")) return null;
455
+ return {
456
+ type: r,
457
+ title: i,
458
+ data: {
459
+ labels: s,
460
+ datasets: o
461
+ }
462
+ };
463
+ }, z = {
464
+ tool_start: "Tool start",
465
+ tool_end: "Tool end",
466
+ pseudo_tool_call: "Narrated tool call",
467
+ progress: "Progress",
468
+ info: "Info",
469
+ error: "Error",
470
+ raw: "Raw event"
471
+ };
472
+ function B(e) {
473
+ return e.kind !== "tool_start" && e.kind !== "tool_end" ? null : E(e.name, e.args);
474
+ }
475
+ function V(e, t = B(e)) {
476
+ return e.kind === "pseudo_tool_call" ? e.name : t?.name ?? null;
477
+ }
478
+ function H(e, t = B(e)) {
479
+ switch (e.kind) {
480
+ case "tool_start": return t.viaCallTool ? `${t.name} (via call_tool)` : t.name;
481
+ case "tool_end": return `${t.viaCallTool ? `${t.name} (via call_tool)` : t.name}${e.runtimeSeconds === void 0 ? "" : ` — ${e.runtimeSeconds.toFixed(2)}s`}${e.isError ? " — failed" : ""}`;
482
+ case "pseudo_tool_call": return `${e.name} — written as text, not actually called`;
483
+ case "progress": return e.message ? `${e.status} — ${e.message}` : e.status;
484
+ case "info": return e.message;
485
+ case "error": return e.httpStatus ? `${e.message} (HTTP ${e.httpStatus})` : e.message;
486
+ case "raw": return `Unrecognized event: ${e.eventType}`;
487
+ }
488
+ }
489
+ function U(e, t = B(e)) {
490
+ return e.kind === "tool_start" || e.kind === "tool_end" ? t.args ? JSON.stringify(t.args, null, 2) : e.args ?? null : e.kind === "pseudo_tool_call" ? e.args ?? null : null;
491
+ }
492
+ function W(e) {
493
+ return e.kind === "tool_end" ? e.output ?? null : null;
494
+ }
495
+ function G(e) {
496
+ return e.kind === "raw" ? e.raw : e.kind === "error" ? e.rawBody ?? null : null;
497
+ }
498
+ function K(e) {
499
+ switch (e.kind) {
500
+ case "tool_start": return `Calling ${E(e.name, e.args).name}...`;
501
+ case "tool_end": {
502
+ let t = E(e.name, e.args).name;
503
+ return e.isError ? `${t} failed` : `${t} returned`;
504
+ }
505
+ case "pseudo_tool_call": return `${e.name} (written as text, not called)`;
506
+ case "progress": return e.message ?? e.status;
507
+ case "info": return e.message;
508
+ case "error": return e.source === "client-timeout" ? `Timed out: ${e.message}` : `Error: ${e.message}`;
509
+ case "raw": return `Unrecognized event: ${e.eventType}`;
510
+ }
511
+ }
512
+ function q(e) {
513
+ let t = new Date(e);
514
+ return `${String(t.getHours()).padStart(2, "0")}:${String(t.getMinutes()).padStart(2, "0")}:${String(t.getSeconds()).padStart(2, "0")}.${String(t.getMilliseconds()).padStart(3, "0")}`;
515
+ }
516
+ function J(e) {
517
+ if (e <= 0) return "+0ms";
518
+ if (e < 1e3) return `+${Math.round(e)}ms`;
519
+ let t = e / 1e3;
520
+ if (t < 60) return `+${t.toFixed(1)}s`;
521
+ let n = Math.floor(t / 60), r = Math.round(t % 60);
522
+ return `+${n}m${String(r).padStart(2, "0")}s`;
523
+ }
524
+ function Y(e) {
525
+ return e.map((t, n) => {
526
+ let r = B(t), i = n === 0 ? t.turnSentAt : e[n - 1].at;
527
+ return {
528
+ key: `${t.at}-${n}`,
529
+ kind: t.kind,
530
+ toolName: V(t, r),
531
+ isToolStart: t.kind === "tool_start",
532
+ failed: t.kind === "tool_end" && t.isError === !0,
533
+ time: q(t.at),
534
+ gapMs: t.at - i,
535
+ label: t.kind === "tool_end" && t.isError === !0 ? "Tool failed" : z[t.kind],
536
+ summary: H(t, r),
537
+ argsDetail: U(t, r),
538
+ outputDetail: W(t),
539
+ rawDetail: G(t)
540
+ };
541
+ });
542
+ }
543
+ function X(e) {
544
+ let t = e.filter((e) => e.kind === "tool_end"), n = t.filter((e) => e.kind === "tool_end" && e.isError), r = e.filter((e) => e.kind === "error"), i = [];
545
+ return t.length > 0 && i.push(`${t.length} tool call${t.length === 1 ? "" : "s"}` + (n.length > 0 ? `, ${n.length} failed` : "")), r.length > 0 && i.push(`${r.length} stream error${r.length === 1 ? "" : "s"}`), i.join(" · ");
546
+ }
547
+ function Z(e) {
548
+ let t = [];
549
+ for (let n of e) {
550
+ let e = t[t.length - 1];
551
+ if (n.toolName && e?.type === "group" && e.toolName === n.toolName) {
552
+ e.rows.push(n);
553
+ continue;
554
+ }
555
+ t.push(n.toolName ? {
556
+ type: "group",
557
+ toolName: n.toolName,
558
+ rows: [n]
559
+ } : {
560
+ type: "single",
561
+ row: n
562
+ });
563
+ }
564
+ return t;
565
+ }
566
+ function se(e) {
567
+ return e.some((e) => e.kind === "tool_end" && e.isError || e.kind === "error");
568
+ }
569
+ //#endregion
570
+ //#region src/ui/markdown.tsx
571
+ function ce({ renderTable: e, renderChart: t } = {}) {
572
+ return {
573
+ a: ({ href: e, children: t }) => !e || !k(e) ? /* @__PURE__ */ l(c, { children: t }) : /* @__PURE__ */ l("a", {
574
+ href: e,
575
+ target: "_blank",
576
+ rel: "noopener noreferrer",
577
+ children: t
578
+ }),
579
+ table: ({ node: t, children: n }) => {
580
+ let r = t && I(t);
581
+ if (r && L(r.rows) && e) {
582
+ let t = r.rows.map((e) => e.map((e) => e.href && !k(e.href) ? { text: e.text } : e));
583
+ return /* @__PURE__ */ l(c, { children: e({
584
+ headers: r.headers,
585
+ rows: t
586
+ }) });
587
+ }
588
+ return /* @__PURE__ */ l("table", { children: n });
589
+ },
590
+ pre: ({ children: e }) => {
591
+ let n = (Array.isArray(e) ? e[0] : e)?.props;
592
+ if ((n?.className?.split(" ") ?? []).includes("language-chartjs") && t) {
593
+ let e = n?.children, r = R(Array.isArray(e) ? e.join("") : String(e ?? ""));
594
+ if (r) return /* @__PURE__ */ l(c, { children: t(r) });
595
+ }
596
+ return /* @__PURE__ */ l("pre", { children: e });
597
+ }
598
+ };
599
+ }
600
+ //#endregion
601
+ //#region src/ui/CopyMarkdownButton.tsx
602
+ var le = 1500;
603
+ function ue({ markdown: e, className: t }) {
604
+ let [r, o] = a(!1), [s, c] = a(!1), f = i(null);
605
+ return n(() => () => {
606
+ f.current !== null && clearTimeout(f.current);
607
+ }, []), /* @__PURE__ */ l(d.Provider, {
608
+ delayDuration: 200,
609
+ children: /* @__PURE__ */ u(d.Root, {
610
+ open: r || s,
611
+ onOpenChange: c,
612
+ children: [/* @__PURE__ */ l(d.Trigger, {
613
+ asChild: !0,
614
+ children: /* @__PURE__ */ l("button", {
615
+ type: "button",
616
+ onClick: async () => {
617
+ try {
618
+ await navigator.clipboard.writeText(e);
619
+ } catch {}
620
+ o(!0), f.current !== null && clearTimeout(f.current), f.current = setTimeout(() => o(!1), le);
621
+ },
622
+ "aria-label": "copy response as markdown",
623
+ className: `bailey-copy-button${t ? ` ${t}` : ""}`,
624
+ children: r ? "✓" : "⧉"
625
+ })
626
+ }), /* @__PURE__ */ l(d.Portal, { children: /* @__PURE__ */ u(d.Content, {
627
+ side: "top",
628
+ className: "bailey-tooltip-content",
629
+ children: [r ? "Copied!" : "Copy as markdown", /* @__PURE__ */ l(d.Arrow, { className: "bailey-tooltip-arrow" })]
630
+ }) })]
631
+ })
632
+ });
633
+ }
634
+ //#endregion
635
+ //#region src/ui/BaileyTracePanel.tsx
636
+ async function de(e) {
637
+ try {
638
+ await navigator.clipboard.writeText(e);
639
+ } catch {}
640
+ }
641
+ function fe({ text: e, label: t = "Copy" }) {
642
+ return /* @__PURE__ */ l("button", {
643
+ type: "button",
644
+ onClick: () => de(e),
645
+ className: "bailey-trace-copy-button",
646
+ children: t
647
+ });
648
+ }
649
+ function pe(e) {
650
+ if (e.failed || e.kind === "error") return "bailey-trace-chip bailey-trace-chip-error";
651
+ switch (e.kind) {
652
+ case "tool_start": return "bailey-trace-chip bailey-trace-chip-info";
653
+ case "tool_end": return "bailey-trace-chip bailey-trace-chip-success";
654
+ case "progress": return "bailey-trace-chip bailey-trace-chip-secondary";
655
+ default: return "bailey-trace-chip bailey-trace-chip-default";
656
+ }
657
+ }
658
+ function Q({ label: e, content: t, copyable: n }) {
659
+ return /* @__PURE__ */ u("details", {
660
+ className: "bailey-trace-disclosure",
661
+ children: [
662
+ /* @__PURE__ */ l("summary", {
663
+ className: "bailey-trace-disclosure-summary",
664
+ children: e
665
+ }),
666
+ n && /* @__PURE__ */ l("div", {
667
+ className: "bailey-trace-disclosure-actions",
668
+ children: /* @__PURE__ */ l(fe, { text: t })
669
+ }),
670
+ /* @__PURE__ */ l("pre", {
671
+ className: "bailey-trace-disclosure-content",
672
+ children: t
673
+ })
674
+ ]
675
+ });
676
+ }
677
+ function $({ row: e }) {
678
+ return /* @__PURE__ */ u("div", {
679
+ className: "bailey-trace-row",
680
+ children: [
681
+ /* @__PURE__ */ u("div", {
682
+ className: "bailey-trace-row-header",
683
+ children: [
684
+ /* @__PURE__ */ l("span", {
685
+ className: "bailey-trace-row-time",
686
+ children: e.time
687
+ }),
688
+ /* @__PURE__ */ l("span", {
689
+ className: "bailey-trace-row-gap",
690
+ title: "Time since the previous event",
691
+ children: J(e.gapMs)
692
+ }),
693
+ /* @__PURE__ */ l("span", {
694
+ className: pe(e),
695
+ children: e.label
696
+ }),
697
+ /* @__PURE__ */ l("span", {
698
+ className: "bailey-trace-row-summary",
699
+ children: e.summary
700
+ })
701
+ ]
702
+ }),
703
+ e.argsDetail && /* @__PURE__ */ l(Q, {
704
+ label: "args",
705
+ content: e.argsDetail
706
+ }),
707
+ e.outputDetail && /* @__PURE__ */ l(Q, {
708
+ label: "output",
709
+ content: e.outputDetail
710
+ }),
711
+ e.rawDetail && /* @__PURE__ */ l(Q, {
712
+ label: "raw",
713
+ content: e.rawDetail
714
+ })
715
+ ]
716
+ });
717
+ }
718
+ function me(e, t) {
719
+ if (e.chunkCount === 0) return "Streamed: no chunks received";
720
+ if (e.chunkCount === 1 || e.firstChunkAt === null) return "Streamed: 1 chunk (not incremental)";
721
+ let n = e.firstChunkAt - t, r = (e.lastChunkAt ?? e.firstChunkAt) - e.firstChunkAt;
722
+ return `Streamed: ${e.chunkCount} chunks · first chunk after ${n}ms · spread over ${(r / 1e3).toFixed(1)}s`;
723
+ }
724
+ function he({ request: e }) {
725
+ let t = r(() => JSON.stringify({
726
+ model: e.model,
727
+ instructions: e.systemPrompt,
728
+ input: e.messages,
729
+ stream: e.stream,
730
+ tools: e.tools,
731
+ toolChoice: e.toolChoice
732
+ }, null, 2), [e]);
733
+ return /* @__PURE__ */ u("div", {
734
+ className: "bailey-trace-request-details",
735
+ children: [
736
+ /* @__PURE__ */ u("span", {
737
+ className: "bailey-trace-request-meta",
738
+ children: [
739
+ "Last request — ",
740
+ e.model,
741
+ " · ",
742
+ new Date(e.sentAt).toLocaleTimeString(),
743
+ e.requestId ? ` · ${e.requestId}` : ""
744
+ ]
745
+ }),
746
+ /* @__PURE__ */ l("span", {
747
+ className: "bailey-trace-request-meta",
748
+ children: me(e.streamStats, e.sentAt)
749
+ }),
750
+ /* @__PURE__ */ l(Q, {
751
+ label: `System prompt (${e.systemPrompt.length.toLocaleString()} chars)`,
752
+ content: e.systemPrompt,
753
+ copyable: !0
754
+ }),
755
+ /* @__PURE__ */ l(Q, {
756
+ label: `Messages (${e.messages.length})`,
757
+ content: JSON.stringify(e.messages, null, 2),
758
+ copyable: !0
759
+ }),
760
+ e.response && /* @__PURE__ */ l(Q, {
761
+ label: `Response (${e.response.content.length.toLocaleString()} chars)`,
762
+ content: e.response.content,
763
+ copyable: !0
764
+ }),
765
+ /* @__PURE__ */ l(Q, {
766
+ label: "Full payload (JSON)",
767
+ content: t,
768
+ copyable: !0
769
+ })
770
+ ]
771
+ });
772
+ }
773
+ function ge({ events: e, lastRequest: t, onClear: n }) {
774
+ let i = r(() => Y(e), [e]), a = r(() => Z(i), [i]), o = r(() => JSON.stringify(e, null, 2), [e]);
775
+ return /* @__PURE__ */ u("div", {
776
+ className: "bailey-trace-body",
777
+ children: [
778
+ /* @__PURE__ */ u("div", {
779
+ className: "bailey-trace-actions-row",
780
+ children: [e.length > 0 && /* @__PURE__ */ l(fe, {
781
+ text: o,
782
+ label: "Copy trace as JSON"
783
+ }), /* @__PURE__ */ l("button", {
784
+ type: "button",
785
+ onClick: n,
786
+ className: "bailey-trace-copy-button",
787
+ children: "Clear"
788
+ })]
789
+ }),
790
+ t && /* @__PURE__ */ l(he, { request: t }),
791
+ /* @__PURE__ */ l("div", {
792
+ className: "bailey-trace-rows",
793
+ children: a.map((e, t) => {
794
+ if (e.type === "single") return /* @__PURE__ */ l($, { row: e.row }, e.row.key);
795
+ let n = e.rows.filter((e) => e.isToolStart).length;
796
+ if (n <= 1) return /* @__PURE__ */ l("div", {
797
+ className: "bailey-trace-rows",
798
+ children: e.rows.map((e) => /* @__PURE__ */ l($, { row: e }, e.key))
799
+ }, `group-${t}`);
800
+ let r = e.rows.filter((e) => e.failed).length;
801
+ return /* @__PURE__ */ u("details", {
802
+ className: "bailey-trace-group",
803
+ children: [/* @__PURE__ */ u("summary", {
804
+ className: "bailey-trace-group-summary",
805
+ children: [
806
+ /* @__PURE__ */ l("strong", { children: e.toolName }),
807
+ " × ",
808
+ n,
809
+ r > 0 && /* @__PURE__ */ u("span", {
810
+ className: "bailey-trace-group-failed",
811
+ children: [
812
+ " ",
813
+ r,
814
+ " failed"
815
+ ]
816
+ })
817
+ ]
818
+ }), /* @__PURE__ */ l("div", {
819
+ className: "bailey-trace-rows",
820
+ children: e.rows.map((e) => /* @__PURE__ */ l($, { row: e }, e.key))
821
+ })]
822
+ }, `group-${t}`);
823
+ })
824
+ })
825
+ ]
826
+ });
827
+ }
828
+ function _e({ events: e, lastRequest: t, onClear: n }) {
829
+ let [i, o] = a(!1), s = r(() => se(e), [e]), c = r(() => X(e), [e]);
830
+ return e.length === 0 && !t ? null : /* @__PURE__ */ u("div", {
831
+ className: "bailey-trace-panel",
832
+ children: [/* @__PURE__ */ u("div", {
833
+ className: "bailey-trace-toggle-row",
834
+ children: [/* @__PURE__ */ u("button", {
835
+ type: "button",
836
+ onClick: () => o((e) => !e),
837
+ "aria-expanded": i,
838
+ className: s ? "bailey-trace-toggle bailey-trace-toggle-error" : "bailey-trace-toggle",
839
+ children: [
840
+ s && !i ? "⚠ " : "",
841
+ i ? "Hide details" : "Show details",
842
+ " (",
843
+ e.length,
844
+ ")"
845
+ ]
846
+ }), c && /* @__PURE__ */ l("span", {
847
+ className: s ? "bailey-trace-summary bailey-trace-summary-error" : "bailey-trace-summary",
848
+ children: c
849
+ })]
850
+ }), i && /* @__PURE__ */ l(ge, {
851
+ events: e,
852
+ lastRequest: t,
853
+ onClear: n
854
+ })]
855
+ });
856
+ }
857
+ //#endregion
858
+ //#region src/ui/BaileyChatPanel.tsx
859
+ var ve = [s], ye = e(function({ content: e, components: t }) {
860
+ return /* @__PURE__ */ l("div", {
861
+ className: "bailey-markdown-content",
862
+ children: /* @__PURE__ */ l(o, {
863
+ remarkPlugins: ve,
864
+ components: t,
865
+ children: e
866
+ })
867
+ });
868
+ });
869
+ function be(e, t, n) {
870
+ if (e !== "streaming") return;
871
+ let r = t.filter((e) => e.turnSentAt === n?.sentAt);
872
+ if (r.length !== 0) return K(r[r.length - 1]);
873
+ }
874
+ function xe({ chat: e, placeholder: t = "Send a message…", className: o, renderMessageActions: s, renderTable: c, renderChart: d }) {
875
+ let { messages: f, traceEvents: p, lastRequest: m, status: h, error: g, send: _, stop: v, retryLast: y, clearTrace: b, clearError: x } = e, [S, C] = a(""), w = i(null), T = r(() => ce({
876
+ renderTable: c,
877
+ renderChart: d
878
+ }), [c, d]), E = r(() => be(h, p, m), [
879
+ h,
880
+ p,
881
+ m
882
+ ]);
883
+ return n(() => {
884
+ w.current?.scrollIntoView({
885
+ behavior: "smooth",
886
+ block: "nearest"
887
+ });
888
+ }, [f]), /* @__PURE__ */ u("div", {
889
+ className: `bailey-chat-panel${o ? ` ${o}` : ""}`,
890
+ children: [
891
+ /* @__PURE__ */ u("div", {
892
+ className: "bailey-chat-transcript",
893
+ children: [
894
+ f.length === 0 && /* @__PURE__ */ l("div", {
895
+ className: "bailey-empty-state",
896
+ children: "Ask Bailey a question to get started."
897
+ }),
898
+ f.map((e, t) => {
899
+ let n = e.role === "assistant" && t === f.length - 1, r = h === "streaming" && n && e.content === "";
900
+ return /* @__PURE__ */ l("div", {
901
+ className: e.role === "user" ? "bailey-message-row bailey-message-row-user" : "bailey-message-row",
902
+ children: e.role === "user" ? /* @__PURE__ */ l("div", {
903
+ className: "bailey-user-bubble",
904
+ children: e.content
905
+ }) : r ? /* @__PURE__ */ l("div", {
906
+ className: "bailey-thinking-hint",
907
+ children: E ?? "Thinking…"
908
+ }) : /* @__PURE__ */ u("div", {
909
+ className: "bailey-assistant-message",
910
+ children: [
911
+ /* @__PURE__ */ l(ye, {
912
+ content: e.content,
913
+ components: T
914
+ }),
915
+ e.streaming && E && /* @__PURE__ */ l("div", {
916
+ className: "bailey-streaming-hint",
917
+ children: E
918
+ }),
919
+ !e.streaming && /* @__PURE__ */ u("div", {
920
+ className: "bailey-message-actions",
921
+ children: [/* @__PURE__ */ l(ue, { markdown: e.content }), s?.(e)]
922
+ })
923
+ ]
924
+ })
925
+ }, e.id);
926
+ }),
927
+ /* @__PURE__ */ l("div", { ref: w })
928
+ ]
929
+ }),
930
+ g && /* @__PURE__ */ u("div", {
931
+ className: "bailey-error-banner",
932
+ role: "alert",
933
+ children: [/* @__PURE__ */ l("span", { children: g }), /* @__PURE__ */ u("div", {
934
+ className: "bailey-error-actions",
935
+ children: [/* @__PURE__ */ l("button", {
936
+ type: "button",
937
+ onClick: y,
938
+ className: "bailey-retry-button",
939
+ children: "Retry"
940
+ }), /* @__PURE__ */ l("button", {
941
+ type: "button",
942
+ onClick: x,
943
+ "aria-label": "dismiss error",
944
+ className: "bailey-dismiss-button",
945
+ children: "✕"
946
+ })]
947
+ })]
948
+ }),
949
+ /* @__PURE__ */ l(_e, {
950
+ events: p,
951
+ lastRequest: m,
952
+ onClear: b
953
+ }),
954
+ /* @__PURE__ */ u("form", {
955
+ onSubmit: (e) => {
956
+ e.preventDefault(), !(!S.trim() || h === "streaming") && (_(S), C(""));
957
+ },
958
+ className: "bailey-input-row",
959
+ children: [/* @__PURE__ */ l("input", {
960
+ type: "text",
961
+ placeholder: t,
962
+ "aria-label": t,
963
+ value: S,
964
+ onChange: (e) => C(e.target.value),
965
+ disabled: h === "streaming",
966
+ className: "bailey-input"
967
+ }), h === "streaming" ? /* @__PURE__ */ l("button", {
968
+ type: "button",
969
+ onClick: v,
970
+ "aria-label": "stop",
971
+ className: "bailey-stop-button",
972
+ children: "Stop"
973
+ }) : /* @__PURE__ */ l("button", {
974
+ type: "submit",
975
+ "aria-label": "send",
976
+ disabled: !S.trim(),
977
+ className: "bailey-send-button",
978
+ children: "Send"
979
+ })]
980
+ })
981
+ ]
982
+ });
983
+ }
984
+ //#endregion
985
+ //#region src/index.ts
986
+ var Se = "0.2.1-pre.0";
987
+ //#endregion
988
+ export { Se as BAILEYAI_CHAT_UI_VERSION, ee as BAILEY_CHART_PROMPT_FRAGMENT, A as BAILEY_TABLE_GRID_ROW_THRESHOLD, xe as BaileyChatPanel, _e as BaileyTracePanel, ue as CopyMarkdownButton, z as TRACE_KIND_LABEL, ce as createBaileyMarkdownComponents, g as extractPseudoToolCalls, I as extractTableData, J as formatTraceGap, q as formatTraceTime, se as hasTraceFailure, k as isSafeMarkdownUrl, C as joinInstructions, R as parseBaileyChartSpec, v as parseSseFrames, E as resolveToolCall, L as shouldUseGrid, Y as toTraceRows, Z as toTraceSegments, U as traceEventArgsDetail, K as traceEventHint, W as traceEventOutputDetail, G as traceEventRawDetail, H as traceEventSummary, V as traceEventToolName, X as traceSummaryLine, S as useBaileyChat };