besser-agentic-framework-ui 0.1.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,1645 @@
1
+ import { useCallback as e, useEffect as t, useId 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 c from "dompurify";
5
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
6
+ //#region src/types/payload.ts
7
+ var d = {
8
+ USER_MESSAGE: "user_message",
9
+ USER_VOICE: "user_voice",
10
+ USER_FILE: "user_file",
11
+ USER_SET_VARIABLE: "user_set_variable",
12
+ RESET: "reset",
13
+ AGENT_REPLY_STR: "agent_reply_str",
14
+ AGENT_REPLY_MARKDOWN: "agent_reply_markdown",
15
+ AGENT_REPLY_HTML: "agent_reply_html",
16
+ AGENT_REPLY_FILE: "agent_reply_file",
17
+ AGENT_REPLY_IMAGE: "agent_reply_image",
18
+ AGENT_REPLY_DF: "agent_reply_dataframe",
19
+ AGENT_REPLY_PLOTLY: "agent_reply_plotly",
20
+ AGENT_REPLY_OPTIONS: "agent_reply_options",
21
+ AGENT_REPLY_LOCATION: "agent_reply_location",
22
+ AGENT_REPLY_RAG: "agent_reply_rag",
23
+ AGENT_REPLY_REASONING_STEP: "agent_reply_reasoning_step",
24
+ AGENT_REPLY_TASK_LIST_UPDATE: "agent_reply_task_list_update",
25
+ AGENT_REPLY_AUDIO: "agent_reply_audio",
26
+ AGENT_REPLY_UI: "agent_reply_ui",
27
+ USER_UPDATE_UI: "user_update_ui",
28
+ FETCH_USER_MESSAGES: "fetch_user_messages"
29
+ }, f = {
30
+ REASONING_STARTED: "reasoning_started",
31
+ REASONING_FINISHED: "reasoning_finished",
32
+ LLM_TEXT: "llm_text",
33
+ LLM_TOOL_CALLS: "llm_tool_calls",
34
+ TOOL_RESULT: "tool_result",
35
+ TASK_ADDED: "task_added",
36
+ TASK_COMPLETED: "task_completed",
37
+ TASK_SKIPPED: "task_skipped",
38
+ PUSHBACK: "pushback",
39
+ MAX_STEPS: "max_steps"
40
+ }, p = {
41
+ PENDING: "pending",
42
+ IN_PROGRESS: "in_progress",
43
+ COMPLETED: "completed",
44
+ SKIPPED: "skipped"
45
+ }, m = "reasoning_trace";
46
+ function h(e) {
47
+ return e.kind === f.REASONING_STARTED;
48
+ }
49
+ function g(e) {
50
+ return e.kind === f.REASONING_FINISHED;
51
+ }
52
+ function _(e) {
53
+ return e.steps.filter((e) => !h(e) && !g(e));
54
+ }
55
+ function v(e) {
56
+ return _(e).length === 0;
57
+ }
58
+ //#endregion
59
+ //#region src/utils/contentDetect.ts
60
+ var y = [
61
+ /^#{1,6}\s+\S/m,
62
+ /^\s*[-*+]\s+\S/m,
63
+ /^\s*\d+\.\s+\S/m,
64
+ /\*\*[^*\n]+\*\*/,
65
+ /(^|[^_])__[^_\n]+__([^_]|$)/,
66
+ /```[\s\S]*?```/,
67
+ /`[^`\n]+`/,
68
+ /\[[^\]]+\]\([^)\s]+\)/,
69
+ /^>\s+\S/m,
70
+ /^\|[^\n]+\|\s*$/m,
71
+ /^---+\s*$/m
72
+ ];
73
+ function b(e) {
74
+ return !e || e.length < 2 ? !1 : y.some((t) => t.test(e));
75
+ }
76
+ var x = RegExp("^\\s*(" + [
77
+ "function\\s",
78
+ "def\\s",
79
+ "class\\s",
80
+ "interface\\s",
81
+ "enum\\s",
82
+ "import\\s",
83
+ "from\\s+\\S+\\s+import\\s",
84
+ "package\\s",
85
+ "const\\s",
86
+ "let\\s",
87
+ "var\\s",
88
+ "public\\s",
89
+ "private\\s",
90
+ "protected\\s",
91
+ "static\\s",
92
+ "async\\s+function\\s",
93
+ "async\\s+def\\s",
94
+ "#include\\b",
95
+ "<\\?php\\b",
96
+ "<!DOCTYPE\\s"
97
+ ].join("|") + ")", "m");
98
+ function S(e) {
99
+ if (!e || e.length < 8) return !1;
100
+ let t = e.split("\n");
101
+ return t.length < 2 ? !1 : !!(x.test(e) || (e.match(/[{}();=]/g) ?? []).length / e.length > .05 && t.length >= 3);
102
+ }
103
+ function C(e) {
104
+ return b(e) ? "markdown" : S(e) ? "code" : "plain";
105
+ }
106
+ //#endregion
107
+ //#region src/components/GUIRenderer.tsx
108
+ function w(e) {
109
+ return e.replace(/_([a-z])/g, (e, t) => t.toUpperCase());
110
+ }
111
+ var T = new Set(["unit_size", "icon_size"]), E = new Set([
112
+ "color_palette",
113
+ "primary_color",
114
+ "line_color",
115
+ "grid_color",
116
+ "axis_color",
117
+ "bar_color",
118
+ "label_color",
119
+ "fill_color"
120
+ ]), D = {
121
+ background_color: "background",
122
+ text_color: "color"
123
+ }, O = new Set(["layout_type"]), k = new Set(["p_type", "alignment"]);
124
+ function A(e) {
125
+ if (!e) return {};
126
+ let t = {};
127
+ if (e.size) for (let [n, r] of Object.entries(e.size)) !r || T.has(n) || (t[w(n)] = r);
128
+ if (e.position) for (let [n, r] of Object.entries(e.position)) !r || k.has(n) || (n === "display" ? r === "table" || r === "table-row" ? (t.display = "flex", t.flexWrap = "wrap", t.alignItems = "stretch") : r === "table-cell" ? (t.display = "flex", t.flex = "1", t.flexDirection = "column", t.height = "auto") : t.display = r : t[w(n)] = r);
129
+ if (e.color) for (let [n, r] of Object.entries(e.color)) !r || E.has(n) || (t[D[n] ?? w(n)] = r);
130
+ if (e.layout) {
131
+ let n = e.layout.layout_type;
132
+ n === "flex" ? t.display = "flex" : n === "grid" && (t.display = "grid");
133
+ for (let [n, r] of Object.entries(e.layout)) !r || O.has(n) || (t[w(n)] = r);
134
+ }
135
+ return t;
136
+ }
137
+ function j(e, t) {
138
+ if (!Array.isArray(e)) return "";
139
+ let n = "";
140
+ for (let r of e) {
141
+ if (!r.selectors?.length || !r.style) continue;
142
+ let e = { ...r.style }, i = e.display;
143
+ i === "table" || i === "table-row" ? (e.display = "flex", e["flex-wrap"] = "wrap") : i === "table-cell" && (e.display = "flex", e["flex-direction"] = "column", e.flex = "1", delete e.height, delete e.width);
144
+ let a = Object.entries(e).map(([e, t]) => ` ${e}: ${t};`).join("\n"), o = (e) => `${e} {\n${a}\n}`, s = r.selectors.map((e) => `.${t} ${e}`).join(", ");
145
+ r.atRuleType === "media" && r.mediaText ? n += `@media ${r.mediaText} {\n${o(s)}\n}\n` : n += o(s) + "\n";
146
+ }
147
+ return n;
148
+ }
149
+ function M(e) {
150
+ let t = [], n = e.custom_attributes?.series;
151
+ if (typeof n == "string") try {
152
+ t = JSON.parse(n);
153
+ } catch {}
154
+ let r = e.show_legend !== !1, i = {
155
+ paper_bgcolor: "transparent",
156
+ plot_bgcolor: "#f8f9fa",
157
+ font: {
158
+ family: "inherit",
159
+ size: 12
160
+ },
161
+ margin: {
162
+ t: e.title ? 40 : 20,
163
+ r: 10,
164
+ b: 40,
165
+ l: 50
166
+ },
167
+ showlegend: r,
168
+ legend: {
169
+ orientation: "h",
170
+ y: -.25,
171
+ font: { size: 11 }
172
+ }
173
+ };
174
+ switch (e.title && (i.title = {
175
+ text: e.title,
176
+ font: { size: 14 },
177
+ x: .5
178
+ }), e.type) {
179
+ case "LineChart": return {
180
+ traces: t.map((t) => ({
181
+ type: "scatter",
182
+ mode: "lines+markers",
183
+ name: t.name,
184
+ x: (t.data ?? []).map((e) => e.name ?? e.subject),
185
+ y: (t.data ?? []).map((e) => e.value),
186
+ line: {
187
+ color: t.color,
188
+ width: e.line_width ?? 2,
189
+ shape: e.curve_type === "monotone" ? "spline" : "linear"
190
+ },
191
+ marker: {
192
+ color: t.color,
193
+ size: e.dot_size ?? 5
194
+ }
195
+ })),
196
+ layout: i
197
+ };
198
+ case "BarChart": {
199
+ let n = e.orientation === "horizontal";
200
+ return {
201
+ traces: t.map((e) => ({
202
+ type: "bar",
203
+ name: e.name,
204
+ ...n ? {
205
+ x: (e.data ?? []).map((e) => e.value),
206
+ y: (e.data ?? []).map((e) => e.name ?? e.subject),
207
+ orientation: "h"
208
+ } : {
209
+ x: (e.data ?? []).map((e) => e.name ?? e.subject),
210
+ y: (e.data ?? []).map((e) => e.value)
211
+ },
212
+ marker: { color: e.color }
213
+ })),
214
+ layout: {
215
+ ...i,
216
+ barmode: e.stacked ? "stack" : "group"
217
+ }
218
+ };
219
+ }
220
+ case "PieChart": {
221
+ let n = t[0];
222
+ return {
223
+ traces: n ? [{
224
+ type: "pie",
225
+ name: n.name,
226
+ labels: (n.data ?? []).map((e) => e.name ?? e.subject),
227
+ values: (n.data ?? []).map((e) => e.value),
228
+ marker: { colors: t.map((e) => e.color).filter(Boolean) }
229
+ }] : [],
230
+ layout: {
231
+ ...i,
232
+ margin: {
233
+ t: e.title ? 40 : 20,
234
+ r: 0,
235
+ b: 0,
236
+ l: 0
237
+ }
238
+ }
239
+ };
240
+ }
241
+ case "RadarChart": return {
242
+ traces: t.map((e) => ({
243
+ type: "scatterpolar",
244
+ fill: "toself",
245
+ name: e.name,
246
+ r: (e.data ?? []).map((e) => e.value),
247
+ theta: (e.data ?? []).map((e) => e.subject ?? e.name),
248
+ line: { color: e.color },
249
+ fillcolor: e.color ? e.color + "33" : void 0
250
+ })),
251
+ layout: {
252
+ ...i,
253
+ polar: {
254
+ radialaxis: { visible: e.show_radius_axis !== !1 },
255
+ gridshape: e.grid_type === "polygon" ? "linear" : "circular"
256
+ },
257
+ margin: {
258
+ t: e.title ? 40 : 20,
259
+ r: 30,
260
+ b: 30,
261
+ l: 30
262
+ }
263
+ }
264
+ };
265
+ case "RadialBarChart": return {
266
+ traces: t.map((e) => ({
267
+ type: "barpolar",
268
+ name: e.name,
269
+ r: (e.data ?? []).map((e) => e.value),
270
+ theta: (e.data ?? []).map((e) => e.name ?? e.subject),
271
+ marker: { color: e.color }
272
+ })),
273
+ layout: {
274
+ ...i,
275
+ margin: {
276
+ t: e.title ? 40 : 20,
277
+ r: 30,
278
+ b: 30,
279
+ l: 30
280
+ }
281
+ }
282
+ };
283
+ default: return {
284
+ traces: [],
285
+ layout: i
286
+ };
287
+ }
288
+ }
289
+ function N({ el: e }) {
290
+ let n = i(null);
291
+ t(() => {
292
+ let t = n.current;
293
+ if (!t) return;
294
+ let r = !0, { traces: i, layout: a } = M(e);
295
+ return import("plotly.js-dist-min").then((e) => {
296
+ !r || !t || e.newPlot(t, i, a, {
297
+ responsive: !0,
298
+ displayModeBar: !1
299
+ });
300
+ }), () => {
301
+ r = !1, import("plotly.js-dist-min").then((e) => {
302
+ t && e.purge(t);
303
+ });
304
+ };
305
+ }, [e.name, e.type]);
306
+ let r = A(e.styling);
307
+ return /* @__PURE__ */ l("div", {
308
+ id: e.component_id ?? void 0,
309
+ className: (e.css_classes ?? []).join(" ") || void 0,
310
+ style: {
311
+ minHeight: "300px",
312
+ ...r
313
+ },
314
+ ref: n
315
+ });
316
+ }
317
+ function P(e, t, n) {
318
+ let r = A(e.styling), i = e.component_id ?? void 0, a = (e.css_classes ?? []).join(" ") || void 0;
319
+ switch (e.type) {
320
+ case "Text": {
321
+ let t = new Set([
322
+ "h1",
323
+ "h2",
324
+ "h3",
325
+ "h4",
326
+ "h5",
327
+ "h6",
328
+ "p",
329
+ "span",
330
+ "div",
331
+ "label",
332
+ "li",
333
+ "td",
334
+ "th"
335
+ ]);
336
+ return /* @__PURE__ */ l(e.tag_name && t.has(e.tag_name) ? e.tag_name : "p", {
337
+ id: i,
338
+ className: a,
339
+ style: r,
340
+ children: e.content
341
+ }, e.name);
342
+ }
343
+ case "Link": return /* @__PURE__ */ l("a", {
344
+ id: i,
345
+ className: a,
346
+ style: r,
347
+ href: e.url ?? "#",
348
+ target: e.target ?? "_self",
349
+ rel: e.rel ?? (e.target === "_blank" ? "noopener noreferrer" : void 0),
350
+ onClick: (r) => {
351
+ e.url && n?.(e.url) ? r.preventDefault() : t?.(JSON.stringify({
352
+ elementId: i ?? e.name,
353
+ action: "onClick",
354
+ value: e.url
355
+ }));
356
+ },
357
+ children: e.label
358
+ }, e.name);
359
+ case "Button": return /* @__PURE__ */ l("button", {
360
+ id: i,
361
+ className: a,
362
+ style: r,
363
+ type: "button",
364
+ onClick: () => {
365
+ e.actionType === "navigate" && e.url && n?.(e.url) || t?.(JSON.stringify({
366
+ elementId: i ?? e.name,
367
+ action: "onClick"
368
+ }));
369
+ },
370
+ children: e.label
371
+ }, e.name);
372
+ case "Image": return /* @__PURE__ */ l("img", {
373
+ id: i,
374
+ className: a,
375
+ style: r,
376
+ src: e.source ?? "",
377
+ alt: e.name,
378
+ onError: (e) => {
379
+ e.target.style.display = "none";
380
+ }
381
+ }, e.name);
382
+ case "InputField": return /* @__PURE__ */ l("input", {
383
+ id: i,
384
+ name: e.name,
385
+ className: a,
386
+ style: {
387
+ padding: "6px 10px",
388
+ border: "1px solid #cbd5e1",
389
+ borderRadius: "4px",
390
+ ...r
391
+ },
392
+ type: (e.field_type ?? "text").toLowerCase(),
393
+ placeholder: e.description || e.name,
394
+ onBlur: (n) => t?.(JSON.stringify({
395
+ elementId: i ?? e.name,
396
+ action: "onChange",
397
+ value: n.target.value
398
+ }))
399
+ }, e.name);
400
+ case "Form": return /* @__PURE__ */ l("form", {
401
+ id: i,
402
+ className: a,
403
+ style: {
404
+ display: "flex",
405
+ flexDirection: "column",
406
+ gap: "8px",
407
+ ...r
408
+ },
409
+ onSubmit: (n) => {
410
+ n.preventDefault();
411
+ let r = Object.fromEntries(new FormData(n.currentTarget));
412
+ t?.(JSON.stringify({
413
+ elementId: i ?? e.name,
414
+ action: "onSubmit",
415
+ value: r
416
+ }));
417
+ },
418
+ children: (e.inputFields ?? []).map((e) => P(e, t, n))
419
+ }, e.name);
420
+ case "Menu": return /* @__PURE__ */ l(e.tag_name && e.tag_name === "nav" ? "nav" : "div", {
421
+ id: i,
422
+ className: a,
423
+ style: r,
424
+ children: /* @__PURE__ */ l("ul", {
425
+ style: {
426
+ listStyle: "none",
427
+ padding: 0,
428
+ margin: 0
429
+ },
430
+ children: (e.menuItems ?? []).map((r, i) => /* @__PURE__ */ l("li", { children: /* @__PURE__ */ l("a", {
431
+ href: r.url ?? "#",
432
+ target: r.target,
433
+ rel: r.target === "_blank" ? "noopener noreferrer" : void 0,
434
+ style: { textDecoration: "none" },
435
+ onClick: (i) => {
436
+ r.url && n?.(r.url) ? i.preventDefault() : t?.(JSON.stringify({
437
+ elementId: e.component_id ?? e.name,
438
+ action: "onClick",
439
+ value: r.url
440
+ }));
441
+ },
442
+ children: r.label
443
+ }) }, i))
444
+ })
445
+ }, e.name);
446
+ case "DataList": return /* @__PURE__ */ l("ul", {
447
+ id: i,
448
+ className: a,
449
+ style: {
450
+ padding: 0,
451
+ ...r
452
+ },
453
+ children: (e.list_sources ?? []).map((e, t) => /* @__PURE__ */ u("li", {
454
+ style: {
455
+ padding: "4px 0",
456
+ color: "#94a3b8",
457
+ fontStyle: "italic"
458
+ },
459
+ children: [
460
+ "(data item ",
461
+ t + 1,
462
+ ")"
463
+ ]
464
+ }, t))
465
+ }, e.name);
466
+ case "EmbeddedContent": {
467
+ let t = e.source ?? e.extra_props?.src ?? "";
468
+ return t ? /* @__PURE__ */ l("iframe", {
469
+ id: i,
470
+ className: a,
471
+ style: {
472
+ width: "100%",
473
+ height: "300px",
474
+ border: "none",
475
+ ...r
476
+ },
477
+ src: t,
478
+ title: e.name,
479
+ loading: "lazy",
480
+ sandbox: "allow-scripts allow-same-origin"
481
+ }, e.name) : /* @__PURE__ */ l("div", {
482
+ id: i,
483
+ className: a,
484
+ style: r,
485
+ children: "[Embedded Content]"
486
+ }, e.name);
487
+ }
488
+ case "ViewContainer": {
489
+ let o = { ...r };
490
+ if (e.layout) {
491
+ let t = e.layout.layout_type;
492
+ t === "flex" ? o.display = "flex" : t === "grid" && (o.display = "grid");
493
+ for (let [t, n] of Object.entries(e.layout)) !n || t === "layout_type" || (o[w(t)] = n);
494
+ }
495
+ let s = new Set([
496
+ "div",
497
+ "section",
498
+ "article",
499
+ "header",
500
+ "footer",
501
+ "main",
502
+ "nav",
503
+ "aside",
504
+ "ul",
505
+ "ol"
506
+ ]);
507
+ return /* @__PURE__ */ l(e.tag_name && s.has(e.tag_name) ? e.tag_name : "div", {
508
+ id: i,
509
+ className: a,
510
+ style: o,
511
+ children: (e.view_elements ?? []).map((e) => P(e, t, n))
512
+ }, e.name);
513
+ }
514
+ case "LineChart":
515
+ case "BarChart":
516
+ case "PieChart":
517
+ case "RadarChart":
518
+ case "RadialBarChart": return /* @__PURE__ */ l(N, { el: e }, e.name);
519
+ case "Table": return /* @__PURE__ */ u("div", {
520
+ id: i,
521
+ className: a,
522
+ style: {
523
+ overflowX: "auto",
524
+ ...r
525
+ },
526
+ children: [e.title && /* @__PURE__ */ l("div", {
527
+ style: {
528
+ fontWeight: 600,
529
+ marginBottom: 8,
530
+ fontSize: "0.95em"
531
+ },
532
+ children: e.title
533
+ }), /* @__PURE__ */ u("table", {
534
+ style: {
535
+ borderCollapse: "collapse",
536
+ width: "100%",
537
+ fontSize: "0.88em"
538
+ },
539
+ children: [e.show_header !== !1 && (e.columns ?? []).length > 0 && /* @__PURE__ */ l("thead", { children: /* @__PURE__ */ l("tr", { children: (e.columns ?? []).map((e, t) => /* @__PURE__ */ l("th", {
540
+ style: {
541
+ padding: "6px 10px",
542
+ borderBottom: "2px solid #e2e8f0",
543
+ textAlign: "left",
544
+ fontWeight: 600
545
+ },
546
+ children: e.label
547
+ }, t)) }) }), /* @__PURE__ */ l("tbody", { children: /* @__PURE__ */ l("tr", { children: /* @__PURE__ */ l("td", {
548
+ colSpan: (e.columns ?? []).length || 1,
549
+ style: {
550
+ padding: "8px 10px",
551
+ color: "#94a3b8",
552
+ fontStyle: "italic"
553
+ },
554
+ children: "(data rows)"
555
+ }) }) })]
556
+ })]
557
+ }, e.name);
558
+ case "MetricCard": return /* @__PURE__ */ u("div", {
559
+ id: i,
560
+ className: ["gui-metric-card", a].filter(Boolean).join(" "),
561
+ style: r,
562
+ children: [
563
+ /* @__PURE__ */ l("div", {
564
+ className: "gui-metric-card__title",
565
+ children: e.metric_title ?? e.name
566
+ }),
567
+ /* @__PURE__ */ l("div", {
568
+ className: "gui-metric-card__value",
569
+ style: { color: e.value_color ?? "#2c3e50" },
570
+ children: "—"
571
+ }),
572
+ /* @__PURE__ */ l("div", {
573
+ className: "gui-metric-card__format",
574
+ children: e.format
575
+ })
576
+ ]
577
+ }, e.name);
578
+ case "AgentComponent": return /* @__PURE__ */ u("div", {
579
+ id: i,
580
+ className: ["gui-agent-component", a].filter(Boolean).join(" "),
581
+ style: r,
582
+ children: [/* @__PURE__ */ l("span", { children: "🤖" }), /* @__PURE__ */ u("span", { children: [e.agent_title ?? e.agent_name ?? "Agent", " Widget"] })]
583
+ }, e.name);
584
+ default: return null;
585
+ }
586
+ }
587
+ function F({ content: i, onInteract: o }) {
588
+ let s = "gui-s" + n().replace(/[^a-zA-Z0-9]/g, ""), c = r(() => {
589
+ try {
590
+ let e = typeof i == "string" ? i : JSON.stringify(i);
591
+ return JSON.parse(e);
592
+ } catch {
593
+ return null;
594
+ }
595
+ }, [i]), d = r(() => (c?.modules ?? []).flatMap((e) => e.screens), [c]), [f, p] = a(0), m = e((e) => {
596
+ let t = d.findIndex((t) => t.name === e);
597
+ if (t >= 0) return p(t), !0;
598
+ let n = d.findIndex((t) => t.route_path === e);
599
+ if (n >= 0) return p(n), !0;
600
+ if (e === "/" || e === "") {
601
+ let e = d.findIndex((e) => e.is_main_page);
602
+ return p(e >= 0 ? e : 0), !0;
603
+ }
604
+ return !1;
605
+ }, [d]);
606
+ t(() => {
607
+ let e = d.findIndex((e) => e.is_main_page);
608
+ p(e >= 0 ? e : 0);
609
+ }, [d]);
610
+ let h = r(() => c?.style_entries ? j(c.style_entries, s) : "", [c, s]);
611
+ if (t(() => {
612
+ if (!h) return;
613
+ let e = document.createElement("style");
614
+ return e.setAttribute("data-gui-scope", s), e.textContent = h, document.head.appendChild(e), () => {
615
+ document.head.removeChild(e);
616
+ };
617
+ }, [h, s]), !c) return /* @__PURE__ */ l("p", {
618
+ className: "msg-text--muted",
619
+ children: "[Invalid UI definition]"
620
+ });
621
+ let g = d[f];
622
+ if (!g) return /* @__PURE__ */ l("p", {
623
+ className: "msg-text--muted",
624
+ children: "[No screens defined]"
625
+ });
626
+ let _ = c.modules.length > 1, v = d.length > 1;
627
+ return /* @__PURE__ */ u("div", {
628
+ className: "gui-renderer",
629
+ children: [
630
+ /* @__PURE__ */ u("div", {
631
+ className: "gui-renderer__header",
632
+ children: [/* @__PURE__ */ l("span", {
633
+ className: "gui-renderer__title",
634
+ children: c.name
635
+ }), c.description && /* @__PURE__ */ l("span", {
636
+ className: "gui-renderer__description",
637
+ children: c.description
638
+ })]
639
+ }),
640
+ (_ || v) && /* @__PURE__ */ l("div", {
641
+ className: "gui-renderer__tabs",
642
+ role: "tablist",
643
+ children: d.map((e, t) => /* @__PURE__ */ u("button", {
644
+ role: "tab",
645
+ "aria-selected": t === f,
646
+ className: `gui-renderer__tab${t === f ? " gui-renderer__tab--active" : ""}`,
647
+ onClick: () => p(t),
648
+ children: [e.name, e.is_main_page && /* @__PURE__ */ l("span", {
649
+ className: "gui-renderer__tab-badge",
650
+ children: "home"
651
+ })]
652
+ }, t))
653
+ }),
654
+ /* @__PURE__ */ l("div", {
655
+ className: `gui-renderer__screen ${s}`,
656
+ children: (g.view_elements ?? []).map((e) => P(e, o, m))
657
+ })
658
+ ]
659
+ });
660
+ }
661
+ //#endregion
662
+ //#region src/components/ReasoningTrace.tsx
663
+ var I = new Set([
664
+ f.TASK_ADDED,
665
+ f.TASK_COMPLETED,
666
+ f.TASK_SKIPPED
667
+ ]), L = new Set([
668
+ "add_tasks",
669
+ "complete_task",
670
+ "skip_task"
671
+ ]);
672
+ function R(e) {
673
+ if (e.kind !== f.LLM_TOOL_CALLS) return !1;
674
+ let t = e.details?.tool_calls ?? [];
675
+ return t.length === 0 ? !1 : t.every((e) => e.name !== void 0 && L.has(e.name));
676
+ }
677
+ function z({ trace: e }) {
678
+ let [n, r] = a(e.inProgress);
679
+ t(() => {
680
+ e.inProgress || r(!1);
681
+ }, [e.inProgress]);
682
+ let i = e.inProgress || n, o = e.steps.filter((e) => !(e.kind === f.REASONING_STARTED || e.kind === f.REASONING_FINISHED || I.has(e.kind) || R(e))), s = new Set(o.map((e) => e.step)).size;
683
+ return /* @__PURE__ */ u("div", {
684
+ className: `reasoning-trace${e.inProgress ? " reasoning-trace--live" : ""}`,
685
+ children: [/* @__PURE__ */ u("button", {
686
+ type: "button",
687
+ className: `reasoning-trace__summary${i ? " reasoning-trace__summary--open" : ""}`,
688
+ onClick: () => !e.inProgress && r((e) => !e),
689
+ disabled: e.inProgress,
690
+ "aria-expanded": i,
691
+ children: [
692
+ /* @__PURE__ */ l("span", {
693
+ className: "reasoning-trace__icon",
694
+ "aria-hidden": !0,
695
+ children: e.inProgress ? "🧠" : "✨"
696
+ }),
697
+ /* @__PURE__ */ l("span", {
698
+ className: "reasoning-trace__label",
699
+ children: e.inProgress ? `Reasoning… (${s} step${s === 1 ? "" : "s"})` : `Reasoned across ${s} step${s === 1 ? "" : "s"}`
700
+ }),
701
+ !e.inProgress && /* @__PURE__ */ l("span", {
702
+ className: "reasoning-trace__chevron",
703
+ "aria-hidden": !0,
704
+ children: "▶"
705
+ })
706
+ ]
707
+ }), /* @__PURE__ */ l("div", {
708
+ className: `reasoning-trace__body-wrapper${i ? " reasoning-trace__body-wrapper--open" : ""}`,
709
+ children: /* @__PURE__ */ u("div", {
710
+ className: "reasoning-trace__body-inner",
711
+ children: [/* @__PURE__ */ l(ne, { steps: o }), e.tasks.length > 0 && /* @__PURE__ */ l(ee, { tasks: e.tasks })]
712
+ })
713
+ })]
714
+ });
715
+ }
716
+ var B = {
717
+ [p.PENDING]: "pending",
718
+ [p.IN_PROGRESS]: "in progress",
719
+ [p.COMPLETED]: "completed",
720
+ [p.SKIPPED]: "skipped"
721
+ };
722
+ function ee({ tasks: e }) {
723
+ let t = e.reduce((e, t) => (e[t.status] = (e[t.status] ?? 0) + 1, e), {}), n = t[p.COMPLETED] ?? 0, r = t[p.SKIPPED] ?? 0, i = (t[p.PENDING] ?? 0) + (t[p.IN_PROGRESS] ?? 0);
724
+ return /* @__PURE__ */ u("div", {
725
+ className: "task-panel",
726
+ children: [/* @__PURE__ */ u("div", {
727
+ className: "task-panel__header",
728
+ children: [/* @__PURE__ */ l("span", {
729
+ className: "task-panel__title",
730
+ children: "Tasks"
731
+ }), /* @__PURE__ */ u("span", {
732
+ className: "task-panel__counts",
733
+ children: [
734
+ n > 0 && /* @__PURE__ */ u("span", {
735
+ className: "task-panel__count task-panel__count--completed",
736
+ children: [n, " ✓"]
737
+ }),
738
+ r > 0 && /* @__PURE__ */ u("span", {
739
+ className: "task-panel__count task-panel__count--skipped",
740
+ children: [r, " ⊘"]
741
+ }),
742
+ i > 0 && /* @__PURE__ */ u("span", {
743
+ className: "task-panel__count task-panel__count--pending",
744
+ children: [i, " pending"]
745
+ })
746
+ ]
747
+ })]
748
+ }), /* @__PURE__ */ l("ul", {
749
+ className: "task-panel__list",
750
+ children: e.map((e) => /* @__PURE__ */ u("li", {
751
+ className: `task-panel__item task-panel__item--${e.status}`,
752
+ children: [/* @__PURE__ */ l("span", {
753
+ className: `task-panel__box task-panel__box--${e.status}`,
754
+ title: B[e.status] ?? e.status,
755
+ "aria-label": B[e.status] ?? e.status
756
+ }), /* @__PURE__ */ u("span", {
757
+ className: "task-panel__text",
758
+ children: [
759
+ /* @__PURE__ */ u("span", {
760
+ className: "task-panel__id",
761
+ children: ["#", e.id]
762
+ }),
763
+ /* @__PURE__ */ l("span", {
764
+ className: "task-panel__description",
765
+ children: e.description
766
+ }),
767
+ e.result && /* @__PURE__ */ u("span", {
768
+ className: "task-panel__result",
769
+ title: e.result,
770
+ children: ["→ ", e.result]
771
+ })
772
+ ]
773
+ })]
774
+ }, e.id))
775
+ })]
776
+ });
777
+ }
778
+ function te(e) {
779
+ let t = [], n = 0;
780
+ for (; n < e.length;) if (e[n].kind === f.TOOL_RESULT) {
781
+ let r = n;
782
+ for (; r < e.length && e[r].kind === f.TOOL_RESULT;) r++;
783
+ let i = e.slice(n, r);
784
+ if (i.length > 2) t.push({
785
+ type: "tool_result_group",
786
+ steps: i
787
+ });
788
+ else for (let e of i) t.push({
789
+ type: "single",
790
+ step: e
791
+ });
792
+ n = r;
793
+ } else t.push({
794
+ type: "single",
795
+ step: e[n]
796
+ }), n++;
797
+ return t;
798
+ }
799
+ function ne({ steps: e }) {
800
+ let t = [];
801
+ for (let n of e) {
802
+ let e = t[t.length - 1];
803
+ e && e.step === n.step ? e.events.push(n) : t.push({
804
+ step: n.step,
805
+ events: [n]
806
+ });
807
+ }
808
+ return t.length === 0 ? null : /* @__PURE__ */ l("div", {
809
+ className: "reasoning-trace__steps",
810
+ children: t.map((e, t) => /* @__PURE__ */ u("div", {
811
+ className: "reasoning-trace__step-group",
812
+ children: [/* @__PURE__ */ u("div", {
813
+ className: "reasoning-trace__step-header",
814
+ title: `actual reasoning iteration #${e.step}`,
815
+ children: ["STEP ", t]
816
+ }), /* @__PURE__ */ l("ol", {
817
+ className: "reasoning-trace__step-list",
818
+ children: te(e.events).map((e, t) => e.type === "tool_result_group" ? /* @__PURE__ */ l(H, { steps: e.steps }, t) : /* @__PURE__ */ l(U, { step: e.step }, t))
819
+ })]
820
+ }, t))
821
+ });
822
+ }
823
+ var V = {
824
+ [f.LLM_TEXT]: "💬",
825
+ [f.LLM_TOOL_CALLS]: "🛠️",
826
+ [f.TOOL_RESULT]: "📥",
827
+ [f.TASK_ADDED]: "📝",
828
+ [f.TASK_COMPLETED]: "✅",
829
+ [f.TASK_SKIPPED]: "⏭️",
830
+ [f.PUSHBACK]: "↩️",
831
+ [f.MAX_STEPS]: "⏱️"
832
+ };
833
+ function H({ steps: e }) {
834
+ let [t, n] = a(!1);
835
+ return /* @__PURE__ */ u("li", {
836
+ className: "reasoning-trace__step",
837
+ children: [/* @__PURE__ */ u("button", {
838
+ type: "button",
839
+ className: "reasoning-trace__step-line",
840
+ onClick: () => n((e) => !e),
841
+ title: "Click to expand tool results",
842
+ children: [
843
+ /* @__PURE__ */ l("span", {
844
+ className: "reasoning-trace__step-icon",
845
+ "aria-hidden": !0,
846
+ children: "📥"
847
+ }),
848
+ /* @__PURE__ */ u("span", {
849
+ className: "reasoning-trace__step-summary",
850
+ children: [
851
+ "Completed ",
852
+ e.length,
853
+ " tool calls"
854
+ ]
855
+ }),
856
+ /* @__PURE__ */ l("span", {
857
+ className: "reasoning-trace__step-chevron",
858
+ "aria-hidden": !0,
859
+ style: {
860
+ fontSize: "0.65rem",
861
+ transition: "transform 0.2s ease",
862
+ transform: t ? "rotate(90deg)" : "none"
863
+ },
864
+ children: "▶"
865
+ })
866
+ ]
867
+ }), t && /* @__PURE__ */ l("ol", {
868
+ className: "reasoning-trace__step-list reasoning-trace__step-list--nested",
869
+ children: e.map((e, t) => /* @__PURE__ */ l(U, { step: e }, t))
870
+ })]
871
+ });
872
+ }
873
+ function U({ step: e }) {
874
+ let [t, n] = a(!1), r = V[e.kind] ?? "🔹", i = e.details && Object.keys(e.details).length > 0;
875
+ return /* @__PURE__ */ u("li", {
876
+ className: "reasoning-trace__step",
877
+ children: [/* @__PURE__ */ u("button", {
878
+ type: "button",
879
+ className: "reasoning-trace__step-line",
880
+ onClick: () => i && n((e) => !e),
881
+ disabled: !i,
882
+ title: i ? "Click to toggle details" : void 0,
883
+ children: [/* @__PURE__ */ l("span", {
884
+ className: "reasoning-trace__step-icon",
885
+ "aria-hidden": !0,
886
+ children: r
887
+ }), /* @__PURE__ */ l("span", {
888
+ className: "reasoning-trace__step-summary",
889
+ children: e.summary
890
+ })]
891
+ }), i && t && /* @__PURE__ */ l("pre", {
892
+ className: "reasoning-trace__step-details",
893
+ children: JSON.stringify(e.details, null, 2)
894
+ })]
895
+ });
896
+ }
897
+ //#endregion
898
+ //#region src/components/MessageBubble.tsx
899
+ function W({ message: e, onOptionSelect: t, onUIInteract: n }) {
900
+ let { action: r, message: i, isUser: a, timestamp: o } = e, s = o ?? null;
901
+ if (!a && r === "reasoning_trace") {
902
+ let e = i;
903
+ return v(e) ? null : /* @__PURE__ */ u("div", {
904
+ className: "message message--agent message--reasoning",
905
+ children: [s && /* @__PURE__ */ l("span", {
906
+ className: "message__timestamp",
907
+ children: s
908
+ }), /* @__PURE__ */ l("div", {
909
+ className: "message__body",
910
+ children: /* @__PURE__ */ l(z, { trace: e })
911
+ })]
912
+ });
913
+ }
914
+ if (a) {
915
+ if (r === d.USER_VOICE) {
916
+ let e = typeof i == "string" ? i : i.data;
917
+ return /* @__PURE__ */ u("div", {
918
+ className: "message message--user",
919
+ children: [s && /* @__PURE__ */ l("span", {
920
+ className: "message__timestamp message__timestamp--user",
921
+ children: s
922
+ }), /* @__PURE__ */ l("div", {
923
+ className: "message__body",
924
+ children: /* @__PURE__ */ l("div", {
925
+ className: "message__bubble message__bubble--user message__bubble--media",
926
+ children: /* @__PURE__ */ l(Q, { data: e })
927
+ })
928
+ })]
929
+ });
930
+ }
931
+ return r === d.USER_FILE ? /* @__PURE__ */ u("div", {
932
+ className: "message message--user",
933
+ children: [s && /* @__PURE__ */ l("span", {
934
+ className: "message__timestamp message__timestamp--user",
935
+ children: s
936
+ }), /* @__PURE__ */ l("div", {
937
+ className: "message__body",
938
+ children: /* @__PURE__ */ l("div", {
939
+ className: "message__bubble message__bubble--user message__bubble--media",
940
+ children: /* @__PURE__ */ l(K, { content: i })
941
+ })
942
+ })]
943
+ }) : /* @__PURE__ */ u("div", {
944
+ className: "message message--user",
945
+ children: [s && /* @__PURE__ */ l("span", {
946
+ className: "message__timestamp message__timestamp--user",
947
+ children: s
948
+ }), /* @__PURE__ */ l("div", {
949
+ className: "message__body",
950
+ children: /* @__PURE__ */ l("div", {
951
+ className: "message__bubble message__bubble--user",
952
+ children: typeof i == "string" ? i : JSON.stringify(i)
953
+ })
954
+ })]
955
+ });
956
+ }
957
+ return /* @__PURE__ */ u("div", {
958
+ className: "message message--agent",
959
+ children: [s && /* @__PURE__ */ l("span", {
960
+ className: "message__timestamp",
961
+ children: s
962
+ }), /* @__PURE__ */ l("div", {
963
+ className: "message__body",
964
+ children: /* @__PURE__ */ l("div", {
965
+ className: "message__bubble message__bubble--agent",
966
+ children: G(r, i, t, n)
967
+ })
968
+ })]
969
+ });
970
+ }
971
+ function G(e, t, n, r) {
972
+ switch (e) {
973
+ case d.AGENT_REPLY_STR: {
974
+ let e = String(t), n = C(e);
975
+ return n === "markdown" ? /* @__PURE__ */ l("div", {
976
+ className: "msg-markdown",
977
+ children: /* @__PURE__ */ l(o, {
978
+ remarkPlugins: [s],
979
+ children: e
980
+ })
981
+ }) : n === "code" ? /* @__PURE__ */ l("pre", {
982
+ className: "msg-code",
983
+ children: /* @__PURE__ */ l("code", { children: e })
984
+ }) : /* @__PURE__ */ l("p", {
985
+ className: "msg-text",
986
+ children: e
987
+ });
988
+ }
989
+ case d.AGENT_REPLY_MARKDOWN: return /* @__PURE__ */ l("div", {
990
+ className: "msg-markdown",
991
+ children: /* @__PURE__ */ l(o, {
992
+ remarkPlugins: [s],
993
+ children: String(t)
994
+ })
995
+ });
996
+ case d.AGENT_REPLY_HTML: return /* @__PURE__ */ l("div", {
997
+ className: "msg-html",
998
+ dangerouslySetInnerHTML: { __html: c.sanitize(String(t), {
999
+ ALLOWED_TAGS: /* @__PURE__ */ "p.br.b.i.em.strong.a.ul.ol.li.code.pre.h1.h2.h3.h4.h5.h6.blockquote.table.thead.tbody.tr.th.td.div.span.hr".split("."),
1000
+ ALLOWED_ATTR: [
1001
+ "href",
1002
+ "target",
1003
+ "rel",
1004
+ "class"
1005
+ ],
1006
+ FORBID_TAGS: [
1007
+ "head",
1008
+ "style",
1009
+ "script",
1010
+ "title",
1011
+ "meta",
1012
+ "link",
1013
+ "noscript"
1014
+ ],
1015
+ FORCE_BODY: !0
1016
+ }) }
1017
+ });
1018
+ case d.AGENT_REPLY_FILE: return /* @__PURE__ */ l(K, { content: t });
1019
+ case d.AGENT_REPLY_IMAGE: return /* @__PURE__ */ l(q, { content: t });
1020
+ case d.AGENT_REPLY_DF: return /* @__PURE__ */ l(J, { content: t });
1021
+ case d.AGENT_REPLY_PLOTLY: return /* @__PURE__ */ l(Y, { content: t });
1022
+ case d.AGENT_REPLY_OPTIONS: return /* @__PURE__ */ l(X, {
1023
+ content: t,
1024
+ onSelect: n
1025
+ });
1026
+ case d.AGENT_REPLY_LOCATION: return /* @__PURE__ */ l(Z, { content: t });
1027
+ case d.AGENT_REPLY_RAG: return /* @__PURE__ */ l(re, { content: t });
1028
+ case d.AGENT_REPLY_AUDIO: return /* @__PURE__ */ l(ie, { content: t });
1029
+ case d.AGENT_REPLY_UI: return /* @__PURE__ */ l(F, {
1030
+ content: t,
1031
+ onInteract: r
1032
+ });
1033
+ default: return /* @__PURE__ */ u("p", {
1034
+ className: "msg-text msg-text--muted",
1035
+ children: [
1036
+ "[Unsupported message type: ",
1037
+ e,
1038
+ "]"
1039
+ ]
1040
+ });
1041
+ }
1042
+ }
1043
+ function K({ content: e }) {
1044
+ let t = e, n = t.data ?? t.base64 ?? "";
1045
+ function r() {
1046
+ try {
1047
+ let e = atob(n), r = new Uint8Array(e.length);
1048
+ for (let t = 0; t < e.length; t++) r[t] = e.charCodeAt(t);
1049
+ let i = new Blob([r], { type: t.type ?? "application/octet-stream" }), a = URL.createObjectURL(i), o = document.createElement("a");
1050
+ o.href = a, o.download = t.name ?? "download", o.click(), URL.revokeObjectURL(a);
1051
+ } catch {
1052
+ console.error("Failed to decode file data");
1053
+ }
1054
+ }
1055
+ return /* @__PURE__ */ u("button", {
1056
+ className: "msg-file-btn",
1057
+ onClick: r,
1058
+ children: ["📄 ", t.name ?? "Download file"]
1059
+ });
1060
+ }
1061
+ function q({ content: e }) {
1062
+ let t, n;
1063
+ if (typeof e == "string") t = e, n = "image/png";
1064
+ else {
1065
+ let r = e;
1066
+ t = r.data ?? r.base64 ?? "", n = r.type ?? (r.format ? `image/${r.format.toLowerCase()}` : "image/png");
1067
+ }
1068
+ return t ? /* @__PURE__ */ l("div", {
1069
+ className: "msg-image",
1070
+ children: /* @__PURE__ */ l("img", {
1071
+ src: `data:${n};base64,${t}`,
1072
+ alt: typeof e == "object" && e ? e.name ?? "Image" : "Image",
1073
+ onError: (e) => {
1074
+ e.target.style.display = "none";
1075
+ }
1076
+ })
1077
+ }) : /* @__PURE__ */ l("span", {
1078
+ className: "msg-text--muted",
1079
+ children: "Image unavailable"
1080
+ });
1081
+ }
1082
+ function J({ content: e }) {
1083
+ let [t, n] = a(null), [r, i] = a(!0), o = [], s = [];
1084
+ if (Array.isArray(e) && e.length > 0) o = Object.keys(e[0]), s = e.map((e) => o.map((t) => e[t]));
1085
+ else if (typeof e == "object" && e) {
1086
+ let t = e;
1087
+ if (Array.isArray(t.data) && Array.isArray(t.columns)) o = t.columns, s = t.data;
1088
+ else {
1089
+ let e = Object.keys(t), n = t[e[0]];
1090
+ if (e.length > 0 && typeof n == "object" && n && !Array.isArray(n)) {
1091
+ o = e;
1092
+ let n = t;
1093
+ s = Object.keys(n[o[0]]).map((e) => o.map((t) => n[t][e]));
1094
+ }
1095
+ }
1096
+ }
1097
+ if (o.length === 0) return /* @__PURE__ */ l("pre", {
1098
+ className: "msg-code",
1099
+ children: JSON.stringify(e, null, 2)
1100
+ });
1101
+ function c(e) {
1102
+ t === e ? i((e) => !e) : (n(e), i(!0));
1103
+ }
1104
+ let d = t === null ? s : [...s].sort((e, n) => {
1105
+ let i = e[t], a = n[t];
1106
+ return i == null && a == null ? 0 : i == null ? r ? 1 : -1 : a == null ? r ? -1 : 1 : typeof i == "number" && typeof a == "number" ? r ? i - a : a - i : r ? String(i).localeCompare(String(a)) : String(a).localeCompare(String(i));
1107
+ });
1108
+ return /* @__PURE__ */ l("div", {
1109
+ className: "msg-table-wrapper",
1110
+ children: /* @__PURE__ */ u("table", {
1111
+ className: "msg-table",
1112
+ children: [/* @__PURE__ */ l("thead", { children: /* @__PURE__ */ l("tr", { children: o.map((e, n) => /* @__PURE__ */ u("th", {
1113
+ className: `msg-table__th${t === n ? " msg-table__th--sorted" : ""}`,
1114
+ onClick: () => c(n),
1115
+ children: [e, /* @__PURE__ */ l("span", {
1116
+ className: "msg-table__sort-icon",
1117
+ children: t === n ? r ? "↑" : "↓" : "↕"
1118
+ })]
1119
+ }, e)) }) }), /* @__PURE__ */ l("tbody", { children: d.map((e, t) => /* @__PURE__ */ l("tr", { children: e.map((e, t) => /* @__PURE__ */ l("td", { children: String(e ?? "") }, t)) }, t)) })]
1120
+ })
1121
+ });
1122
+ }
1123
+ function Y({ content: e }) {
1124
+ let n = i(null);
1125
+ return t(() => {
1126
+ let t = n.current;
1127
+ if (!t) return;
1128
+ let r = !0, i = e;
1129
+ return import("plotly.js-dist-min").then((e) => {
1130
+ !r || !t || e.newPlot(t, i.data ?? [], {
1131
+ margin: {
1132
+ t: 24,
1133
+ r: 10,
1134
+ b: 40,
1135
+ l: 50
1136
+ },
1137
+ ...i.layout ?? {}
1138
+ }, {
1139
+ responsive: !0,
1140
+ displayModeBar: !0,
1141
+ scrollZoom: !0
1142
+ });
1143
+ }), () => {
1144
+ r = !1, import("plotly.js-dist-min").then((e) => {
1145
+ t && e.purge(t);
1146
+ });
1147
+ };
1148
+ }, [e]), /* @__PURE__ */ l("div", {
1149
+ ref: n,
1150
+ className: "msg-plotly"
1151
+ });
1152
+ }
1153
+ function X({ content: e, onSelect: t }) {
1154
+ let n;
1155
+ return n = Array.isArray(e) ? e.map(String) : typeof e == "object" && e ? Object.values(e).map(String) : [], /* @__PURE__ */ l("div", {
1156
+ className: "msg-options",
1157
+ children: n.map((e, n) => /* @__PURE__ */ l("button", {
1158
+ className: "msg-option-btn",
1159
+ onClick: () => t?.(e),
1160
+ children: e
1161
+ }, n))
1162
+ });
1163
+ }
1164
+ function Z({ content: e }) {
1165
+ let { latitude: t, longitude: n, zoom: r = 15 } = e, i = 360 / 2 ** (r + 1), a = `https://www.openstreetmap.org/export/embed.html?bbox=${`${n - i},${t - i},${n + i},${t + i}`}&layer=mapnik&marker=${t},${n}`, o = `https://www.openstreetmap.org/?mlat=${t}&mlon=${n}#map=${r}/${t}/${n}`;
1166
+ return /* @__PURE__ */ u("div", {
1167
+ className: "msg-location",
1168
+ children: [/* @__PURE__ */ l("iframe", {
1169
+ src: a,
1170
+ className: "msg-location__map",
1171
+ title: "Location map",
1172
+ loading: "lazy",
1173
+ referrerPolicy: "no-referrer"
1174
+ }), /* @__PURE__ */ u("a", {
1175
+ className: "msg-location__link",
1176
+ href: o,
1177
+ target: "_blank",
1178
+ rel: "noopener noreferrer",
1179
+ children: [
1180
+ "📍 ",
1181
+ t.toFixed(5),
1182
+ ", ",
1183
+ n.toFixed(5),
1184
+ " — Open in OpenStreetMap"
1185
+ ]
1186
+ })]
1187
+ });
1188
+ }
1189
+ function re({ content: e }) {
1190
+ let [t, n] = a(!1), r = e, i = r.docs ?? r.documents ?? [];
1191
+ return /* @__PURE__ */ u("div", {
1192
+ className: "msg-rag",
1193
+ children: [/* @__PURE__ */ l("p", {
1194
+ className: "msg-rag__answer",
1195
+ children: r.answer
1196
+ }), i.length > 0 && /* @__PURE__ */ u("div", {
1197
+ className: "msg-rag__details",
1198
+ children: [/* @__PURE__ */ u("button", {
1199
+ type: "button",
1200
+ className: `msg-rag__summary${t ? " msg-rag__summary--open" : ""}`,
1201
+ onClick: () => n((e) => !e),
1202
+ children: [/* @__PURE__ */ l("span", {
1203
+ className: "msg-rag__summary-arrow",
1204
+ children: "▶"
1205
+ }), "Details"]
1206
+ }), /* @__PURE__ */ l("div", {
1207
+ className: `msg-rag__body-wrapper${t ? " msg-rag__body-wrapper--open" : ""}`,
1208
+ children: /* @__PURE__ */ l("div", {
1209
+ className: "msg-rag__body-inner",
1210
+ children: /* @__PURE__ */ u("div", {
1211
+ className: "msg-rag__details-body",
1212
+ children: [
1213
+ /* @__PURE__ */ l("div", {
1214
+ className: "msg-rag__rag-answer-label",
1215
+ children: "RAG Answer"
1216
+ }),
1217
+ r.llm_name && /* @__PURE__ */ u("div", {
1218
+ className: "msg-rag__llm-row",
1219
+ children: [/* @__PURE__ */ l("span", {
1220
+ className: "msg-rag__llm-label",
1221
+ children: "Model"
1222
+ }), /* @__PURE__ */ l("code", {
1223
+ className: "msg-rag__llm-badge",
1224
+ children: r.llm_name
1225
+ })]
1226
+ }),
1227
+ /* @__PURE__ */ u("div", {
1228
+ className: "msg-rag__context-label",
1229
+ children: [
1230
+ "Context (",
1231
+ i.length,
1232
+ " Documents)"
1233
+ ]
1234
+ }),
1235
+ /* @__PURE__ */ l("div", {
1236
+ className: "msg-rag__docs",
1237
+ children: i.map((e, t) => {
1238
+ let n = e.metadata?.source, r = e.metadata?.page;
1239
+ return /* @__PURE__ */ u("div", {
1240
+ className: "msg-rag__doc-card",
1241
+ children: [
1242
+ /* @__PURE__ */ u("div", {
1243
+ className: "msg-rag__doc-header",
1244
+ children: [
1245
+ "Document ",
1246
+ t + 1,
1247
+ "/",
1248
+ i.length
1249
+ ]
1250
+ }),
1251
+ n && /* @__PURE__ */ u("div", {
1252
+ className: "msg-rag__doc-row",
1253
+ children: [/* @__PURE__ */ l("span", {
1254
+ className: "msg-rag__doc-key",
1255
+ children: "Source"
1256
+ }), /* @__PURE__ */ l("span", {
1257
+ className: "msg-rag__doc-value",
1258
+ children: n
1259
+ })]
1260
+ }),
1261
+ r != null && /* @__PURE__ */ u("div", {
1262
+ className: "msg-rag__doc-row",
1263
+ children: [/* @__PURE__ */ l("span", {
1264
+ className: "msg-rag__doc-key",
1265
+ children: "Page"
1266
+ }), /* @__PURE__ */ l("span", {
1267
+ className: "msg-rag__doc-value",
1268
+ children: String(r)
1269
+ })]
1270
+ }),
1271
+ /* @__PURE__ */ u("div", {
1272
+ className: "msg-rag__doc-row msg-rag__doc-row--content",
1273
+ children: [/* @__PURE__ */ l("span", {
1274
+ className: "msg-rag__doc-key",
1275
+ children: "Content"
1276
+ }), /* @__PURE__ */ l("span", {
1277
+ className: "msg-rag__doc-value msg-rag__doc-content",
1278
+ children: e.content
1279
+ })]
1280
+ })
1281
+ ]
1282
+ }, t);
1283
+ })
1284
+ })
1285
+ ]
1286
+ })
1287
+ })
1288
+ })]
1289
+ })]
1290
+ });
1291
+ }
1292
+ function Q({ data: e, mimeType: n = "audio/wav" }) {
1293
+ let [r, i] = a(null);
1294
+ return t(() => {
1295
+ let t = null;
1296
+ try {
1297
+ let r = atob(e), a = new Uint8Array(r.length);
1298
+ for (let e = 0; e < r.length; e++) a[e] = r.charCodeAt(e);
1299
+ let o = new Blob([a], { type: n });
1300
+ t = URL.createObjectURL(o), i(t);
1301
+ } catch {
1302
+ i(null);
1303
+ }
1304
+ return () => {
1305
+ t && URL.revokeObjectURL(t);
1306
+ };
1307
+ }, [e, n]), r ? /* @__PURE__ */ l("audio", {
1308
+ controls: !0,
1309
+ src: r,
1310
+ className: "msg-audio__player"
1311
+ }) : /* @__PURE__ */ l("span", {
1312
+ className: "msg-text--muted",
1313
+ children: "Audio unavailable"
1314
+ });
1315
+ }
1316
+ function ie({ content: e }) {
1317
+ let t = typeof e == "string" ? { data: e } : e;
1318
+ return /* @__PURE__ */ u("div", {
1319
+ className: "msg-audio",
1320
+ children: [/* @__PURE__ */ l(Q, {
1321
+ data: t.data,
1322
+ mimeType: t.type ?? "audio/wav"
1323
+ }), t.sample_rate != null && /* @__PURE__ */ u("span", {
1324
+ className: "msg-audio__meta",
1325
+ children: [
1326
+ t.sample_rate,
1327
+ " Hz",
1328
+ t.dtype ? ` · ${t.dtype}` : ""
1329
+ ]
1330
+ })]
1331
+ });
1332
+ }
1333
+ //#endregion
1334
+ //#region src/components/ChatArea.tsx
1335
+ function $() {
1336
+ let e = /* @__PURE__ */ new Date(), t = (e) => String(e).padStart(2, "0");
1337
+ return `${e.getFullYear()}-${t(e.getMonth() + 1)}-${t(e.getDate())} ${t(e.getHours())}:${t(e.getMinutes())}:${t(e.getSeconds())}`;
1338
+ }
1339
+ function ae({ messages: n, setMessages: r, status: o, send: s }) {
1340
+ let [c, f] = a(""), [p, m] = a([]), [h, g] = a(!1), [_, v] = a(!1), y = i(null), b = i(null), x = i(null), S = i(null), C = i(null), w = i([]);
1341
+ t(() => {
1342
+ y.current?.scrollIntoView({ behavior: "smooth" });
1343
+ }, [n]), t(() => {
1344
+ if (!h) return;
1345
+ function e(e) {
1346
+ S.current && !S.current.contains(e.target) && g(!1);
1347
+ }
1348
+ return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
1349
+ }, [h]);
1350
+ function T() {
1351
+ let e = b.current;
1352
+ e && (e.style.height = "auto", e.style.height = Math.min(e.scrollHeight, 160) + "px");
1353
+ }
1354
+ async function E() {
1355
+ try {
1356
+ let e = await navigator.mediaDevices.getUserMedia({ audio: !0 }), t = MediaRecorder.isTypeSupported("audio/webm") ? "audio/webm" : "audio/ogg", n = new MediaRecorder(e, { mimeType: t });
1357
+ w.current = [], n.ondataavailable = (e) => {
1358
+ e.data.size > 0 && w.current.push(e.data);
1359
+ }, n.onstop = () => {
1360
+ let n = new Blob(w.current, { type: t });
1361
+ e.getTracks().forEach((e) => e.stop());
1362
+ let i = new FileReader();
1363
+ i.onload = () => {
1364
+ let e = i.result.split(",")[1] ?? "";
1365
+ r((t) => [...t, {
1366
+ id: crypto.randomUUID(),
1367
+ action: d.USER_VOICE,
1368
+ message: e,
1369
+ isUser: !0,
1370
+ timestamp: $()
1371
+ }]), s(d.USER_VOICE, e);
1372
+ }, i.readAsDataURL(n), v(!1);
1373
+ }, n.start(), C.current = n, v(!0);
1374
+ } catch {
1375
+ console.error("Microphone access denied or unavailable");
1376
+ }
1377
+ }
1378
+ function D() {
1379
+ _ ? (C.current?.stop(), C.current = null) : E();
1380
+ }
1381
+ let O = e(() => {
1382
+ let e = c.trim(), t = p.length > 0;
1383
+ if (!(!e && !t || o !== "connected")) {
1384
+ for (let e of p) r((t) => [...t, {
1385
+ id: crypto.randomUUID(),
1386
+ action: d.USER_FILE,
1387
+ message: {
1388
+ name: e.name,
1389
+ type: e.mimeType,
1390
+ base64: e.base64
1391
+ },
1392
+ isUser: !0,
1393
+ timestamp: $()
1394
+ }]), s(d.USER_FILE, JSON.stringify({
1395
+ name: e.name,
1396
+ type: e.mimeType,
1397
+ base64: e.base64
1398
+ }));
1399
+ m([]), e && (r((t) => [...t, {
1400
+ id: crypto.randomUUID(),
1401
+ action: d.USER_MESSAGE,
1402
+ message: e,
1403
+ isUser: !0,
1404
+ timestamp: $()
1405
+ }]), s(d.USER_MESSAGE, e), f(""), b.current && (b.current.style.height = "auto"));
1406
+ }
1407
+ }, [
1408
+ c,
1409
+ p,
1410
+ o,
1411
+ s,
1412
+ r
1413
+ ]);
1414
+ function k(e) {
1415
+ e.key === "Enter" && !e.shiftKey && (e.preventDefault(), O());
1416
+ }
1417
+ function A(e) {
1418
+ r((t) => [...t, {
1419
+ id: crypto.randomUUID(),
1420
+ action: d.USER_MESSAGE,
1421
+ message: e,
1422
+ isUser: !0,
1423
+ timestamp: $()
1424
+ }]), s(d.USER_MESSAGE, e);
1425
+ }
1426
+ function j(e) {
1427
+ s(d.USER_UPDATE_UI, e);
1428
+ }
1429
+ function M(e) {
1430
+ let t = Array.from(e.target.files ?? []);
1431
+ t.length !== 0 && (t.forEach((e) => {
1432
+ let t = new FileReader();
1433
+ t.onload = () => {
1434
+ let n = t.result.split(",")[1] ?? "";
1435
+ m((t) => [...t, {
1436
+ id: crypto.randomUUID(),
1437
+ name: e.name,
1438
+ base64: n,
1439
+ mimeType: e.type
1440
+ }]);
1441
+ }, t.readAsDataURL(e);
1442
+ }), e.target.value = "", g(!1));
1443
+ }
1444
+ function N(e) {
1445
+ m((t) => t.filter((t) => t.id !== e));
1446
+ }
1447
+ let P = o === "connected" ? "Type a message… (Enter to send, Shift+Enter for new line)" : o === "connecting" ? "Connecting…" : "Not connected", F = o === "connected" && (c.trim().length > 0 || p.length > 0);
1448
+ return /* @__PURE__ */ u("div", {
1449
+ className: "chat-area",
1450
+ children: [/* @__PURE__ */ u("div", {
1451
+ className: "chat-area__messages",
1452
+ children: [
1453
+ n.length === 0 && /* @__PURE__ */ l("div", {
1454
+ className: "chat-area__empty",
1455
+ children: o === "connecting" ? "Connecting to agent…" : o === "connected" ? "Send a message to start the conversation" : o === "error" ? "Connection error — check the agent URL" : "Disconnected"
1456
+ }),
1457
+ n.map((e) => /* @__PURE__ */ l(W, {
1458
+ message: e,
1459
+ onOptionSelect: A,
1460
+ onUIInteract: j
1461
+ }, e.id)),
1462
+ /* @__PURE__ */ l("div", { ref: y })
1463
+ ]
1464
+ }), /* @__PURE__ */ u("div", {
1465
+ className: "chat-area__input-row",
1466
+ children: [
1467
+ /* @__PURE__ */ l("input", {
1468
+ ref: x,
1469
+ type: "file",
1470
+ multiple: !0,
1471
+ style: { display: "none" },
1472
+ onChange: M
1473
+ }),
1474
+ /* @__PURE__ */ u("div", {
1475
+ className: "chat-area__composer",
1476
+ children: [p.length > 0 && /* @__PURE__ */ l("div", {
1477
+ className: "chat-area__attachments",
1478
+ children: p.map((e) => /* @__PURE__ */ u("div", {
1479
+ className: "attachment-chip",
1480
+ children: [
1481
+ /* @__PURE__ */ l("span", {
1482
+ className: "attachment-chip__icon",
1483
+ children: "📄"
1484
+ }),
1485
+ /* @__PURE__ */ l("span", {
1486
+ className: "attachment-chip__name",
1487
+ children: e.name
1488
+ }),
1489
+ /* @__PURE__ */ l("button", {
1490
+ className: "attachment-chip__remove",
1491
+ onClick: () => N(e.id),
1492
+ title: "Remove file",
1493
+ children: "✕"
1494
+ })
1495
+ ]
1496
+ }, e.id))
1497
+ }), /* @__PURE__ */ l("div", {
1498
+ className: "chat-area__input-line",
1499
+ children: /* @__PURE__ */ l("textarea", {
1500
+ ref: b,
1501
+ className: "chat-area__textarea",
1502
+ value: c,
1503
+ rows: 1,
1504
+ placeholder: P,
1505
+ disabled: o !== "connected",
1506
+ onChange: (e) => {
1507
+ f(e.target.value), T();
1508
+ },
1509
+ onKeyDown: k
1510
+ })
1511
+ })]
1512
+ }),
1513
+ /* @__PURE__ */ u("div", {
1514
+ className: "attach-menu-anchor",
1515
+ ref: S,
1516
+ children: [/* @__PURE__ */ l("button", {
1517
+ className: "btn chat-area__icon-btn",
1518
+ title: "Attach",
1519
+ disabled: o !== "connected",
1520
+ onClick: () => g((e) => !e),
1521
+ children: "+"
1522
+ }), h && /* @__PURE__ */ l("div", {
1523
+ className: "attach-menu",
1524
+ children: /* @__PURE__ */ l("button", {
1525
+ className: "attach-menu__item",
1526
+ onClick: () => x.current?.click(),
1527
+ children: "Add Files"
1528
+ })
1529
+ })]
1530
+ }),
1531
+ /* @__PURE__ */ l("button", {
1532
+ type: "button",
1533
+ className: `btn chat-area__icon-btn chat-area__mic-btn${_ ? " chat-area__mic-btn--recording" : ""}`,
1534
+ title: _ ? "Stop recording" : "Record voice message",
1535
+ disabled: o !== "connected",
1536
+ onClick: D,
1537
+ children: _ ? /* @__PURE__ */ l("svg", {
1538
+ width: "14",
1539
+ height: "14",
1540
+ viewBox: "0 0 14 14",
1541
+ fill: "currentColor",
1542
+ children: /* @__PURE__ */ l("rect", {
1543
+ x: "1",
1544
+ y: "1",
1545
+ width: "12",
1546
+ height: "12",
1547
+ rx: "2"
1548
+ })
1549
+ }) : /* @__PURE__ */ u("svg", {
1550
+ width: "16",
1551
+ height: "16",
1552
+ viewBox: "0 0 16 16",
1553
+ fill: "currentColor",
1554
+ children: [
1555
+ /* @__PURE__ */ l("rect", {
1556
+ x: "5",
1557
+ y: "1",
1558
+ width: "6",
1559
+ height: "9",
1560
+ rx: "3"
1561
+ }),
1562
+ /* @__PURE__ */ l("path", {
1563
+ d: "M3 7a5 5 0 0 0 10 0",
1564
+ stroke: "currentColor",
1565
+ strokeWidth: "1.5",
1566
+ fill: "none",
1567
+ strokeLinecap: "round"
1568
+ }),
1569
+ /* @__PURE__ */ l("line", {
1570
+ x1: "8",
1571
+ y1: "12",
1572
+ x2: "8",
1573
+ y2: "15",
1574
+ stroke: "currentColor",
1575
+ strokeWidth: "1.5",
1576
+ strokeLinecap: "round"
1577
+ }),
1578
+ /* @__PURE__ */ l("line", {
1579
+ x1: "5.5",
1580
+ y1: "15",
1581
+ x2: "10.5",
1582
+ y2: "15",
1583
+ stroke: "currentColor",
1584
+ strokeWidth: "1.5",
1585
+ strokeLinecap: "round"
1586
+ })
1587
+ ]
1588
+ })
1589
+ }),
1590
+ /* @__PURE__ */ l("button", {
1591
+ className: "btn btn--primary chat-area__send-btn",
1592
+ onClick: O,
1593
+ disabled: !F,
1594
+ title: "Send",
1595
+ children: "→"
1596
+ })
1597
+ ]
1598
+ })]
1599
+ });
1600
+ }
1601
+ //#endregion
1602
+ //#region src/hooks/useWebSocket.ts
1603
+ function oe(n, r) {
1604
+ let [o, s] = a("disconnected"), c = i(null), l = i(r);
1605
+ return l.current = r, t(() => {
1606
+ if (!n) {
1607
+ s("disconnected");
1608
+ return;
1609
+ }
1610
+ s("connecting");
1611
+ let e = new WebSocket(n);
1612
+ return c.current = e, e.onopen = () => {
1613
+ s("connected"), l.current.onOpen?.();
1614
+ }, e.onclose = () => s("disconnected"), e.onerror = () => s("error"), e.onmessage = (e) => {
1615
+ try {
1616
+ let t = JSON.parse(e.data);
1617
+ if (typeof t.message == "string") try {
1618
+ t.message = JSON.parse(t.message);
1619
+ } catch {
1620
+ try {
1621
+ t.message = JSON.parse(t.message.replace(/'/g, "\""));
1622
+ } catch {}
1623
+ }
1624
+ t.history ? l.current.onHistoryMessage?.(t) : l.current.onMessage(t);
1625
+ } catch {
1626
+ console.error("Failed to parse WS message:", e.data);
1627
+ }
1628
+ }, () => {
1629
+ e.close(), c.current = null;
1630
+ };
1631
+ }, [n]), {
1632
+ status: o,
1633
+ send: e((e, t) => {
1634
+ c.current?.readyState === WebSocket.OPEN && c.current.send(JSON.stringify({
1635
+ action: e,
1636
+ message: t
1637
+ }));
1638
+ }, []),
1639
+ disconnect: e(() => {
1640
+ c.current?.close(), c.current = null;
1641
+ }, [])
1642
+ };
1643
+ }
1644
+ //#endregion
1645
+ export { ae as ChatArea, F as GUIRenderer, W as MessageBubble, d as PayloadAction, m as REASONING_TRACE_ACTION, f as ReasoningStepKind, z as ReasoningTrace, p as TaskStatus, C as detectContentKind, v as isEmptyTrace, g as isReasoningEnd, h as isReasoningStart, S as looksLikeCode, b as looksLikeMarkdown, oe as useWebSocket, _ as visibleSteps };