@singlebase/elements 0.5.0 → 0.7.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.
Files changed (52) hide show
  1. package/dist/{authui-display-BCZBP7HR.js → authui-display-BM_F3-5e.js} +426 -436
  2. package/dist/authui-display-BM_F3-5e.js.map +1 -0
  3. package/dist/{authui-display-CLGFSqRi.cjs → authui-display-CMVHTNFz.cjs} +45 -65
  4. package/dist/authui-display-CMVHTNFz.cjs.map +1 -0
  5. package/dist/authui.cjs +1 -1
  6. package/dist/authui.js +2 -2
  7. package/dist/{chat-bXaRWel7.js → chat-BH_3e1jT.js} +2081 -1121
  8. package/dist/chat-BH_3e1jT.js.map +1 -0
  9. package/dist/chat-ezUmd9II.cjs +3281 -0
  10. package/dist/chat-ezUmd9II.cjs.map +1 -0
  11. package/dist/chat-messages.d.ts +19 -6
  12. package/dist/chat.cjs +1 -1
  13. package/dist/chat.d.ts +4 -3
  14. package/dist/chat.js +8 -6
  15. package/dist/elements/authui-base.d.ts +2 -0
  16. package/dist/elements/authui-buttons.d.ts +1 -1
  17. package/dist/elements/authui-display.d.ts +1 -1
  18. package/dist/elements/authui.d.ts +1 -1
  19. package/dist/elements/chat.d.ts +192 -11
  20. package/dist/elements/uploader.d.ts +8 -0
  21. package/dist/files-4T62wkwj.cjs +77 -0
  22. package/dist/files-4T62wkwj.cjs.map +1 -0
  23. package/dist/{files-BOwtpYyQ.js → files-DS-H-3yN.js} +93 -47
  24. package/dist/files-DS-H-3yN.js.map +1 -0
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.js +24 -22
  27. package/dist/messages.d.ts +0 -2
  28. package/dist/singlebase-elements.min.js +3838 -2844
  29. package/dist/singlebase-elements.min.js.map +1 -1
  30. package/dist/styles/branding.d.ts +5 -0
  31. package/dist/styles/tokens.d.ts +2 -0
  32. package/dist/upload-messages.d.ts +0 -1
  33. package/dist/{uploader-DGV2y9uT.cjs → uploader-COP8PkJ6.cjs} +53 -76
  34. package/dist/uploader-COP8PkJ6.cjs.map +1 -0
  35. package/dist/{uploader-abQoem5q.js → uploader-tdMU9Gxv.js} +249 -253
  36. package/dist/uploader-tdMU9Gxv.js.map +1 -0
  37. package/dist/uploader.cjs +1 -1
  38. package/dist/uploader.js +2 -2
  39. package/dist/utils/branding.d.ts +8 -0
  40. package/dist/utils/markdown.d.ts +69 -12
  41. package/dist/utils/svg.d.ts +10 -0
  42. package/package.json +3 -3
  43. package/dist/authui-display-BCZBP7HR.js.map +0 -1
  44. package/dist/authui-display-CLGFSqRi.cjs.map +0 -1
  45. package/dist/chat-DRenTJlI.cjs +0 -3001
  46. package/dist/chat-DRenTJlI.cjs.map +0 -1
  47. package/dist/chat-bXaRWel7.js.map +0 -1
  48. package/dist/files-BOwtpYyQ.js.map +0 -1
  49. package/dist/files-DW8A4Jl-.cjs +0 -38
  50. package/dist/files-DW8A4Jl-.cjs.map +0 -1
  51. package/dist/uploader-DGV2y9uT.cjs.map +0 -1
  52. package/dist/uploader-abQoem5q.js.map +0 -1
@@ -1,3001 +0,0 @@
1
- "use strict";var mt=Object.defineProperty;var We=o=>{throw TypeError(o)};var bt=(o,n,e)=>n in o?mt(o,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[n]=e;var k=(o,n,e)=>bt(o,typeof n!="symbol"?n+"":n,e),qe=(o,n,e)=>n.has(o)||We("Cannot "+e);var d=(o,n,e)=>(qe(o,n,"read from private field"),e?e.call(o):n.get(o)),p=(o,n,e)=>n.has(o)?We("Cannot add the same private member more than once"):n instanceof WeakSet?n.add(o):n.set(o,e),h=(o,n,e,t)=>(qe(o,n,"write to private field"),t?t.call(o,e):n.set(o,e),e);const s=require("lit"),u=require("lit/decorators.js"),ft=require("lit/directives/repeat.js"),xt=require("@singlebase/core"),$=require("./files-DW8A4Jl-.cjs");if(typeof CSS<"u"&&"registerProperty"in CSS)try{CSS.registerProperty({name:"--sb-ai-angle",syntax:"<angle>",inherits:!1,initialValue:"0deg"})}catch{}const vt=s.css`
2
- :host {
3
- --c-ink: var(--sb-ink, #16181a);
4
- --c-ink2: var(--sb-ink-2, #41464b);
5
- --c-muted: var(--sb-muted-ink, #61666c);
6
- --c-faint: #8a8f95;
7
- --c-bg: var(--sb-surface, #ffffff);
8
- --c-bg2: var(--sb-surface-alt, #fafafa);
9
- --c-hover: var(--sb-hover, #f2f3f4);
10
- --c-line: var(--sb-border, #e4e6e9);
11
- --c-line2: var(--sb-divider, #ecedee);
12
- --c-strong: var(--sb-border-strong, #cdd1d6);
13
- --c-brand: var(--sb-accent, #16181a);
14
- --c-on-brand: var(--sb-on-accent, #ffffff);
15
- --c-danger: var(--sb-danger, #b4231a);
16
- --c-ok: var(--sb-ok, #0f6b4a);
17
- --c-mono: var(--sb-mono, "Geist Mono", ui-monospace, monospace);
18
- --c-r: var(--sb-radius, 4px);
19
- --c-r2: calc(var(--c-r) * 1.5);
20
- --c-r3: calc(var(--c-r) * 2);
21
- --c-r4: calc(var(--c-r) * 3);
22
- --c-glow: 0.6;
23
- --c-conic: conic-gradient(
24
- from var(--sb-ai-angle, 0deg),
25
- oklch(0.72 0.15 295),
26
- oklch(0.74 0.13 245),
27
- oklch(0.8 0.11 190),
28
- oklch(0.84 0.12 85),
29
- oklch(0.78 0.12 350),
30
- oklch(0.72 0.15 295)
31
- );
32
- --c-z: var(--sb-chat-z, 1000);
33
- display: block;
34
- height: 100%;
35
- min-height: 0;
36
- color-scheme: light;
37
- }
38
-
39
- :host([theme="dark"]) {
40
- --sb-hover: #24272b;
41
- --sb-ink-2: #c9ccd0;
42
- --sb-divider: #26292d;
43
- --c-faint: #7c8187;
44
- color-scheme: dark;
45
- }
46
-
47
- :host([glow="vivid"]) {
48
- --c-glow: 1;
49
- }
50
-
51
- :host([embed="inline"]) {
52
- height: auto;
53
- }
54
-
55
- :host([embed="launcher"]) {
56
- height: 0;
57
- }
58
-
59
- * {
60
- box-sizing: border-box;
61
- }
62
-
63
- button {
64
- font: inherit;
65
- color: inherit;
66
- }
67
-
68
- button:focus-visible,
69
- input:focus-visible,
70
- textarea:focus-visible,
71
- [role="button"]:focus-visible {
72
- outline: 2px solid var(--c-ink);
73
- outline-offset: 1px;
74
- }
75
-
76
- .mono {
77
- font-family: var(--c-mono);
78
- }
79
-
80
- .label {
81
- font-family: var(--c-mono);
82
- font-size: 11px;
83
- letter-spacing: 0.07em;
84
- text-transform: uppercase;
85
- color: var(--c-muted);
86
- }
87
-
88
- /* ── frames ───────────────────────────────────────────── */
89
-
90
- .frame {
91
- position: relative;
92
- display: flex;
93
- height: 100%;
94
- min-height: 0;
95
- background: var(--c-bg);
96
- color: var(--c-ink);
97
- overflow: hidden;
98
- }
99
-
100
- .frame.boxed {
101
- border: 1px solid var(--c-line);
102
- border-radius: var(--c-r4);
103
- }
104
-
105
- .frame.inline {
106
- width: 440px;
107
- height: 660px;
108
- min-width: 340px;
109
- min-height: 480px;
110
- max-width: 100%;
111
- resize: both;
112
- box-shadow: 0 1px 2px rgba(22, 24, 26, 0.06);
113
- }
114
-
115
- @media (max-width: 559px) {
116
- .frame.inline {
117
- width: 100%;
118
- min-width: 0;
119
- resize: none;
120
- }
121
- }
122
-
123
- .frame.launcher {
124
- position: fixed;
125
- bottom: 96px;
126
- right: 24px;
127
- z-index: var(--c-z);
128
- width: 420px;
129
- height: min(680px, calc(100vh - 120px));
130
- max-width: calc(100vw - 48px);
131
- box-shadow: 0 24px 60px -24px rgba(22, 24, 26, 0.35);
132
- transform-origin: bottom right;
133
- animation: scaleIn 0.2s ease-out;
134
- }
135
-
136
- :host([position="left"]) .frame.launcher {
137
- right: auto;
138
- left: 24px;
139
- transform-origin: bottom left;
140
- }
141
-
142
- .frame.expanded {
143
- position: fixed;
144
- inset: 24px;
145
- width: auto;
146
- height: auto;
147
- max-width: none;
148
- z-index: var(--c-z);
149
- resize: none;
150
- box-shadow: 0 24px 60px -24px rgba(22, 24, 26, 0.35);
151
- animation: scaleIn 0.2s ease-out;
152
- }
153
-
154
- .frame.full {
155
- position: fixed;
156
- inset: 0;
157
- width: auto;
158
- height: auto;
159
- max-width: none;
160
- border-radius: 0;
161
- border: none;
162
- z-index: var(--c-z);
163
- resize: none;
164
- }
165
-
166
- .root {
167
- position: relative;
168
- display: flex;
169
- flex: 1;
170
- min-width: 0;
171
- min-height: 0;
172
- font-family: var(--sb-font, "Geist", -apple-system, "Segoe UI", Helvetica, sans-serif);
173
- background: var(--c-bg);
174
- color: var(--c-ink);
175
- }
176
-
177
- /* ── launcher ─────────────────────────────────────────── */
178
-
179
- .launcher-btn {
180
- position: fixed;
181
- bottom: 24px;
182
- right: 24px;
183
- z-index: calc(var(--c-z) + 1);
184
- width: 56px;
185
- height: 56px;
186
- border-radius: 999px;
187
- display: inline-flex;
188
- align-items: center;
189
- justify-content: center;
190
- border: none;
191
- cursor: pointer;
192
- background: var(--c-brand);
193
- color: var(--c-on-brand);
194
- box-shadow: 0 12px 28px -10px rgba(22, 24, 26, 0.45);
195
- }
196
-
197
- :host([position="left"]) .launcher-btn,
198
- :host([position="left"]) .bubble {
199
- right: auto;
200
- left: 24px;
201
- }
202
-
203
- .badge {
204
- position: absolute;
205
- top: 2px;
206
- right: 2px;
207
- width: 12px;
208
- height: 12px;
209
- border-radius: 999px;
210
- background: var(--c-danger);
211
- border: 2px solid var(--c-bg);
212
- }
213
-
214
- .bubble {
215
- position: fixed;
216
- bottom: 96px;
217
- right: 24px;
218
- z-index: var(--c-z);
219
- width: 260px;
220
- display: flex;
221
- align-items: flex-start;
222
- gap: 8px;
223
- padding: 12px 10px 12px 14px;
224
- background: var(--c-bg);
225
- color: var(--c-ink);
226
- border: 1px solid var(--c-line);
227
- border-radius: calc(var(--c-r) * 2.5);
228
- box-shadow: 0 12px 32px -12px rgba(22, 24, 26, 0.25);
229
- font-family: var(--sb-font, "Geist", -apple-system, "Segoe UI", Helvetica, sans-serif);
230
- animation: aiIn 0.25s ease-out;
231
- }
232
-
233
- .bubble-text {
234
- flex: 1;
235
- min-width: 0;
236
- text-align: left;
237
- font-size: 13.5px;
238
- line-height: 1.45;
239
- background: none;
240
- border: none;
241
- padding: 0;
242
- cursor: pointer;
243
- }
244
-
245
- /* ── icon buttons ─────────────────────────────────────── */
246
-
247
- .icon {
248
- display: inline-flex;
249
- align-items: center;
250
- justify-content: center;
251
- flex: 0 0 auto;
252
- width: 28px;
253
- height: 28px;
254
- padding: 0;
255
- border: none;
256
- border-radius: var(--c-r);
257
- background: transparent;
258
- color: var(--c-muted);
259
- cursor: pointer;
260
- }
261
-
262
- .icon:hover:not(:disabled),
263
- .icon.on {
264
- color: var(--c-ink);
265
- }
266
-
267
- .icon:hover:not(:disabled) {
268
- background: var(--c-hover);
269
- }
270
-
271
- .icon.danger:hover:not(:disabled) {
272
- color: var(--c-danger);
273
- }
274
-
275
- .icon:disabled {
276
- opacity: 0.4;
277
- cursor: default;
278
- }
279
-
280
- .icon.sm {
281
- width: 24px;
282
- height: 24px;
283
- }
284
-
285
- svg.i {
286
- width: 16px;
287
- height: 16px;
288
- fill: none;
289
- stroke: currentColor;
290
- stroke-width: 1.5;
291
- stroke-linecap: round;
292
- stroke-linejoin: round;
293
- }
294
-
295
- svg.i.filled path {
296
- fill: currentColor;
297
- }
298
-
299
- @media (pointer: coarse) {
300
- .icon {
301
- width: 44px;
302
- height: 44px;
303
- }
304
- }
305
-
306
- /* ── sidebar ──────────────────────────────────────────── */
307
-
308
- .scrim {
309
- position: absolute;
310
- inset: 0;
311
- z-index: 29;
312
- background: rgba(22, 24, 26, 0.18);
313
- }
314
-
315
- .sidebar {
316
- display: flex;
317
- flex-direction: column;
318
- min-height: 0;
319
- min-width: 0;
320
- background: var(--c-bg2);
321
- border-right: 1px solid var(--c-line);
322
- }
323
-
324
- .sidebar.docked {
325
- position: relative;
326
- flex: 0 0 272px;
327
- width: 272px;
328
- }
329
-
330
- .sidebar.overlay {
331
- position: absolute;
332
- left: 0;
333
- top: 0;
334
- bottom: 0;
335
- z-index: 30;
336
- width: min(280px, 86%);
337
- box-shadow: 12px 0 32px -16px rgba(22, 24, 26, 0.25);
338
- animation: slideIn 0.15s ease-out;
339
- }
340
-
341
- .side-head {
342
- display: flex;
343
- align-items: center;
344
- justify-content: space-between;
345
- gap: 8px;
346
- padding: 14px 12px 10px 16px;
347
- }
348
-
349
- .side-tools {
350
- display: flex;
351
- flex-direction: column;
352
- gap: 8px;
353
- padding: 0 12px 8px;
354
- }
355
-
356
- .new-chat {
357
- display: flex;
358
- align-items: center;
359
- gap: 8px;
360
- width: 100%;
361
- min-height: 34px;
362
- font-size: 13px;
363
- font-weight: 500;
364
- color: var(--c-on-brand);
365
- background: var(--c-brand);
366
- border: 1px solid var(--c-brand);
367
- border-radius: var(--c-r2);
368
- padding: 8px 12px;
369
- cursor: pointer;
370
- }
371
-
372
- .new-chat:hover {
373
- filter: brightness(1.2);
374
- }
375
-
376
- .search {
377
- width: 100%;
378
- font: inherit;
379
- font-size: 13px;
380
- color: var(--c-ink);
381
- background: var(--c-bg);
382
- border: 1px solid var(--c-line);
383
- border-radius: var(--c-r2);
384
- padding: 8px 10px;
385
- outline: none;
386
- }
387
-
388
- .search:focus {
389
- border-color: var(--c-ink);
390
- }
391
-
392
- .threads {
393
- flex: 1;
394
- min-height: 0;
395
- overflow-y: auto;
396
- display: flex;
397
- flex-direction: column;
398
- gap: 1px;
399
- padding: 4px 12px 12px;
400
- }
401
-
402
- .group {
403
- font-family: var(--c-mono);
404
- font-size: 11px;
405
- letter-spacing: 0.07em;
406
- text-transform: uppercase;
407
- color: var(--c-muted);
408
- padding: 10px 8px 6px;
409
- }
410
-
411
- .thread {
412
- display: flex;
413
- align-items: center;
414
- gap: 4px;
415
- min-height: 34px;
416
- width: 100%;
417
- font-size: 13px;
418
- color: var(--c-ink);
419
- border-radius: var(--c-r2);
420
- padding: 3px 4px 3px 10px;
421
- cursor: pointer;
422
- }
423
-
424
- .thread:hover {
425
- background: var(--c-hover);
426
- }
427
-
428
- .thread.active {
429
- background: var(--c-line2);
430
- font-weight: 500;
431
- }
432
-
433
- .thread-title {
434
- flex: 1;
435
- min-width: 0;
436
- overflow: hidden;
437
- text-overflow: ellipsis;
438
- white-space: nowrap;
439
- }
440
-
441
- .thread-actions {
442
- display: none;
443
- gap: 0;
444
- }
445
-
446
- .thread:hover .thread-actions,
447
- .thread:focus-within .thread-actions {
448
- display: flex;
449
- }
450
-
451
- .thread-rename {
452
- flex: 1;
453
- min-width: 0;
454
- font: inherit;
455
- color: var(--c-ink);
456
- background: var(--c-bg);
457
- border: 1px solid var(--c-ink);
458
- border-radius: var(--c-r);
459
- padding: 3px 6px;
460
- outline: none;
461
- }
462
-
463
- .side-note {
464
- font-size: 12.5px;
465
- color: var(--c-muted);
466
- padding: 6px 10px;
467
- }
468
-
469
- .skeleton {
470
- height: 28px;
471
- margin: 3px 0;
472
- border-radius: var(--c-r2);
473
- background: linear-gradient(90deg, var(--c-hover) 0%, var(--c-line2) 50%, var(--c-hover) 100%);
474
- background-size: 200% 100%;
475
- animation: aiShimmer 1.6s linear infinite;
476
- }
477
-
478
- /* ── main column ──────────────────────────────────────── */
479
-
480
- .main {
481
- container: chat / inline-size;
482
- position: relative;
483
- flex: 1;
484
- min-width: 0;
485
- min-height: 0;
486
- display: flex;
487
- flex-direction: column;
488
- }
489
-
490
- .header {
491
- display: flex;
492
- align-items: center;
493
- justify-content: space-between;
494
- gap: 12px;
495
- min-height: 52px;
496
- padding: 10px 8px 10px 12px;
497
- border-bottom: 1px solid var(--c-line);
498
- }
499
-
500
- .header-left {
501
- display: flex;
502
- align-items: center;
503
- gap: 10px;
504
- min-width: 0;
505
- }
506
-
507
- .header-right {
508
- flex: 0 0 auto;
509
- display: flex;
510
- align-items: center;
511
- gap: 2px;
512
- }
513
-
514
- .title {
515
- min-width: 0;
516
- font-size: 14px;
517
- font-weight: 600;
518
- letter-spacing: -0.01em;
519
- overflow: hidden;
520
- text-overflow: ellipsis;
521
- white-space: nowrap;
522
- background: none;
523
- border: none;
524
- padding: 2px 4px;
525
- border-radius: var(--c-r);
526
- cursor: text;
527
- animation: aiIn 0.25s ease-out;
528
- }
529
-
530
- .title:hover:not(:disabled) {
531
- background: var(--c-hover);
532
- }
533
-
534
- .title:disabled {
535
- cursor: default;
536
- }
537
-
538
- .title-input {
539
- min-width: 0;
540
- width: 320px;
541
- max-width: 100%;
542
- font: inherit;
543
- font-size: 14px;
544
- font-weight: 600;
545
- color: var(--c-ink);
546
- background: var(--c-bg);
547
- border: 1px solid var(--c-ink);
548
- border-radius: var(--c-r);
549
- padding: 2px 6px;
550
- outline: none;
551
- }
552
-
553
- .divider {
554
- width: 1px;
555
- height: 18px;
556
- background: var(--c-line);
557
- margin: 0 4px;
558
- }
559
-
560
- .menu-wrap {
561
- position: relative;
562
- }
563
-
564
- .menu-scrim {
565
- position: fixed;
566
- inset: 0;
567
- z-index: 40;
568
- }
569
-
570
- .menu {
571
- position: absolute;
572
- right: 0;
573
- top: 34px;
574
- z-index: 41;
575
- width: 220px;
576
- display: flex;
577
- flex-direction: column;
578
- padding: 4px;
579
- background: var(--c-bg);
580
- border: 1px solid var(--c-line);
581
- border-radius: var(--c-r2);
582
- box-shadow: 0 12px 32px -12px rgba(22, 24, 26, 0.22);
583
- animation: aiIn 0.15s ease-out;
584
- }
585
-
586
- .menu .label {
587
- font-size: 10.5px;
588
- padding: 8px 10px 6px;
589
- }
590
-
591
- .menu-item {
592
- display: flex;
593
- align-items: baseline;
594
- justify-content: space-between;
595
- gap: 10px;
596
- width: 100%;
597
- text-align: left;
598
- font-size: 13px;
599
- background: none;
600
- border: none;
601
- border-radius: var(--c-r);
602
- padding: 8px 10px;
603
- cursor: pointer;
604
- }
605
-
606
- .menu-item:hover {
607
- background: var(--c-hover);
608
- }
609
-
610
- .menu-item .ext {
611
- font-family: var(--c-mono);
612
- font-size: 11px;
613
- color: var(--c-muted);
614
- }
615
-
616
- .scroller {
617
- position: relative;
618
- flex: 1;
619
- min-height: 0;
620
- overflow-y: auto;
621
- }
622
-
623
- .banner {
624
- margin: 10px 16px 0;
625
- padding: 8px 12px;
626
- font-size: 12.5px;
627
- color: var(--c-ink2);
628
- background: var(--c-bg2);
629
- border: 1px solid var(--c-line);
630
- border-radius: var(--c-r2);
631
- }
632
-
633
- /* ── welcome ──────────────────────────────────────────── */
634
-
635
- .welcome {
636
- max-width: 640px;
637
- min-height: 100%;
638
- margin: 0 auto;
639
- display: flex;
640
- flex-direction: column;
641
- justify-content: center;
642
- gap: 20px;
643
- padding: 28px 18px;
644
- }
645
-
646
- .welcome-head {
647
- display: flex;
648
- flex-direction: column;
649
- gap: 8px;
650
- }
651
-
652
- .welcome-logo {
653
- width: 32px;
654
- height: 32px;
655
- object-fit: contain;
656
- border-radius: var(--c-r2);
657
- }
658
-
659
- .welcome h2 {
660
- margin: 0;
661
- font-size: 24px;
662
- font-weight: 600;
663
- letter-spacing: -0.01em;
664
- }
665
-
666
- .welcome p {
667
- margin: 0;
668
- font-size: 14px;
669
- line-height: 1.55;
670
- color: var(--c-muted);
671
- text-wrap: pretty;
672
- }
673
-
674
- .prompts {
675
- display: grid;
676
- grid-template-columns: repeat(2, minmax(0, 1fr));
677
- gap: 8px;
678
- }
679
-
680
- .prompt {
681
- display: flex;
682
- flex-direction: column;
683
- gap: 4px;
684
- text-align: left;
685
- background: var(--c-bg);
686
- border: 1px solid var(--c-line);
687
- border-radius: var(--c-r2);
688
- padding: 12px 14px;
689
- cursor: pointer;
690
- transition:
691
- border-color 0.15s,
692
- box-shadow 0.15s;
693
- }
694
-
695
- .prompt:hover {
696
- border-color: var(--c-ink);
697
- box-shadow: 0 6px 18px -10px rgba(22, 24, 26, 0.25);
698
- }
699
-
700
- .prompt .label {
701
- font-size: 10.5px;
702
- letter-spacing: 0.06em;
703
- }
704
-
705
- .prompt-text {
706
- font-size: 13.5px;
707
- font-weight: 500;
708
- line-height: 1.4;
709
- }
710
-
711
- @container chat (max-width: 480px) {
712
- .prompts {
713
- grid-template-columns: minmax(0, 1fr);
714
- }
715
- }
716
-
717
- /* ── messages ─────────────────────────────────────────── */
718
-
719
- .thread-view {
720
- max-width: 760px;
721
- margin: 0 auto;
722
- display: flex;
723
- flex-direction: column;
724
- gap: 30px;
725
- padding: 20px 16px 28px;
726
- }
727
-
728
- .msg {
729
- position: relative;
730
- display: flex;
731
- flex-direction: column;
732
- border-radius: var(--c-r3);
733
- }
734
-
735
- .msg.user {
736
- align-self: flex-end;
737
- max-width: 80%;
738
- align-items: flex-end;
739
- gap: 6px;
740
- margin-bottom: -22px;
741
- animation: aiIn 0.25s ease-out;
742
- }
743
-
744
- .bubble-user {
745
- padding: 10px 14px;
746
- font-size: 14.5px;
747
- line-height: 1.6;
748
- white-space: pre-wrap;
749
- overflow-wrap: anywhere;
750
- background: var(--c-hover);
751
- border-radius: calc(var(--c-r) * 2.5) calc(var(--c-r) * 2.5) 2px calc(var(--c-r) * 2.5);
752
- }
753
-
754
- .attachments {
755
- display: flex;
756
- flex-wrap: wrap;
757
- justify-content: flex-end;
758
- gap: 6px;
759
- }
760
-
761
- .doc-chip {
762
- display: inline-flex;
763
- align-items: center;
764
- gap: 8px;
765
- padding: 6px 10px;
766
- font-size: 12.5px;
767
- border-radius: var(--c-r2);
768
- border: 1px solid var(--c-line);
769
- background: var(--c-bg);
770
- }
771
-
772
- .doc-chip .ext {
773
- font-family: var(--c-mono);
774
- font-size: 10px;
775
- letter-spacing: 0.04em;
776
- color: var(--c-muted);
777
- }
778
-
779
- .doc-chip .name {
780
- max-width: 180px;
781
- overflow: hidden;
782
- text-overflow: ellipsis;
783
- white-space: nowrap;
784
- }
785
-
786
- .toolbar {
787
- display: flex;
788
- align-items: center;
789
- gap: 2px;
790
- opacity: 0;
791
- transition: opacity 0.15s;
792
- }
793
-
794
- .msg:hover .toolbar,
795
- .msg:focus-within .toolbar,
796
- .toolbar.pinned {
797
- opacity: 1;
798
- }
799
-
800
- @media (hover: none) {
801
- .toolbar {
802
- opacity: 1;
803
- }
804
- }
805
-
806
- .msg.bot .toolbar {
807
- margin-left: -6px;
808
- }
809
-
810
- .time {
811
- font-family: var(--c-mono);
812
- font-size: 11px;
813
- color: var(--c-faint);
814
- padding: 0 6px;
815
- font-variant-numeric: tabular-nums;
816
- }
817
-
818
- .note {
819
- font-size: 12px;
820
- color: var(--c-muted);
821
- }
822
-
823
- .spacer {
824
- flex: 1;
825
- }
826
-
827
- .saved {
828
- display: inline-flex;
829
- align-items: center;
830
- gap: 4px;
831
- font-family: var(--c-mono);
832
- font-size: 10.5px;
833
- letter-spacing: 0.05em;
834
- text-transform: uppercase;
835
- color: var(--c-ink);
836
- }
837
-
838
- .saved svg {
839
- width: 12px;
840
- height: 12px;
841
- fill: currentColor;
842
- stroke: currentColor;
843
- stroke-width: 1.5;
844
- }
845
-
846
- .bot-body {
847
- position: relative;
848
- z-index: 1;
849
- display: flex;
850
- flex-direction: column;
851
- gap: 12px;
852
- }
853
-
854
- .edit-box {
855
- width: 440px;
856
- max-width: 100%;
857
- display: flex;
858
- flex-direction: column;
859
- gap: 8px;
860
- padding: 8px;
861
- border: 1px solid var(--c-ink);
862
- border-radius: var(--c-r3);
863
- background: var(--c-bg);
864
- }
865
-
866
- .edit-box textarea {
867
- width: 100%;
868
- resize: vertical;
869
- font: inherit;
870
- font-size: 14px;
871
- line-height: 1.5;
872
- color: var(--c-ink);
873
- background: transparent;
874
- border: none;
875
- outline: none;
876
- padding: 4px;
877
- }
878
-
879
- .row-end {
880
- display: flex;
881
- justify-content: flex-end;
882
- gap: 8px;
883
- }
884
-
885
- .btn {
886
- font-size: 12.5px;
887
- font-weight: 500;
888
- border-radius: var(--c-r);
889
- padding: 6px 12px;
890
- cursor: pointer;
891
- background: transparent;
892
- color: var(--c-muted);
893
- border: 1px solid var(--c-line);
894
- }
895
-
896
- .btn:hover {
897
- color: var(--c-ink);
898
- background: var(--c-bg2);
899
- }
900
-
901
- .btn.primary {
902
- background: var(--c-brand);
903
- color: var(--c-on-brand);
904
- border-color: var(--c-brand);
905
- }
906
-
907
- .btn.primary:hover {
908
- filter: brightness(1.2);
909
- }
910
-
911
- .error-card {
912
- display: flex;
913
- align-items: center;
914
- justify-content: space-between;
915
- gap: 12px;
916
- padding: 10px 12px;
917
- font-size: 13px;
918
- color: var(--c-danger);
919
- border: 1px solid var(--sb-danger-border, #f3d6d3);
920
- background: var(--sb-danger-bg, #fdf1f0);
921
- border-radius: var(--c-r2);
922
- }
923
-
924
- .followups {
925
- display: flex;
926
- flex-direction: column;
927
- align-items: flex-start;
928
- gap: 6px;
929
- }
930
-
931
- .followup {
932
- display: inline-flex;
933
- align-items: baseline;
934
- gap: 8px;
935
- text-align: left;
936
- font-size: 13px;
937
- background: var(--c-bg);
938
- border: 1px solid var(--c-line);
939
- border-radius: var(--c-r2);
940
- padding: 6px 12px;
941
- cursor: pointer;
942
- animation: aiIn 0.25s ease-out;
943
- }
944
-
945
- .followup:hover {
946
- background: var(--c-hover);
947
- }
948
-
949
- .followup .arrow {
950
- font-family: var(--c-mono);
951
- color: var(--c-muted);
952
- }
953
-
954
- .jump {
955
- position: absolute;
956
- left: 50%;
957
- bottom: 8px;
958
- transform: translateX(-50%);
959
- z-index: 5;
960
- font-size: 12.5px;
961
- font-weight: 500;
962
- color: var(--c-on-brand);
963
- background: var(--c-brand);
964
- border: none;
965
- border-radius: 999px;
966
- padding: 6px 14px;
967
- cursor: pointer;
968
- box-shadow: 0 8px 20px -10px rgba(22, 24, 26, 0.4);
969
- animation: aiIn 0.2s ease-out;
970
- }
971
-
972
- /* ── rendered answer ──────────────────────────────────── */
973
-
974
- .answer {
975
- display: flex;
976
- flex-direction: column;
977
- gap: 14px;
978
- font-size: 14.5px;
979
- line-height: 1.7;
980
- }
981
-
982
- .answer p {
983
- margin: 0;
984
- text-wrap: pretty;
985
- overflow-wrap: anywhere;
986
- }
987
-
988
- .answer .raw {
989
- white-space: pre-wrap;
990
- }
991
-
992
- .answer h3 {
993
- margin: 6px 0 0;
994
- font-size: 15.5px;
995
- font-weight: 600;
996
- letter-spacing: -0.01em;
997
- line-height: 1.4;
998
- }
999
-
1000
- .answer ul,
1001
- .answer ol {
1002
- margin: 0;
1003
- padding-left: 20px;
1004
- display: flex;
1005
- flex-direction: column;
1006
- gap: 6px;
1007
- }
1008
-
1009
- .answer li {
1010
- line-height: 1.65;
1011
- padding-left: 2px;
1012
- }
1013
-
1014
- .answer strong {
1015
- font-weight: 600;
1016
- }
1017
-
1018
- .answer a {
1019
- color: var(--c-ink);
1020
- text-underline-offset: 3px;
1021
- }
1022
-
1023
- .answer code.inline {
1024
- font-family: var(--c-mono);
1025
- font-size: 12.5px;
1026
- background: var(--c-hover);
1027
- border-radius: calc(var(--c-r) * 0.75);
1028
- padding: 1px 5px;
1029
- }
1030
-
1031
- .quote {
1032
- font-size: 13.5px;
1033
- line-height: 1.6;
1034
- color: var(--c-ink2);
1035
- background: var(--c-bg2);
1036
- border: 1px solid var(--c-line);
1037
- border-radius: var(--c-r2);
1038
- padding: 10px 14px;
1039
- }
1040
-
1041
- .code {
1042
- border: 1px solid var(--c-line);
1043
- border-radius: var(--c-r2);
1044
- overflow: hidden;
1045
- background: var(--c-bg2);
1046
- }
1047
-
1048
- .code-head {
1049
- display: flex;
1050
- align-items: center;
1051
- justify-content: space-between;
1052
- padding: 7px 12px;
1053
- border-bottom: 1px solid var(--c-line);
1054
- }
1055
-
1056
- .code-head .label {
1057
- font-size: 11px;
1058
- }
1059
-
1060
- .text-btn {
1061
- font-size: 12px;
1062
- color: var(--c-muted);
1063
- background: none;
1064
- border: none;
1065
- padding: 0;
1066
- cursor: pointer;
1067
- }
1068
-
1069
- .text-btn:hover {
1070
- color: var(--c-ink);
1071
- }
1072
-
1073
- .text-btn.underline {
1074
- text-decoration: underline;
1075
- text-underline-offset: 3px;
1076
- }
1077
-
1078
- .code pre {
1079
- margin: 0;
1080
- padding: 12px 14px;
1081
- overflow-x: auto;
1082
- font-family: var(--c-mono);
1083
- font-size: 13px;
1084
- line-height: 1.6;
1085
- }
1086
-
1087
- .table {
1088
- border: 1px solid var(--c-line);
1089
- border-radius: var(--c-r2);
1090
- overflow-x: auto;
1091
- }
1092
-
1093
- .table table {
1094
- width: 100%;
1095
- border-collapse: collapse;
1096
- font-size: 13px;
1097
- font-variant-numeric: tabular-nums;
1098
- }
1099
-
1100
- .table th {
1101
- text-align: left;
1102
- font-size: 12px;
1103
- font-weight: 500;
1104
- color: var(--c-muted);
1105
- background: var(--c-bg2);
1106
- border-bottom: 1px solid var(--c-line);
1107
- padding: 9px 12px;
1108
- white-space: nowrap;
1109
- }
1110
-
1111
- .table td {
1112
- padding: 9px 12px;
1113
- border-top: 1px solid var(--c-line2);
1114
- white-space: nowrap;
1115
- }
1116
-
1117
- .table th:first-child,
1118
- .table td:first-child {
1119
- min-width: 120px;
1120
- }
1121
-
1122
- .cite {
1123
- display: inline-flex;
1124
- align-items: center;
1125
- justify-content: center;
1126
- min-width: 17px;
1127
- height: 17px;
1128
- padding: 0 4px;
1129
- margin: 0 1px 0 3px;
1130
- vertical-align: 2px;
1131
- font: 500 10px var(--c-mono);
1132
- border-radius: calc(var(--c-r) * 0.75);
1133
- cursor: pointer;
1134
- border: 1px solid var(--c-strong);
1135
- background: var(--c-hover);
1136
- color: var(--c-ink);
1137
- }
1138
-
1139
- .cite:hover,
1140
- .cite.active {
1141
- background: var(--c-ink);
1142
- color: var(--c-bg);
1143
- border-color: var(--c-ink);
1144
- }
1145
-
1146
- .chart {
1147
- margin: 0;
1148
- display: flex;
1149
- flex-direction: column;
1150
- gap: 14px;
1151
- border: 1px solid var(--c-line);
1152
- border-radius: var(--c-r2);
1153
- padding: 14px 16px 12px;
1154
- background: var(--c-bg);
1155
- }
1156
-
1157
- .chart-head {
1158
- display: flex;
1159
- flex-wrap: wrap;
1160
- align-items: baseline;
1161
- justify-content: space-between;
1162
- gap: 8px 16px;
1163
- }
1164
-
1165
- .chart-title {
1166
- font-size: 13px;
1167
- font-weight: 600;
1168
- }
1169
-
1170
- .legend {
1171
- display: flex;
1172
- flex-wrap: wrap;
1173
- gap: 4px 12px;
1174
- }
1175
-
1176
- .legend span {
1177
- display: inline-flex;
1178
- align-items: center;
1179
- gap: 6px;
1180
- font-size: 12px;
1181
- color: var(--c-ink2);
1182
- }
1183
-
1184
- .swatch {
1185
- width: 8px;
1186
- height: 8px;
1187
- border-radius: 2px;
1188
- }
1189
-
1190
- .bars {
1191
- display: flex;
1192
- flex-direction: column;
1193
- gap: 10px;
1194
- }
1195
-
1196
- .bar-row {
1197
- display: grid;
1198
- grid-template-columns: 92px minmax(0, 1fr) 64px;
1199
- align-items: center;
1200
- gap: 12px;
1201
- }
1202
-
1203
- .bar-label {
1204
- font-size: 12.5px;
1205
- color: var(--c-ink2);
1206
- overflow: hidden;
1207
- text-overflow: ellipsis;
1208
- white-space: nowrap;
1209
- }
1210
-
1211
- .bar-track {
1212
- display: flex;
1213
- height: 12px;
1214
- background: var(--c-hover);
1215
- border-radius: 2px;
1216
- overflow: hidden;
1217
- }
1218
-
1219
- .bar-fill {
1220
- display: flex;
1221
- height: 100%;
1222
- transform-origin: left;
1223
- animation: aiGrow 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
1224
- }
1225
-
1226
- .bar-value {
1227
- font-family: var(--c-mono);
1228
- font-size: 11.5px;
1229
- text-align: right;
1230
- font-variant-numeric: tabular-nums;
1231
- }
1232
-
1233
- .line-chart {
1234
- display: flex;
1235
- flex-direction: column;
1236
- gap: 6px;
1237
- padding-left: 48px;
1238
- }
1239
-
1240
- .plot {
1241
- position: relative;
1242
- height: 170px;
1243
- }
1244
-
1245
- .tick {
1246
- position: absolute;
1247
- left: 0;
1248
- right: 0;
1249
- border-top: 1px dashed var(--c-line2);
1250
- }
1251
-
1252
- .tick.base {
1253
- border-top: 1px solid var(--c-strong);
1254
- }
1255
-
1256
- .tick span,
1257
- .x-labels span {
1258
- font-family: var(--c-mono);
1259
- font-size: 10.5px;
1260
- color: var(--c-faint);
1261
- white-space: nowrap;
1262
- font-variant-numeric: tabular-nums;
1263
- }
1264
-
1265
- .tick span {
1266
- position: absolute;
1267
- right: calc(100% + 8px);
1268
- top: -7px;
1269
- }
1270
-
1271
- .plot svg {
1272
- position: absolute;
1273
- inset: 0;
1274
- width: 100%;
1275
- height: 100%;
1276
- overflow: visible;
1277
- }
1278
-
1279
- .plot polyline {
1280
- fill: none;
1281
- stroke-width: 2;
1282
- vector-effect: non-scaling-stroke;
1283
- stroke-linejoin: round;
1284
- stroke-linecap: round;
1285
- stroke-dasharray: 1;
1286
- animation: aiDraw 1s ease-out;
1287
- }
1288
-
1289
- .x-labels {
1290
- display: flex;
1291
- justify-content: space-between;
1292
- gap: 4px;
1293
- }
1294
-
1295
- .chart-pending {
1296
- display: flex;
1297
- align-items: center;
1298
- justify-content: center;
1299
- height: 190px;
1300
- border: 1px solid var(--c-line);
1301
- border-radius: var(--c-r2);
1302
- background: linear-gradient(90deg, var(--c-bg2) 0%, var(--c-hover) 50%, var(--c-bg2) 100%);
1303
- background-size: 200% 100%;
1304
- animation: aiShimmer 1.6s linear infinite;
1305
- }
1306
-
1307
- .gallery {
1308
- display: grid;
1309
- grid-template-columns: minmax(0, 1fr);
1310
- gap: 10px;
1311
- max-width: 520px;
1312
- }
1313
-
1314
- .gallery.many {
1315
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1316
- max-width: 100%;
1317
- }
1318
-
1319
- .gallery figure {
1320
- margin: 0;
1321
- display: flex;
1322
- flex-direction: column;
1323
- gap: 6px;
1324
- min-width: 0;
1325
- }
1326
-
1327
- .gallery img {
1328
- width: 100%;
1329
- aspect-ratio: 16 / 10;
1330
- max-height: 320px;
1331
- object-fit: contain;
1332
- border-radius: var(--c-r2);
1333
- border: 1px solid var(--c-line);
1334
- background: var(--c-bg2);
1335
- }
1336
-
1337
- .img-missing {
1338
- aspect-ratio: 16 / 9;
1339
- display: flex;
1340
- align-items: center;
1341
- justify-content: center;
1342
- border-radius: var(--c-r2);
1343
- border: 1px dashed var(--c-strong);
1344
- background: repeating-linear-gradient(135deg, var(--c-bg2) 0 10px, var(--c-hover) 10px 20px);
1345
- }
1346
-
1347
- figcaption {
1348
- font-family: var(--c-mono);
1349
- font-size: 11px;
1350
- color: var(--c-muted);
1351
- overflow: hidden;
1352
- text-overflow: ellipsis;
1353
- white-space: nowrap;
1354
- }
1355
-
1356
- .caret {
1357
- display: inline-block;
1358
- width: 7px;
1359
- height: 15px;
1360
- margin-top: -6px;
1361
- background: var(--c-brand);
1362
- animation: rgcaret 1s steps(1) infinite;
1363
- }
1364
-
1365
- /* ── sources ──────────────────────────────────────────── */
1366
-
1367
- .retrieval {
1368
- display: flex;
1369
- flex-direction: column;
1370
- border: 1px solid var(--c-line);
1371
- border-radius: var(--c-r2);
1372
- background: var(--c-bg2);
1373
- }
1374
-
1375
- .retrieval-toggle {
1376
- display: flex;
1377
- align-items: center;
1378
- gap: 10px;
1379
- width: 100%;
1380
- text-align: left;
1381
- font-size: 12.5px;
1382
- color: var(--c-ink2);
1383
- background: none;
1384
- border: none;
1385
- padding: 9px 12px;
1386
- cursor: pointer;
1387
- }
1388
-
1389
- .retrieval-toggle .chev,
1390
- .retrieval-toggle .ms {
1391
- font-family: var(--c-mono);
1392
- font-size: 11px;
1393
- color: var(--c-muted);
1394
- }
1395
-
1396
- .retrieval-list {
1397
- display: flex;
1398
- flex-direction: column;
1399
- border-top: 1px solid var(--c-line);
1400
- padding: 4px 12px;
1401
- }
1402
-
1403
- .passage {
1404
- display: grid;
1405
- grid-template-columns: 22px minmax(0, 1fr) 64px;
1406
- align-items: center;
1407
- gap: 10px;
1408
- width: 100%;
1409
- text-align: left;
1410
- background: none;
1411
- border: none;
1412
- border-bottom: 1px solid var(--c-line2);
1413
- padding: 8px 0;
1414
- cursor: pointer;
1415
- }
1416
-
1417
- .passage:last-child {
1418
- border-bottom: none;
1419
- }
1420
-
1421
- .passage .n,
1422
- .passage .score {
1423
- font-family: var(--c-mono);
1424
- font-size: 11px;
1425
- color: var(--c-muted);
1426
- font-variant-numeric: tabular-nums;
1427
- }
1428
-
1429
- .passage .what {
1430
- display: flex;
1431
- flex-direction: column;
1432
- gap: 1px;
1433
- min-width: 0;
1434
- }
1435
-
1436
- .passage .what span:first-child {
1437
- font-size: 12.5px;
1438
- overflow: hidden;
1439
- text-overflow: ellipsis;
1440
- white-space: nowrap;
1441
- }
1442
-
1443
- .passage .what span:last-child {
1444
- font-size: 11.5px;
1445
- color: var(--c-muted);
1446
- }
1447
-
1448
- .relevance {
1449
- display: flex;
1450
- flex-direction: column;
1451
- gap: 3px;
1452
- align-items: flex-end;
1453
- }
1454
-
1455
- .relevance-track {
1456
- width: 64px;
1457
- height: 3px;
1458
- background: var(--c-line);
1459
- border-radius: 99px;
1460
- overflow: hidden;
1461
- }
1462
-
1463
- .relevance-fill {
1464
- display: block;
1465
- height: 100%;
1466
- background: var(--c-brand);
1467
- }
1468
-
1469
- .cards {
1470
- display: flex;
1471
- flex-direction: column;
1472
- gap: 8px;
1473
- }
1474
-
1475
- .card-grid {
1476
- display: grid;
1477
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
1478
- gap: 8px;
1479
- }
1480
-
1481
- .source-card {
1482
- display: flex;
1483
- flex-direction: column;
1484
- gap: 6px;
1485
- min-width: 0;
1486
- text-align: left;
1487
- padding: 10px 12px;
1488
- border-radius: var(--c-r2);
1489
- cursor: pointer;
1490
- background: var(--c-bg);
1491
- border: 1px solid var(--c-line);
1492
- }
1493
-
1494
- .source-card:hover,
1495
- .source-card.active {
1496
- border-color: var(--c-ink);
1497
- }
1498
-
1499
- .source-card .top {
1500
- display: flex;
1501
- align-items: center;
1502
- gap: 8px;
1503
- min-width: 0;
1504
- }
1505
-
1506
- .num {
1507
- min-width: 16px;
1508
- height: 16px;
1509
- padding: 0 4px;
1510
- border-radius: calc(var(--c-r) * 0.75);
1511
- border: 1px solid var(--c-strong);
1512
- display: inline-flex;
1513
- align-items: center;
1514
- justify-content: center;
1515
- font-family: var(--c-mono);
1516
- font-size: 10px;
1517
- background: var(--c-bg);
1518
- }
1519
-
1520
- .source-card .t {
1521
- font-size: 13px;
1522
- font-weight: 500;
1523
- overflow: hidden;
1524
- text-overflow: ellipsis;
1525
- white-space: nowrap;
1526
- }
1527
-
1528
- .source-card .s {
1529
- font-size: 12px;
1530
- line-height: 1.45;
1531
- color: var(--c-muted);
1532
- display: -webkit-box;
1533
- -webkit-line-clamp: 2;
1534
- -webkit-box-orient: vertical;
1535
- overflow: hidden;
1536
- }
1537
-
1538
- .panel {
1539
- display: flex;
1540
- flex-direction: column;
1541
- min-height: 0;
1542
- min-width: 0;
1543
- background: var(--c-bg);
1544
- border-left: 1px solid var(--c-line);
1545
- animation: aiIn 0.15s ease-out;
1546
- }
1547
-
1548
- .panel.docked {
1549
- position: relative;
1550
- flex: 0 0 400px;
1551
- width: 400px;
1552
- }
1553
-
1554
- .panel.overlay {
1555
- position: absolute;
1556
- right: 0;
1557
- top: 0;
1558
- bottom: 0;
1559
- z-index: 30;
1560
- width: min(420px, 100%);
1561
- box-shadow: -12px 0 32px -16px rgba(22, 24, 26, 0.25);
1562
- }
1563
-
1564
- .panel-head {
1565
- display: flex;
1566
- align-items: center;
1567
- justify-content: space-between;
1568
- gap: 8px;
1569
- padding: 14px 18px;
1570
- border-bottom: 1px solid var(--c-line);
1571
- }
1572
-
1573
- .panel-body {
1574
- flex: 1;
1575
- min-height: 0;
1576
- overflow-y: auto;
1577
- display: flex;
1578
- flex-direction: column;
1579
- gap: 16px;
1580
- padding: 18px;
1581
- }
1582
-
1583
- .panel-body h3 {
1584
- margin: 0;
1585
- font-size: 16px;
1586
- font-weight: 600;
1587
- letter-spacing: -0.01em;
1588
- }
1589
-
1590
- .panel-meta {
1591
- display: flex;
1592
- flex-direction: column;
1593
- gap: 4px;
1594
- }
1595
-
1596
- .panel-meta .path {
1597
- font-family: var(--c-mono);
1598
- font-size: 11px;
1599
- color: var(--c-muted);
1600
- overflow-wrap: anywhere;
1601
- }
1602
-
1603
- .panel-meta .meta {
1604
- font-size: 12px;
1605
- color: var(--c-muted);
1606
- }
1607
-
1608
- .passage-box {
1609
- display: flex;
1610
- flex-direction: column;
1611
- gap: 8px;
1612
- padding: 12px 14px;
1613
- border-radius: var(--c-r2);
1614
- background: var(--c-hover);
1615
- border: 1px solid var(--c-strong);
1616
- }
1617
-
1618
- .passage-box .text {
1619
- font-size: 13px;
1620
- line-height: 1.6;
1621
- color: var(--c-ink2);
1622
- white-space: pre-wrap;
1623
- overflow-wrap: anywhere;
1624
- }
1625
-
1626
- .passage-foot {
1627
- display: flex;
1628
- align-items: center;
1629
- justify-content: space-between;
1630
- gap: 8px;
1631
- padding-top: 8px;
1632
- border-top: 1px solid var(--c-line);
1633
- }
1634
-
1635
- .copy-ref {
1636
- display: inline-flex;
1637
- align-items: center;
1638
- gap: 6px;
1639
- font-size: 12px;
1640
- background: var(--c-bg);
1641
- border: 1px solid var(--c-line);
1642
- border-radius: var(--c-r);
1643
- padding: 4px 8px;
1644
- cursor: pointer;
1645
- }
1646
-
1647
- .copy-ref:hover {
1648
- border-color: var(--c-strong);
1649
- }
1650
-
1651
- .panel-foot {
1652
- display: flex;
1653
- flex-direction: column;
1654
- gap: 6px;
1655
- padding: 12px 18px 16px;
1656
- border-top: 1px solid var(--c-line);
1657
- }
1658
-
1659
- .chips {
1660
- display: flex;
1661
- flex-wrap: wrap;
1662
- gap: 6px;
1663
- }
1664
-
1665
- .chip {
1666
- font-size: 12px;
1667
- background: var(--c-bg);
1668
- border: 1px solid var(--c-line);
1669
- border-radius: var(--c-r);
1670
- padding: 4px 8px;
1671
- cursor: pointer;
1672
- max-width: 100%;
1673
- overflow: hidden;
1674
- text-overflow: ellipsis;
1675
- white-space: nowrap;
1676
- }
1677
-
1678
- .chip:hover {
1679
- border-color: var(--c-ink);
1680
- }
1681
-
1682
- /* ── composer ─────────────────────────────────────────── */
1683
-
1684
- .composer-wrap {
1685
- padding: 0 12px 12px;
1686
- }
1687
-
1688
- .composer-col {
1689
- max-width: 760px;
1690
- margin: 0 auto;
1691
- display: flex;
1692
- flex-direction: column;
1693
- gap: 8px;
1694
- }
1695
-
1696
- .composer-box {
1697
- position: relative;
1698
- }
1699
-
1700
- .composer {
1701
- position: relative;
1702
- z-index: 1;
1703
- display: flex;
1704
- flex-direction: column;
1705
- gap: 4px;
1706
- padding: 8px;
1707
- border-radius: calc(var(--c-r) * 2.25);
1708
- background: var(--c-bg);
1709
- border: 1px solid var(--c-strong);
1710
- box-shadow:
1711
- 0 1px 2px rgba(22, 24, 26, 0.04),
1712
- 0 12px 32px -18px rgba(22, 24, 26, 0.22);
1713
- transition: border-color 0.15s;
1714
- }
1715
-
1716
- .composer:focus-within {
1717
- border-color: var(--c-ink);
1718
- }
1719
-
1720
- .composer.busy {
1721
- border-color: transparent;
1722
- }
1723
-
1724
- :host([glow="off"]) .composer.busy {
1725
- border-color: var(--c-strong);
1726
- }
1727
-
1728
- .composer textarea {
1729
- width: 100%;
1730
- resize: none;
1731
- font: inherit;
1732
- font-size: 14.5px;
1733
- line-height: 1.5;
1734
- color: var(--c-ink);
1735
- background: transparent;
1736
- border: none;
1737
- outline: none;
1738
- padding: 6px 6px 2px;
1739
- max-height: 176px;
1740
- }
1741
-
1742
- .composer textarea::placeholder {
1743
- color: var(--c-faint);
1744
- }
1745
-
1746
- .composer-row {
1747
- display: flex;
1748
- align-items: center;
1749
- justify-content: space-between;
1750
- gap: 8px;
1751
- }
1752
-
1753
- .attach {
1754
- display: inline-flex;
1755
- align-items: center;
1756
- gap: 6px;
1757
- font-size: 12.5px;
1758
- color: var(--c-muted);
1759
- background: none;
1760
- border: none;
1761
- border-radius: var(--c-r);
1762
- padding: 6px 8px;
1763
- cursor: pointer;
1764
- }
1765
-
1766
- .attach:hover {
1767
- background: var(--c-hover);
1768
- color: var(--c-ink);
1769
- }
1770
-
1771
- .send {
1772
- display: inline-flex;
1773
- align-items: center;
1774
- justify-content: center;
1775
- width: 32px;
1776
- height: 32px;
1777
- padding: 0;
1778
- border-radius: var(--c-r2);
1779
- border: 1px solid var(--c-brand);
1780
- cursor: pointer;
1781
- background: var(--c-brand);
1782
- color: var(--c-on-brand);
1783
- transition: background 0.15s;
1784
- }
1785
-
1786
- .send:disabled {
1787
- cursor: default;
1788
- background: var(--c-line);
1789
- border-color: var(--c-line);
1790
- color: var(--c-faint);
1791
- }
1792
-
1793
- .send.stop {
1794
- background: var(--c-bg);
1795
- color: var(--c-ink);
1796
- border-color: var(--c-ink);
1797
- }
1798
-
1799
- .send.stop svg {
1800
- fill: currentColor;
1801
- stroke: none;
1802
- }
1803
-
1804
- .pending-files {
1805
- display: flex;
1806
- flex-wrap: wrap;
1807
- gap: 6px;
1808
- padding: 2px 2px 4px;
1809
- }
1810
-
1811
- .pending-file {
1812
- display: inline-flex;
1813
- align-items: center;
1814
- gap: 8px;
1815
- padding: 4px 8px 4px 4px;
1816
- font-size: 12.5px;
1817
- border-radius: var(--c-r2);
1818
- border: 1px solid var(--c-line);
1819
- background: var(--c-bg2);
1820
- animation: aiIn 0.2s ease-out;
1821
- }
1822
-
1823
- .pending-file .ext {
1824
- width: 28px;
1825
- height: 28px;
1826
- display: inline-flex;
1827
- align-items: center;
1828
- justify-content: center;
1829
- border-radius: var(--c-r);
1830
- background: var(--c-bg);
1831
- border: 1px solid var(--c-line);
1832
- font-family: var(--c-mono);
1833
- font-size: 9px;
1834
- letter-spacing: 0.03em;
1835
- color: var(--c-muted);
1836
- }
1837
-
1838
- .pending-file .meta {
1839
- display: flex;
1840
- flex-direction: column;
1841
- gap: 1px;
1842
- min-width: 0;
1843
- }
1844
-
1845
- .pending-file .name {
1846
- max-width: 160px;
1847
- overflow: hidden;
1848
- text-overflow: ellipsis;
1849
- white-space: nowrap;
1850
- }
1851
-
1852
- .pending-file .size {
1853
- font-family: var(--c-mono);
1854
- font-size: 10.5px;
1855
- color: var(--c-muted);
1856
- }
1857
-
1858
- .pending-file button {
1859
- font-size: 15px;
1860
- line-height: 1;
1861
- color: var(--c-muted);
1862
- background: none;
1863
- border: none;
1864
- padding: 0 0 0 2px;
1865
- cursor: pointer;
1866
- }
1867
-
1868
- .pending-file button:hover {
1869
- color: var(--c-danger);
1870
- }
1871
-
1872
- .footnote,
1873
- .branding {
1874
- text-align: center;
1875
- font-size: 11.5px;
1876
- color: var(--c-muted);
1877
- }
1878
-
1879
- .branding {
1880
- padding: 0 12px 10px;
1881
- margin-top: -4px;
1882
- }
1883
-
1884
- .branding a {
1885
- font-family: var(--c-mono);
1886
- font-size: 10.5px;
1887
- letter-spacing: 0.06em;
1888
- text-transform: uppercase;
1889
- color: var(--c-muted);
1890
- text-decoration: none;
1891
- }
1892
-
1893
- .branding a:hover {
1894
- color: var(--c-ink);
1895
- }
1896
-
1897
- .toast {
1898
- position: absolute;
1899
- left: 50%;
1900
- bottom: 124px;
1901
- transform: translateX(-50%);
1902
- z-index: 35;
1903
- display: flex;
1904
- align-items: center;
1905
- gap: 14px;
1906
- padding: 9px 14px;
1907
- background: var(--c-ink);
1908
- color: var(--c-bg);
1909
- font-size: 13px;
1910
- border-radius: var(--c-r2);
1911
- box-shadow: 0 12px 32px -12px rgba(22, 24, 26, 0.25);
1912
- white-space: nowrap;
1913
- animation: aiIn 0.2s ease-out;
1914
- }
1915
-
1916
- .toast button {
1917
- font-size: 13px;
1918
- font-weight: 500;
1919
- color: var(--c-bg);
1920
- background: none;
1921
- border: none;
1922
- padding: 0;
1923
- cursor: pointer;
1924
- text-decoration: underline;
1925
- text-underline-offset: 3px;
1926
- }
1927
-
1928
- .drop {
1929
- position: absolute;
1930
- inset: 10px;
1931
- z-index: 36;
1932
- display: flex;
1933
- flex-direction: column;
1934
- align-items: center;
1935
- justify-content: center;
1936
- gap: 6px;
1937
- text-align: center;
1938
- padding: 16px;
1939
- border: 1.5px dashed var(--c-ink);
1940
- border-radius: var(--c-r3);
1941
- background: color-mix(in srgb, var(--c-bg) 92%, transparent);
1942
- }
1943
-
1944
- .drop strong {
1945
- font-size: 15px;
1946
- font-weight: 600;
1947
- }
1948
-
1949
- .drop span {
1950
- font-size: 12.5px;
1951
- color: var(--c-muted);
1952
- }
1953
-
1954
- /* ── AI glow ──────────────────────────────────────────── */
1955
-
1956
- .halo {
1957
- position: absolute;
1958
- inset: -18px -24px;
1959
- z-index: 0;
1960
- pointer-events: none;
1961
- opacity: var(--c-glow);
1962
- }
1963
-
1964
- .halo::before {
1965
- content: "";
1966
- position: absolute;
1967
- inset: 0;
1968
- border-radius: 20px;
1969
- background: var(--c-conic);
1970
- filter: blur(32px);
1971
- opacity: 0.45;
1972
- animation:
1973
- aiSpin 5s linear infinite,
1974
- aiBreathe 2.6s ease-in-out infinite;
1975
- }
1976
-
1977
- .arrived {
1978
- position: absolute;
1979
- inset: -12px -16px;
1980
- z-index: 0;
1981
- pointer-events: none;
1982
- border-radius: var(--c-r4);
1983
- animation: aiDone 2.6s ease-out forwards;
1984
- }
1985
-
1986
- .arrived .wash {
1987
- position: absolute;
1988
- inset: 0;
1989
- border-radius: inherit;
1990
- background: var(--c-conic);
1991
- filter: blur(26px);
1992
- opacity: calc(0.22 * var(--c-glow) + 0.06);
1993
- animation: aiSpin 2.6s linear infinite;
1994
- }
1995
-
1996
- .ring {
1997
- position: absolute;
1998
- inset: 0;
1999
- border-radius: inherit;
2000
- padding: 1px;
2001
- background: var(--c-conic);
2002
- -webkit-mask:
2003
- linear-gradient(#000 0 0) content-box,
2004
- linear-gradient(#000 0 0);
2005
- -webkit-mask-composite: xor;
2006
- mask-composite: exclude;
2007
- animation: aiSpin 2.6s linear infinite;
2008
- pointer-events: none;
2009
- }
2010
-
2011
- .arrived .sweep {
2012
- position: absolute;
2013
- inset: 0;
2014
- border-radius: inherit;
2015
- overflow: hidden;
2016
- }
2017
-
2018
- .arrived .sweep::before {
2019
- content: "";
2020
- position: absolute;
2021
- inset: 0;
2022
- background: linear-gradient(
2023
- 100deg,
2024
- transparent 25%,
2025
- oklch(0.88 0.07 260 / 0.5) 50%,
2026
- transparent 75%
2027
- );
2028
- animation: aiSweep 1.6s cubic-bezier(0.3, 0.6, 0.3, 1) forwards;
2029
- }
2030
-
2031
- .pill {
2032
- position: relative;
2033
- display: inline-flex;
2034
- align-self: flex-start;
2035
- align-items: center;
2036
- gap: 9px;
2037
- padding: 6px 14px 6px 10px;
2038
- border-radius: 999px;
2039
- background: var(--c-bg);
2040
- box-shadow: 0 0 24px -6px oklch(0.7 0.15 280 / 0.5);
2041
- animation: aiIn 0.25s ease-out;
2042
- }
2043
-
2044
- .pill .ring {
2045
- border-radius: 999px;
2046
- animation-duration: 2.4s;
2047
- }
2048
-
2049
- .pill .dot {
2050
- width: 9px;
2051
- height: 9px;
2052
- border-radius: 50%;
2053
- background: var(--c-conic);
2054
- animation:
2055
- aiSpin 1.6s linear infinite,
2056
- aiPulse 1.6s ease-in-out infinite;
2057
- }
2058
-
2059
- .pill .shimmer {
2060
- font-size: 12.5px;
2061
- font-weight: 500;
2062
- background: linear-gradient(90deg, var(--c-faint) 0%, var(--c-ink) 45%, var(--c-faint) 90%);
2063
- background-size: 200% 100%;
2064
- -webkit-background-clip: text;
2065
- background-clip: text;
2066
- color: transparent;
2067
- animation: aiShimmer 1.8s linear infinite;
2068
- }
2069
-
2070
- .composer-glow {
2071
- position: absolute;
2072
- inset: -4px;
2073
- z-index: 0;
2074
- border-radius: var(--c-r4);
2075
- background: var(--c-conic);
2076
- filter: blur(14px);
2077
- opacity: calc(0.32 + 0.23 * (var(--c-glow) - 0.6) / 0.4);
2078
- animation: aiSpin 4s linear infinite;
2079
- pointer-events: none;
2080
- }
2081
-
2082
- .composer-ring {
2083
- position: absolute;
2084
- inset: 0;
2085
- z-index: 2;
2086
- border-radius: calc(var(--c-r) * 2.25);
2087
- pointer-events: none;
2088
- }
2089
-
2090
- .composer-ring .ring {
2091
- animation-duration: 3s;
2092
- }
2093
-
2094
- :host([glow="off"]) .halo,
2095
- :host([glow="off"]) .arrived,
2096
- :host([glow="off"]) .composer-glow,
2097
- :host([glow="off"]) .composer-ring,
2098
- :host([glow="off"]) .pill .ring {
2099
- display: none;
2100
- }
2101
-
2102
- :host([glow="off"]) .pill {
2103
- box-shadow: inset 0 0 0 1px var(--c-line);
2104
- }
2105
-
2106
- :host([glow="off"]) .pill .dot {
2107
- background: var(--c-ink);
2108
- }
2109
-
2110
- @keyframes aiSpin {
2111
- to {
2112
- --sb-ai-angle: 360deg;
2113
- }
2114
- }
2115
-
2116
- @keyframes aiShimmer {
2117
- from {
2118
- background-position: 200% 0;
2119
- }
2120
- to {
2121
- background-position: -200% 0;
2122
- }
2123
- }
2124
-
2125
- @keyframes aiBreathe {
2126
- 0%,
2127
- 100% {
2128
- transform: scale(0.97);
2129
- }
2130
- 50% {
2131
- transform: scale(1.03);
2132
- }
2133
- }
2134
-
2135
- @keyframes aiPulse {
2136
- 0%,
2137
- 100% {
2138
- transform: scale(0.8);
2139
- }
2140
- 50% {
2141
- transform: scale(1.15);
2142
- }
2143
- }
2144
-
2145
- @keyframes aiDone {
2146
- 0% {
2147
- opacity: 0;
2148
- }
2149
- 12% {
2150
- opacity: 1;
2151
- }
2152
- 100% {
2153
- opacity: 0;
2154
- }
2155
- }
2156
-
2157
- @keyframes aiSweep {
2158
- from {
2159
- transform: translateX(-100%);
2160
- }
2161
- to {
2162
- transform: translateX(100%);
2163
- }
2164
- }
2165
-
2166
- @keyframes aiIn {
2167
- from {
2168
- opacity: 0;
2169
- transform: translateY(4px);
2170
- }
2171
- to {
2172
- opacity: 1;
2173
- transform: none;
2174
- }
2175
- }
2176
-
2177
- @keyframes scaleIn {
2178
- from {
2179
- opacity: 0;
2180
- transform: translateY(12px) scale(0.98);
2181
- }
2182
- to {
2183
- opacity: 1;
2184
- transform: none;
2185
- }
2186
- }
2187
-
2188
- @keyframes slideIn {
2189
- from {
2190
- opacity: 0;
2191
- transform: translateX(-8px);
2192
- }
2193
- to {
2194
- opacity: 1;
2195
- transform: none;
2196
- }
2197
- }
2198
-
2199
- @keyframes aiGrow {
2200
- from {
2201
- transform: scaleX(0);
2202
- }
2203
- }
2204
-
2205
- @keyframes aiDraw {
2206
- from {
2207
- stroke-dashoffset: 1;
2208
- }
2209
- to {
2210
- stroke-dashoffset: 0;
2211
- }
2212
- }
2213
-
2214
- @keyframes rgcaret {
2215
- 0%,
2216
- 100% {
2217
- opacity: 1;
2218
- }
2219
- 50% {
2220
- opacity: 0;
2221
- }
2222
- }
2223
-
2224
- @media (prefers-reduced-motion: reduce) {
2225
- *,
2226
- *::before,
2227
- *::after {
2228
- animation-duration: 0.01ms !important;
2229
- animation-iteration-count: 1 !important;
2230
- }
2231
- .caret {
2232
- display: none;
2233
- }
2234
- }
2235
-
2236
- @media print {
2237
- .sidebar,
2238
- .scrim,
2239
- .header-right,
2240
- .composer-wrap,
2241
- .branding,
2242
- .toolbar,
2243
- .followups,
2244
- .panel,
2245
- .toast {
2246
- display: none !important;
2247
- }
2248
- .frame,
2249
- .scroller {
2250
- overflow: visible;
2251
- height: auto;
2252
- }
2253
- }
2254
- `,ot={eyebrowChat:"Chat",eyebrowRag:"Grounded answers",eyebrowRich:"Charts · tables · images",headingChat:"What can I help with?",headingRag:"Ask your knowledge base",headingRich:"Ask for a chart or a table",descriptionChat:"Ask anything. Attach text files to give it more context.",descriptionRag:"Answers are grounded in your sources, with a citation for every claim. Attach text files to search them too.",descriptionRich:"Answers come back with charts, tables and images when they help. Attach CSV or JSON files to use your own data.",placeholderChat:"Message {name}…",placeholderRag:"Ask about your sources…",placeholderRich:"Ask for a chart, table or breakdown…",footnote:"{name} can make mistakes. Check important details.",attach:"Attach files",send:"Send message",stop:"Stop generating",removeFile:"Remove file",dropTitle:"Drop files to attach",dropSub:"Text, Markdown, CSV and JSON files are added as context.",thinking:"Thinking",searching:"Searching sources",building:"Building charts and tables",chats:"Chats",newChat:"New chat",searchChats:"Search chats",groupBookmarked:"Bookmarked",groupToday:"Today",groupYesterday:"Yesterday",groupWeek:"Previous 7 days",groupOlder:"Older",noChats:"No chats yet.",noMatch:"No chats match “{query}”.",loadingChats:"Loading chats",showChats:"Show chats",hideSidebar:"Hide sidebar",untitled:"New chat",renameChat:"Rename chat",bookmarkChat:"Bookmark chat",unbookmarkChat:"Remove chat bookmark",exportChat:"Export chat",deleteChat:"Delete chat",expand:"Expand",restore:"Restore size",minimize:"Minimize chat",exportHeading:"Export this chat",exportMarkdown:"Markdown",exportJson:"JSON",exportText:"Plain text",exportCopy:"Copy as Markdown",copy:"Copy",copied:"Copied",edit:"Edit and resend",saveResend:"Save & resend",cancel:"Cancel",regenerate:"Regenerate",helpful:"Helpful",notHelpful:"Not helpful",markedHelpful:"Marked helpful",thanksFeedback:"Thanks for the feedback",bookmarkMessage:"Bookmark message",unbookmarkMessage:"Remove bookmark",deleteMessage:"Delete message",saved:"Saved",stopped:"Stopped",emptyReply:"(empty response)",newReply:"New reply",you:"You",sourcesCited:"Cited sources",sourcesRetrieved:"Sources",searchedSources:"Searched {n} sources",sourceLabel:"Source {n}",openSource:"Open source {n}",citedPassage:"Cited passage",copyReference:"Copy passage with reference",alsoCited:"Also cited",close:"Close",undo:"Undo",chatDeleted:"Chat deleted",messageDeleted:"Message deleted",messageBookmarked:"Message bookmarked",bookmarkRemoved:"Bookmark removed",chatBookmarked:"Chat bookmarked",chatUnbookmarked:"Chat removed from bookmarks",exported:"Exported {name}",copiedMarkdown:"Copied as Markdown",fileTooLarge:"{name} is larger than {size}.",fileType:"{name} isn't a text file.",tooManyFiles:"Attach up to {n} files at a time.",errGeneric:"Something went wrong.",errNotFound:"This chat no longer exists. Retry to start a new one.",errNoClient:"Chat isn't connected. Create a SinglebaseClient() on this page.",errLoad:"Couldn't load this chat.",retry:"Retry",offline:"You're offline. Messages will send when you reconnect.",bubbleText:"Hi! Questions? Ask me here.",openChat:"Open chat",closeChat:"Close chat",dismiss:"Dismiss",brandingLabel:"Chat by Singlebase"};function lt(o){return{...ot,...o??{}}}const yt=/^\|.*\|$/,kt=/^\|[\s:|-]+\|$/,Ge=/^!\[([^\]]*)\]\(([^)]*)\)$/,Ve=/^([-*]|\d+\.)\s+/;function ct(o){const n=[],e=(o??"").replace(/\r/g,"").split("```");return e.forEach((t,i)=>{if(i%2===1){const a=t.indexOf(`
2255
- `),r=(a>-1?t.slice(0,a):t).trim().toLowerCase(),l=(a>-1?t.slice(a+1):"").replace(/\n$/,""),c=i===e.length-1;if(r==="chart"){const m=c?null:wt(l);n.push(m?{type:"chart",spec:m}:{type:"chartPending"})}else n.push({type:"code",lang:r||"code",text:l});return}for(const a of t.split(/\n{2,}/)){const r=a.trim();r&&n.push(...dt(r))}}),n}function dt(o){const n=o.split(`
2256
- `).map(t=>t.trim()).filter(Boolean);if(n.length>1&&n.every(t=>yt.test(t))){const t=n.filter(i=>!kt.test(i)).map(i=>i.replace(/^\||\|$/g,"").split("|").map(a=>a.trim()));return[{type:"table",head:t[0]??[],rows:t.slice(1)}]}if(n.every(t=>Ge.test(t)))return[{type:"img",images:n.map(t=>{const i=t.match(Ge);return{alt:i[1],src:i[2]}})}];if(n.every(t=>t.startsWith(">")))return[{type:"quote",text:n.map(t=>t.replace(/^>\s?/,"")).join(" ")}];if(n.every(t=>Ve.test(t)))return[{type:"list",ordered:/^\d+\./.test(n[0]),items:n.map(t=>t.replace(Ve,""))}];const e=n[0].match(/^(#{1,4})\s+(.*)$/);if(e){const t=n.slice(1).join(`
2257
- `);return[{type:"h",level:e[1].length,text:e[2]},...t?dt(t):[]]}return[{type:"p",text:n.join(" ")}]}function wt(o){let n;try{n=JSON.parse(o)}catch{return null}if(!n||typeof n!="object")return null;const e=(Array.isArray(n.series)?n.series:[]).filter(i=>i&&Array.isArray(i.values)).map((i,a)=>({name:String(i.name??`Series ${a+1}`),values:i.values.map(r=>Number(r)||0)}));if(!e.length)return null;const t=Array.isArray(n.labels)?n.labels.map(String):e[0].values.map((i,a)=>String(a+1));return{type:n.type==="line"?"line":"bar",title:String(n.title??""),unit:String(n.unit??""),labels:t,series:e}}const Xe=/\*\*([^*]+)\*\*|`([^`]+)`|\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)|\s?\[(\d+(?:\s*,\s*\d+)*)\]/g;function pt(o,n=0){const e=[];let t=0,i;Xe.lastIndex=0;const a=r=>{if(!r)return;const l=e[e.length-1];(l==null?void 0:l.type)==="text"?l.text+=r:e.push({type:"text",text:r})};for(;i=Xe.exec(o);){if(a(o.slice(t,i.index)),i[1]!==void 0)e.push({type:"bold",text:i[1]});else if(i[2]!==void 0)e.push({type:"code",text:i[2]});else if(i[3]!==void 0)e.push({type:"link",text:i[3],href:i[4]});else{const l=i[5].split(",").map(c=>Number(c.trim())).filter(c=>c>=1&&c<=n);n?l.forEach(c=>e.push({type:"cite",n:c})):a(i[0])}t=i.index+i[0].length}return a(o.slice(t)),e}function Pe(o){const n=new Set;for(const e of(o??"").match(/\[(\d+(?:\s*,\s*\d+)*)\]/g)??[])e.replace(/[[\]]/g,"").split(",").forEach(t=>n.add(Number(t.trim())));return n}function Ye(o){return{head:["",...o.series.map(n=>n.name)],rows:o.labels.map((n,e)=>[n,...o.series.map(t=>t.values[e]===void 0?"":`${t.values[e]}${o.unit}`)])}}const Fe=o=>o.replace(/\*\*/g,"").replace(/`/g,"").replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g,"$1");function ht(o,n){if(n==="markdown")return o.flatMap(e=>{if(e.type==="chart"){const t=Ye(e.spec);return[...e.spec.title?[{type:"p",text:`**${e.spec.title}**`}]:[],{type:"table",...t}]}return e.type==="img"?e.images.map(t=>({type:"p",text:`Image: ${t.alt||"untitled"}`})):[e]});if(n==="text"){const e=o.map(t=>{switch(t.type){case"chart":{const i=Ye(t.spec);return[t.spec.title,...[i.head,...i.rows].map(a=>a.join(" · "))].filter(Boolean).join(`
2258
- `)}case"chartPending":return"";case"img":return t.images.map(i=>`Image: ${i.alt||"untitled"}`).join(`
2259
- `);case"table":return[t.head,...t.rows].map(i=>i.map(Fe).join(" · ")).join(`
2260
- `);case"list":return t.items.map(i=>`- ${Fe(i)}`).join(`
2261
- `);case"code":case"raw":return t.text;default:return Fe(t.text)}}).filter(Boolean).join(`
2262
-
2263
- `);return e?[{type:"raw",text:e}]:[]}return o}function He(o){const n=o??"",e=n.search(/FOLLOWUPS:/i);if(e<0)return{text:n.trim(),followups:[]};const i=n.slice(e).replace(/^FOLLOWUPS:/i,"").split(/\||\n/).map(a=>a.replace(/^\s*(?:[-*↳→]|\d+[.)])\s*/,"").trim()).filter(Boolean).slice(0,3);return{text:n.slice(0,e).trim(),followups:i}}function $t(o){return(o??"").replace(/```(\w*)[\s\S]*?(```|$)/g,(n,e)=>e==="chart"?"[Chart] ":"[Code] ").replace(/!\[([^\]]*)\]\([^)]*\)/g,"[Image: $1]").replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g,"$1").replace(/[*#>`]/g,"").replace(/\|/g," ").replace(/\s?\[\d+(?:\s*,\s*\d+)*\]/g,"").replace(/\s+/g," ").trim()}function Ct(o,n=48){const e=$t(o);if(e.length<=n)return e;const t=e.slice(0,n),i=t.lastIndexOf(" ");return(i>n/2?t.slice(0,i):t).trim()}function St(o){return String(o??"").split(`
2264
- `)[0].trim().replace(/^["'“”‘’]+|["'“”‘’]+$/g,"").replace(/^title:\s*/i,"").replace(/[.!?:;,]+$/,"").trim().slice(0,80)}function Qe(o,n=!1){return/^https?:\/\//i.test(o)?!0:n&&/^(blob:|data:image\/)/i.test(o)}var ut=Object.defineProperty,Tt=Object.getOwnPropertyDescriptor,zt=(o,n,e)=>n in o?ut(o,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):o[n]=e,g=(o,n,e,t)=>{for(var i=t>1?void 0:t?Tt(n,e):n,a=o.length-1,r;a>=0;a--)(r=o[a])&&(i=(t?r(n,e,i):r(i))||i);return t&&i&&ut(n,e,i),i},Mt=(o,n,e)=>zt(o,n+"",e);const Ze=["embed","mode","renderAs","glow","position","sidebar","showTitle","assistantName","logoUrl","heading","description","prompts","bubbleText","greetingBubble","unreadBadge","allowUpload","allowExport","branding","followups","autoTitle","model","params","systemMessage","retrieval","metadata","messages","theme"],Je={fromAttribute:o=>{if(o)try{return JSON.parse(o)}catch{console.warn("[singlebase-chat] an attribute holds invalid JSON; ignoring it");return}},toAttribute:o=>JSON.stringify(o??null)},M={fromAttribute:o=>o===null?!0:o!=="false",toAttribute:o=>o?null:"false"},Ot={fromAttribute:o=>o===null?void 0:o!=="false",toAttribute:o=>o===void 0?null:String(o)},_t=272,It=820,Lt=940,et=5,tt=512*1024,jt=/\.(md|markdown|txt|csv|tsv|json|html?|ya?ml|xml|log)$/i,At=5e3,Et=2600,z=["var(--c-ink)","oklch(0.58 0.13 255)","oklch(0.63 0.1 175)","oklch(0.74 0.12 70)"],it={chat:"Be helpful and concise. Use Markdown when it helps: headings, lists, **bold**, code blocks and tables.",rag:"Answer ONLY from the sources provided with each message, numbered in the order given. Put a citation like [1] right after each claim it supports. If the sources don't cover the question, say so plainly.",rich:'Lead with one sentence stating the key finding, with key numbers in **bold**. For trends and comparisons, include a chart as a fenced code block with the language "chart" containing only JSON: {"type":"bar"|"line","title":string,"unit":string,"labels":[string],"series":[{"name":string,"values":[number]}]}. Use Markdown tables for exact values. Keep prose short.'},Nt="After the answer, on a final line write FOLLOWUPS: followed by three short follow-up questions the user might ask next, separated by |.",st={chat:[["Write","Draft a short welcome email for new users"],["Explain","Explain how refresh tokens work, simply"],["Code","Write a JavaScript debounce function"],["Plan","Outline a one-week plan to learn TypeScript"]],rag:[["Overview","What topics do these sources cover?"],["Summarize","Summarize the most important points"],["Find","Where is the refund policy described?"],["Explain","Explain the setup steps in plain language"]],rich:[["Bar chart","Compare the five most spoken languages in a bar chart"],["Line chart","Show world population from 1950 to 2020"],["Table","List the planets with their diameters in a table"],["Breakdown","Break down a $4,000 monthly budget by category"]]},w=(o,n="")=>s.html`<svg class="i ${n}" viewBox="0 0 16 16" aria-hidden="true">${o}</svg>`,v={sidebar:()=>w(s.svg`<rect x="2" y="2.5" width="12" height="11" rx="1.5"></rect><path d="M6 2.5v11"></path>`),plus:()=>w(s.svg`<path d="M8 3v10M3 8h10"></path>`),bookmark:(o=!1)=>w(s.svg`<path d="M4.5 2.5h7v11L8 11l-3.5 2.5z"></path>`,o?"filled":""),download:()=>w(s.svg`<path d="M8 2.5v8M4.5 7.5L8 11l3.5-3.5M2.5 13.5h11"></path>`),trash:()=>w(s.svg`<path d="M2.5 4.5h11M6.5 4.5v-2h3v2M4 4.5l.7 9h6.6l.7-9"></path>`),pencil:()=>w(s.svg`<path d="M10.5 2.5l3 3L6 13H3v-3z"></path>`),copy:()=>w(s.svg`<rect x="5.5" y="5.5" width="8" height="8" rx="1.5"></rect><path d="M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2"></path>`),refresh:()=>w(s.svg`<path d="M13.5 8A5.5 5.5 0 1 1 11.9 4.1M13.5 2v3.5H10"></path>`),thumb:(o=!1)=>s.html`<svg
2265
- class="i"
2266
- viewBox="0 0 16 16"
2267
- aria-hidden="true"
2268
- style=${o?"transform:rotate(180deg)":""}
2269
- >
2270
- <path
2271
- d="M5 7v6.5H2.5V7zM5 7l2.5-4.5a1.3 1.3 0 0 1 1.9 1.4L9 6.5h3.6a1 1 0 0 1 1 1.2l-1 4.8a1 1 0 0 1-1 .8H5"
2272
- ></path>
2273
- </svg>`,expand:()=>w(s.svg`<path d="M9.5 2.5h4v4M13.5 2.5L9 7M6.5 13.5h-4v-4M2.5 13.5L7 9"></path>`),restore:()=>w(s.svg`<path d="M13.5 6.5h-4v-4M9.5 6.5l4-4M2.5 9.5h4v4M6.5 9.5l-4 4"></path>`),minimize:()=>w(s.svg`<path d="M4 8h8"></path>`),close:()=>w(s.svg`<path d="M4 4l8 8M12 4l-8 8"></path>`),clip:()=>w(s.svg`<path d="M13 7.5l-5.3 5.3a3 3 0 0 1-4.3-4.3L9 2.9a2 2 0 0 1 2.9 2.9L6.4 11.3a1 1 0 0 1-1.4-1.4L10 5"></path>`),up:()=>w(s.svg`<path d="M8 13V3M3.5 7.5L8 3l4.5 4.5"></path>`),stop:()=>w(s.svg`<rect x="4.5" y="4.5" width="7" height="7" rx="1"></rect>`),chat:()=>s.html`<svg
2274
- width="22"
2275
- height="22"
2276
- viewBox="0 0 22 22"
2277
- aria-hidden="true"
2278
- style="fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round"
2279
- >
2280
- <path
2281
- d="M4 5.5A2.5 2.5 0 0 1 6.5 3h9A2.5 2.5 0 0 1 18 5.5v7a2.5 2.5 0 0 1-2.5 2.5H9l-4 3.5V15H6.5"
2282
- ></path>
2283
- </svg>`,chevronDown:()=>s.html`<svg
2284
- width="20"
2285
- height="20"
2286
- viewBox="0 0 20 20"
2287
- aria-hidden="true"
2288
- style="fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round"
2289
- >
2290
- <path d="M5 8l5 5 5-5"></path>
2291
- </svg>`};let Bt=0;const Ke=()=>`m${Date.now().toString(36)}${(Bt++).toString(36)}`;function at(o){var e;const n=o;return(n==null?void 0:n.message)==="NOT_FOUND"||(n==null?void 0:n.code)==="NOT_FOUND"||((e=n==null?void 0:n.details)==null?void 0:e.status)===404}function Dt(o){const n=o;return(n==null?void 0:n.code)||(n==null?void 0:n.message)||"UNKNOWN"}const Rt=()=>typeof matchMedia<"u"&&matchMedia("(prefers-reduced-motion: reduce)").matches,Re=(o,n)=>(Number.isInteger(o)?o.toLocaleString("en-US"):o.toFixed(1))+n,rt=o=>{const n=o.lastIndexOf(".");return n>0?o.slice(n+1,n+5).toUpperCase():"FILE"};function _(o,n){const e=o??{},t=e.metadata&&typeof e.metadata=="object"?e.metadata:{},i=(...l)=>l.find(c=>typeof c=="string"&&c.trim()),a=i(e.content,e.text,e.page_content,e.body,e.snippet,e.chunk,t.content)??JSON.stringify(e,null,2),r=[e.score,e.relevance,e._score,t.score].find(l=>typeof l=="number");return{n,title:i(e.title,e.name,e.filename,t.title,t.name)??`Source ${n}`,path:i(e.path,e.url,e.key,e.source,t.path,t.url)??"",collection:i(e.collection,e.namespace,e.dbname,t.collection)??"",updated:i(e.updated,e._modified_at,t.updated)??"",text:a,score:r===void 0?null:Math.max(0,Math.min(1,r))}}function Ut(o){const n=[],e=[];for(const t of o)if(/\.csv$/i.test(t.name))n.push({type:"csv",data:t.content});else if(/\.json$/i.test(t.name))try{n.push({type:"json",data:JSON.parse(t.content)})}catch{e.push({title:t.name,content:t.content})}else e.push({title:t.name,content:t.content});return e.length&&n.push({type:"docs",payload:{documents:e}}),n}function Ue(o){const n=o?Date.parse(o):NaN;if(Number.isNaN(n))return"older";const e=new Date;e.setHours(0,0,0,0);const t=864e5;return n>=e.getTime()?"today":n>=e.getTime()-t?"yesterday":n>=e.getTime()-7*t?"week":"older"}var I,L,j,A,E,N,B,D,R,U,F,K,P,H,J,W,q,G,V,X,Y,Q,Z,ee,te,ie,se,ae,re,ne,oe,le,ce,de,pe,he,ue,ge,me,be,fe,xe,ve,ye,ke,we,$e,Ce,Se,Te,ze,Me,Oe,_e,Ie,Le,je,Ae,Ee,Ne,Be,nt;exports.SinglebaseChat=(nt=class extends s.LitElement{constructor(){super(...arguments);p(this,I,null);p(this,L,{});p(this,j);p(this,A,"chat");p(this,E,"rich");p(this,N,"subtle");p(this,B,!0);p(this,D,!0);p(this,R,"");p(this,U,{});p(this,F,"");p(this,K,[]);p(this,P,{});p(this,H,"page");p(this,J,"right");p(this,W);p(this,q,!0);p(this,G,"");p(this,V,"Assistant");p(this,X,"");p(this,Y,"");p(this,Q,"");p(this,Z,"");p(this,ee,"");p(this,te,!1);p(this,ie,!1);p(this,se,!0);p(this,ae,!0);p(this,re,!0);p(this,ne,[]);p(this,oe,"idle");p(this,le,null);p(this,ce,"");p(this,de,!1);p(this,pe,[]);p(this,he,!1);p(this,ue,"");p(this,ge,!1);p(this,me,"");p(this,be,[]);p(this,fe,"");p(this,xe,null);p(this,ve,0);p(this,ye,null);p(this,ke,!1);p(this,we,"");p(this,$e,"");p(this,Ce,!1);p(this,Se,"");p(this,Te,null);p(this,ze,"");p(this,Me,new Set);p(this,Oe,"");p(this,_e,!1);p(this,Ie,!1);p(this,Le,!1);p(this,je,!1);p(this,Ae,!1);p(this,Ee,!1);p(this,Ne,!1);p(this,Be,!1);k(this,"run",0);k(this,"abort",null);k(this,"revealTimer");k(this,"timers",new Set);k(this,"toastTimer");k(this,"stick",!0);k(this,"renamed",new Set);k(this,"observer",null);k(this,"observed",null);k(this,"media",null);k(this,"focusNext","");k(this,"bubbleScheduled",!1);k(this,"onNetwork",()=>{this.offline=navigator.onLine===!1});k(this,"onMedia",()=>{var e;this.mobile=!!((e=this.media)!=null&&e.matches)})}get client(){return d(this,I)}set client(e){h(this,I,e)}get messages(){return d(this,L)}set messages(e){h(this,L,e)}get theme(){return d(this,j)}set theme(e){h(this,j,e)}get mode(){return d(this,A)}set mode(e){h(this,A,e)}get renderAs(){return d(this,E)}set renderAs(e){h(this,E,e)}get glow(){return d(this,N)}set glow(e){h(this,N,e)}get followups(){return d(this,B)}set followups(e){h(this,B,e)}get autoTitle(){return d(this,D)}set autoTitle(e){h(this,D,e)}get model(){return d(this,R)}set model(e){h(this,R,e)}get params(){return d(this,U)}set params(e){h(this,U,e)}get systemMessage(){return d(this,F)}set systemMessage(e){h(this,F,e)}get retrieval(){return d(this,K)}set retrieval(e){h(this,K,e)}get metadata(){return d(this,P)}set metadata(e){h(this,P,e)}get embed(){return d(this,H)}set embed(e){h(this,H,e)}get position(){return d(this,J)}set position(e){h(this,J,e)}get sidebar(){return d(this,W)}set sidebar(e){h(this,W,e)}get showTitle(){return d(this,q)}set showTitle(e){h(this,q,e)}get chatIdAttr(){return d(this,G)}set chatIdAttr(e){h(this,G,e)}get assistantName(){return d(this,V)}set assistantName(e){h(this,V,e)}get logoUrl(){return d(this,X)}set logoUrl(e){h(this,X,e)}get heading(){return d(this,Y)}set heading(e){h(this,Y,e)}get description(){return d(this,Q)}set description(e){h(this,Q,e)}get prompts(){return d(this,Z)}set prompts(e){h(this,Z,e)}get bubbleText(){return d(this,ee)}set bubbleText(e){h(this,ee,e)}get greetingBubble(){return d(this,te)}set greetingBubble(e){h(this,te,e)}get unreadBadge(){return d(this,ie)}set unreadBadge(e){h(this,ie,e)}get allowUpload(){return d(this,se)}set allowUpload(e){h(this,se,e)}get allowExport(){return d(this,ae)}set allowExport(e){h(this,ae,e)}get branding(){return d(this,re)}set branding(e){h(this,re,e)}get chatList(){return d(this,ne)}set chatList(e){h(this,ne,e)}get listState(){return d(this,oe)}set listState(e){h(this,oe,e)}get activeId(){return d(this,le)}set activeId(e){h(this,le,e)}get chatTitle(){return d(this,ce)}set chatTitle(e){h(this,ce,e)}get bookmarked(){return d(this,de)}set bookmarked(e){h(this,de,e)}get msgs(){return d(this,pe)}set msgs(e){h(this,pe,e)}get loadingThread(){return d(this,he)}set loadingThread(e){h(this,he,e)}get threadError(){return d(this,ue)}set threadError(e){h(this,ue,e)}get busy(){return d(this,ge)}set busy(e){h(this,ge,e)}get draft(){return d(this,me)}set draft(e){h(this,me,e)}get files(){return d(this,be)}set files(e){h(this,be,e)}get search(){return d(this,fe)}set search(e){h(this,fe,e)}get sidebarOpen(){return d(this,xe)}set sidebarOpen(e){h(this,xe,e)}get width(){return d(this,ve)}set width(e){h(this,ve,e)}get panel(){return d(this,ye)}set panel(e){h(this,ye,e)}get menuOpen(){return d(this,ke)}set menuOpen(e){h(this,ke,e)}get editingKey(){return d(this,we)}set editingKey(e){h(this,we,e)}get editDraft(){return d(this,$e)}set editDraft(e){h(this,$e,e)}get editingTitle(){return d(this,Ce)}set editingTitle(e){h(this,Ce,e)}get renamingId(){return d(this,Se)}set renamingId(e){h(this,Se,e)}get toast(){return d(this,Te)}set toast(e){h(this,Te,e)}get copiedKey(){return d(this,ze)}set copiedKey(e){h(this,ze,e)}get retrievalOpen(){return d(this,Me)}set retrievalOpen(e){h(this,Me,e)}get arrivedKey(){return d(this,Oe)}set arrivedKey(e){h(this,Oe,e)}get dragging(){return d(this,_e)}set dragging(e){h(this,_e,e)}get showJump(){return d(this,Ie)}set showJump(e){h(this,Ie,e)}get offline(){return d(this,Le)}set offline(e){h(this,Le,e)}get isOpen(){return d(this,je)}set isOpen(e){h(this,je,e)}get expanded(){return d(this,Ae)}set expanded(e){h(this,Ae,e)}get bubble(){return d(this,Ee)}set bubble(e){h(this,Ee,e)}get seen(){return d(this,Ne)}set seen(e){h(this,Ne,e)}get mobile(){return d(this,Be)}set mobile(e){h(this,Be,e)}get msg(){return lt(this.messages)}get resolvedClient(){return this.client??xt.getDefaultClient()??null}get chatId(){return this.activeId}get thread(){return this.msgs}get chats(){return this.chatList}set config(e){const t=this;for(const i of Ze)e&&i in e&&(t[i]=e[i])}get config(){const e=this;return Object.fromEntries(Ze.map(t=>[t,e[t]]))}connectedCallback(){var e,t;super.connectedCallback(),this.offline=typeof navigator<"u"&&navigator.onLine===!1,window.addEventListener("online",this.onNetwork),window.addEventListener("offline",this.onNetwork),this.media=typeof matchMedia<"u"?matchMedia("(max-width: 559px)"):null,this.mobile=!!((e=this.media)!=null&&e.matches),(t=this.media)==null||t.addEventListener("change",this.onMedia)}disconnectedCallback(){var e,t;super.disconnectedCallback(),window.removeEventListener("online",this.onNetwork),window.removeEventListener("offline",this.onNetwork),(e=this.media)==null||e.removeEventListener("change",this.onMedia),(t=this.observer)==null||t.disconnect(),this.observer=null,this.observed=null,this.flushToast(),this.halt(),this.timers.forEach(clearTimeout),this.timers.clear()}willUpdate(e){if(e.has("retrieval")&&!Array.isArray(this.retrieval)){const t=this.retrieval;this.retrieval=t&&typeof t=="object"?[t]:[]}e.has("params")&&(!this.params||typeof this.params!="object")&&(this.params={}),e.has("metadata")&&(!this.metadata||typeof this.metadata!="object")&&(this.metadata={}),e.has("sidebar")&&this.sidebar!==void 0&&(this.sidebarOpen=this.sidebar),this.embed==="launcher"&&this.greetingBubble&&!this.bubbleScheduled&&(this.bubbleScheduled=!0,this.later(()=>{!this.isOpen&&!this.seen&&(this.bubble=!0)},1200))}firstUpdated(){this.chatIdAttr&&this.openChat(this.chatIdAttr)}updated(){var t;const e=this.renderRoot.querySelector(".root");if(e!==this.observed&&((t=this.observer)==null||t.disconnect(),this.observed=e,e&&typeof ResizeObserver<"u"&&(this.observer??(this.observer=new ResizeObserver(([i])=>{const a=Math.round(i.contentRect.width);a!==this.width&&(this.width=a,this.sidebarOpen===null&&(this.sidebarOpen=this.sidebar??this.docked))})),this.observer.observe(e))),this.sidebarOpen&&this.listState==="idle"&&this.resolvedClient&&this.loadChats(),this.focusNext){const i=this.renderRoot.querySelector(this.focusNext);this.focusNext="",i&&(i.focus(),"select"in i&&i.tagName==="INPUT"&&i.select())}}later(e,t){const i=setTimeout(()=>{this.timers.delete(i),e()},t);this.timers.add(i)}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}get docked(){return this.embed==="page"&&this.width>=It}get panelDocked(){const e=this.docked&&this.sidebarOpen?_t:0;return this.width-e>=Lt}newChat(){this.halt(),this.activeId=null,this.chatTitle="",this.bookmarked=!1,this.msgs=[],this.threadError="",this.resetViewState(),this.focusNext="textarea.input"}async openChat(e){const t=this.resolvedClient;if(!e)return;this.halt();const i=this.chatList.find(r=>r._id===e);if(this.activeId=e,this.chatTitle=(i==null?void 0:i.title)??"",this.bookmarked=!!(i!=null&&i.bookmarked),this.msgs=[],this.threadError="",this.resetViewState(),!t){this.threadError=this.msg.errNoClient;return}const a=++this.run;this.loadingThread=!0;try{const r=await t.llm.call("get_chat",{_id:e});if(a!==this.run)return;this.chatTitle=(r==null?void 0:r.title)??"",this.bookmarked=!!(r!=null&&r.bookmarked),this.msgs=((r==null?void 0:r.messages)??[]).filter(l=>l&&(l.role==="user"||l.role==="assistant")).map(l=>this.fromServer(l)),this.upsertChat({...i,...r,_id:e}),this.stick=!0,this.scrollToBottom()}catch(r){if(a!==this.run)return;at(r)?(this.chatList=this.chatList.filter(l=>l._id!==e),this.newChat(),this.showToast(this.msg.errNotFound)):this.threadError=this.msg.errLoad}finally{a===this.run&&(this.loadingThread=!1)}}async send(e){const t=(typeof e=="string"?e:this.draft).trim();if(!t||this.busy)return;const i=this.files;this.draft="",this.files=[];const a=this.renderRoot.querySelector("textarea.input");a&&(a.style.height="auto"),await this.runTurn(this.userMessage(t,i))}stop(){if(!this.busy)return;const e=this.msgs[this.msgs.length-1];this.halt(),(e==null?void 0:e.role)==="assistant"&&(e.phase==="pending"||e.phase==="streaming")&&(e.phase="done",e.stopped=!0,e.followups=[],this.msgs=[...this.msgs])}exportChat(e="md"){var T;if(!this.msgs.length)return;this.menuOpen=!1;const t=this.chatTitle||this.msg.untitled,i=y=>y.role==="user"?this.msg.you:this.assistantName,a=y=>new Date(y||Date.now()).toLocaleString(),r=y=>y.sources.map((O,gt)=>{const De=_(O,gt+1);return`[${De.n}] ${De.title}${De.path?` — ${De.path}`:""}`}),l=y=>(y.attachments??[]).map(O=>O.name);let c,m="text/markdown",x="md";if(e==="json"?(c=JSON.stringify({exportedAt:new Date().toISOString(),id:this.activeId,title:t,mode:this.mode,bookmarked:this.bookmarked,messages:this.msgs.map(y=>({role:y.role,text:y.content,at:new Date(y.at||Date.now()).toISOString(),bookmarked:y.bookmarked,attachments:l(y),sources:r(y)}))},null,2),m="application/json",x="json"):e==="txt"?(c=`${t}
2292
- ${"=".repeat(t.length)}
2293
-
2294
- `+this.msgs.map(y=>[`${i(y)} · ${a(y.at)}`,l(y).length?`Attachments: ${l(y).join(", ")}`:"",y.content,r(y).length?`Sources:
2295
- ${r(y).join(`
2296
- `)}`:""].filter(Boolean).join(`
2297
- `)).join(`
2298
-
2299
- `),m="text/plain",x="txt"):c=`# ${t}
2300
-
2301
- `+this.msgs.map(y=>[`### ${i(y)} · ${a(y.at)}`,l(y).length?`Attachments: ${l(y).join(", ")}`:"",y.content,r(y).length?`**Sources**
2302
-
2303
- ${r(y).map(O=>`- ${O}`).join(`
2304
- `)}`:""].filter(Boolean).join(`
2305
-
2306
- `)).join(`
2307
-
2308
- ---
2309
-
2310
- `)+`
2311
- `,this.emit("singlebase-chat-export",{chatId:this.activeId,format:e}),e==="copy"){(T=navigator.clipboard)==null||T.writeText(c).catch(()=>{}),this.showToast(this.msg.copiedMarkdown);return}const S=`${t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"chat"}-${new Date().toISOString().slice(0,10)}.${x}`,C=URL.createObjectURL(new Blob([c],{type:m})),b=document.createElement("a");b.href=C,b.download=S,document.body.appendChild(b),b.click(),b.remove(),setTimeout(()=>URL.revokeObjectURL(C),2e3),this.showToast($.fill(this.msg.exported,{name:S}))}expand(){this.expanded=!0,this.emit("singlebase-chat-expand",{expanded:!0})}collapse(){this.expanded=!1,this.emit("singlebase-chat-expand",{expanded:!1})}open(){this.isOpen=!0,this.seen=!0,this.bubble=!1,this.focusNext="textarea.input",this.emit("singlebase-chat-open",{})}close(){this.isOpen=!1,this.expanded=!1,this.emit("singlebase-chat-close",{})}userMessage(e,t=[]){return{key:Ke(),id:null,role:"user",content:e,at:Date.now(),bookmarked:!1,sources:[],followups:[],phase:"done",attachments:t}}systemPrompt(){return[this.systemMessage,it[this.mode]??it.chat,this.followups?Nt:""].filter(Boolean).join(`
2312
-
2313
- `)}payloadFor(e){const t={message:e.content,format:"markdown"};this.activeId?t._id=this.activeId:(t.title=Ct(e.content),t.system_message=this.systemPrompt()),this.model&&(t.model=this.model),Object.keys(this.params??{}).length&&(t.params=this.params);const i=(e.attachments??[]).map(r=>r.name);(Object.keys(this.metadata??{}).length||i.length)&&(t.metadata={...this.metadata,...i.length?{attachments:i}:{}});const a=[...this.retrieval??[],...Ut(e.attachments??[])];return a.length&&(t.retrieval=a),t}async runTurn(e){const t={key:Ke(),id:null,role:"assistant",content:"",at:Date.now(),bookmarked:!1,sources:[],followups:[],phase:"pending"};this.msgs=[...this.msgs,e,t],this.busy=!0,this.panel=null,this.stick=!0,this.scrollToBottom(),this.emit("singlebase-chat-send",{chatId:this.activeId,text:e.content});const i=this.resolvedClient;if(!i){this.failTurn(t,this.msg.errNoClient,"NO_CLIENT"),this.busy=!1;return}const a=++this.run,r=new AbortController;this.abort=r;const l=!this.activeId,c=this.payloadFor(e);try{const m=await i.llm.call("chat",c,{signal:r.signal}),x=(m==null?void 0:m._id)||(m==null?void 0:m.chat_id)||this.activeId;if(l&&x&&this.upsertChat({_id:x,title:(m==null?void 0:m.title)||c.title,bookmarked:!!(m!=null&&m.bookmarked),_modified_at:new Date().toISOString()}),a!==this.run)return;x&&(this.activeId=x),l?(this.chatTitle=(m==null?void 0:m.title)||c.title,this.bookmarked=!!(m!=null&&m.bookmarked)):x&&this.touchChat(x);const f=(m==null?void 0:m.message)??{},S=typeof f.content=="string"?f.content:(m==null?void 0:m.json)!==void 0?JSON.stringify(m.json,null,2):"",{text:C,followups:b}=He(S);e.id=f.reply_to??null,Object.assign(t,{id:f._id??null,content:C,sources:Array.isArray(f.sources)?f.sources:[],followups:this.followups?b:[],execTime:typeof f.exec_time=="number"?f.exec_time:void 0,model:f.model,at:Date.now()}),this.emit("singlebase-chat-response",{chatId:x,message:t}),await this.reveal(t,a),l&&x&&this.autoTitle&&this.retitle(x,e.content,t.content)}catch(m){if(a!==this.run)return;const x=at(m);x&&(this.chatList=this.chatList.filter(f=>f._id!==this.activeId),this.activeId=null),this.failTurn(t,x?this.msg.errNotFound:this.msg.errGeneric,Dt(m))}finally{a===this.run&&(this.busy=!1,this.abort=null,this.stick&&this.scrollToBottom())}}failTurn(e,t,i){e.phase="error",e.error=t,this.msgs=[...this.msgs],this.emit("singlebase-chat-error",{chatId:this.activeId,code:i,message:t})}reveal(e,t){const i=e.content.length,a=()=>{e.phase="done",this.msgs=[...this.msgs],this.arrivedKey=e.key,this.later(()=>{this.arrivedKey===e.key&&(this.arrivedKey="")},Et),this.stick?this.scrollToBottom():this.showJump=!0};if(!i||Rt())return a(),Promise.resolve();const r=e.content,l=Math.max(4,Math.ceil(i/90));let c=0;return e.phase="streaming",e.content="",new Promise(m=>{this.revealTimer=setInterval(()=>{if(t!==this.run){clearInterval(this.revealTimer),m();return}if(c=Math.min(i,c+l),e.content=r.slice(0,c),c>=i){clearInterval(this.revealTimer),a(),m();return}this.msgs=[...this.msgs],this.stick&&this.scrollToBottom()},16)})}halt(){var e;this.run++,(e=this.abort)==null||e.abort(),this.abort=null,clearInterval(this.revealTimer),this.busy=!1}async retitle(e,t,i){const a=this.resolvedClient;if(!(!a||this.renamed.has(e)))try{const r=await a.llm.call("generate",{user_input:`user: ${t}
2314
- assistant: ${i.slice(0,1500)}`,custom_instructions:"Write a concise title (3–6 words, sentence case, no quotes, no trailing punctuation) for this conversation.",format:"text"}),l=St(r==null?void 0:r.result);if(!l||this.renamed.has(e))return;await a.llm.call("update_chat",{_id:e,title:l}),this.applyTitle(e,l,!0)}catch{}}applyTitle(e,t,i){this.chatList=this.chatList.map(a=>a._id===e?{...a,title:t}:a),this.activeId===e&&(this.chatTitle=t),this.emit("singlebase-chat-title",{chatId:e,title:t,auto:i})}commitTitle(e){this.editingTitle&&(this.editingTitle=!1,this.activeId&&this.renameChat(this.activeId,e))}commitRename(e,t){this.renamingId===e&&(this.renamingId="",this.renameChat(e,t))}async renameChat(e,t){var r,l;const i=t.trim().slice(0,80),a=((r=this.chatList.find(c=>c._id===e))==null?void 0:r.title)??this.chatTitle;if(!(!i||i===a)){this.renamed.add(e),this.applyTitle(e,i,!1);try{await((l=this.resolvedClient)==null?void 0:l.llm.call("update_chat",{_id:e,title:i}))}catch{this.applyTitle(e,a??"",!1),this.showToast(this.msg.errGeneric)}}}fromServer(e){const t=e.role==="assistant",{text:i,followups:a}=t?He(String(e.content??"")):{text:String(e.content??""),followups:[]};return{key:Ke(),id:e._id??null,role:t?"assistant":"user",content:i,at:Date.parse(e._created_at??"")||0,bookmarked:!!e.bookmarked,sources:Array.isArray(e.sources)?e.sources:[],followups:this.followups?a:[],phase:"done",execTime:typeof e.exec_time=="number"?e.exec_time:void 0,model:e.model}}async loadChats(){const e=this.resolvedClient;if(e){this.listState="loading";try{const t=await e.llm.call("list_chats",{limit:100});this.chatList=[...(t==null?void 0:t.items)??[]],this.listState="ready"}catch{this.listState="error"}}}upsertChat(e){const t=this.chatList.filter(a=>a._id!==e._id),i=this.chatList.find(a=>a._id===e._id);this.chatList=[{...i,...e},...t]}touchChat(e){const t=this.chatList.find(i=>i._id===e);t&&this.upsertChat({...t,_modified_at:new Date().toISOString()})}resetViewState(){this.panel=null,this.menuOpen=!1,this.editingKey="",this.editingTitle=!1,this.showJump=!1,this.retrievalOpen=new Set,this.sidebarOpen&&!this.docked&&(this.sidebarOpen=!1)}async deleteOnServer(e){const t=this.resolvedClient,i=this.activeId;if(!(!t||!i))for(const a of e)a&&await t.llm.call("delete_chat_message",{_id:i,message_id:a}).catch(()=>{})}async regenerate(){if(this.busy)return;const e=this.msgs.map(a=>a.role).lastIndexOf("assistant"),t=this.msgs[e-1];if(e<1||(t==null?void 0:t.role)!=="user")return;const i=this.msgs.slice(e-1);this.msgs=this.msgs.slice(0,e-1),await this.deleteOnServer(i.map(a=>a.id)),await this.runTurn(this.userMessage(t.content,t.attachments))}async retry(e){if(this.busy)return;const t=this.msgs.indexOf(e),i=this.msgs[t-1];(i==null?void 0:i.role)==="user"&&(this.msgs=this.msgs.slice(0,t-1),await this.runTurn(this.userMessage(i.content,i.attachments)))}async saveEdit(e){const t=this.editDraft.trim(),i=this.msgs.indexOf(e);if(this.editingKey="",!t||i<0||this.busy)return;const a=this.msgs.slice(i);this.msgs=this.msgs.slice(0,i),await this.deleteOnServer(a.map(r=>r.id)),await this.runTurn(this.userMessage(t,e.attachments))}copy(e,t){var i;(i=navigator.clipboard)==null||i.writeText(t).catch(()=>{}),this.copiedKey=e,this.later(()=>{this.copiedKey===e&&(this.copiedKey="")},1400)}async toggleMessageBookmark(e){var i;const t=this.activeId;if(!(!t||!e.id)){e.bookmarked=!e.bookmarked,this.msgs=[...this.msgs],this.showToast(e.bookmarked?this.msg.messageBookmarked:this.msg.bookmarkRemoved),this.emit("singlebase-chat-bookmark",{chatId:t,messageId:e.id,bookmarked:e.bookmarked});try{await((i=this.resolvedClient)==null?void 0:i.llm.call("bookmark_chat_message",{_id:t,message_id:e.id,bookmarked:e.bookmarked}))}catch{e.bookmarked=!e.bookmarked,this.msgs=[...this.msgs],this.showToast(this.msg.errGeneric)}}}async toggleChatBookmark(e){var r,l;const t=((r=this.chatList.find(c=>c._id===e))==null?void 0:r.bookmarked)??(e===this.activeId?this.bookmarked:!1),i=!t,a=c=>{this.chatList=this.chatList.map(m=>m._id===e?{...m,bookmarked:c}:m),e===this.activeId&&(this.bookmarked=c)};a(i),this.showToast(i?this.msg.chatBookmarked:this.msg.chatUnbookmarked),this.emit("singlebase-chat-bookmark",{chatId:e,bookmarked:i});try{await((l=this.resolvedClient)==null?void 0:l.llm.call("bookmark_chat",{_id:e,bookmarked:i}))}catch{a(t),this.showToast(this.msg.errGeneric)}}deleteMessage(e){var a;const t=this.activeId,i=this.msgs.indexOf(e);i<0||(this.msgs=this.msgs.filter(r=>r!==e),((a=this.panel)==null?void 0:a.key)===e.key&&(this.panel=null),this.showToast(this.msg.messageDeleted,{undo:()=>{if(this.activeId!==t)return;const r=[...this.msgs];r.splice(i,0,e),this.msgs=r},commit:()=>{var r;this.emit("singlebase-chat-message-delete",{chatId:t,messageId:e.id}),t&&e.id&&((r=this.resolvedClient)==null||r.llm.call("delete_chat_message",{_id:t,message_id:e.id}).catch(()=>{}))}}))}deleteChat(e){const t=this.chatList.findIndex(l=>l._id===e),i=this.chatList[t]??{_id:e,title:this.chatTitle,bookmarked:this.bookmarked},a=e===this.activeId,r=a?{title:this.chatTitle,bookmarked:this.bookmarked,msgs:this.msgs}:null;this.chatList=this.chatList.filter(l=>l._id!==e),a&&this.newChat(),this.showToast(this.msg.chatDeleted,{undo:()=>{const l=[...this.chatList];l.splice(Math.max(0,t),0,i),this.chatList=l,r&&!this.activeId&&!this.msgs.length&&(this.activeId=e,this.chatTitle=r.title,this.bookmarked=r.bookmarked,this.msgs=r.msgs)},commit:()=>{var l;this.emit("singlebase-chat-delete",{chatId:e}),(l=this.resolvedClient)==null||l.llm.call("delete_chat",{_id:e}).catch(()=>{})}})}feedback(e,t){e.feedback=t,this.msgs=[...this.msgs],this.emit("singlebase-chat-feedback",{chatId:this.activeId,messageId:e.id,value:t,text:e.content})}showToast(e,t={}){this.flushToast();const i={key:Date.now(),text:e,...t};this.toast=i,this.toastTimer=setTimeout(()=>{this.toast===i&&this.flushToast()},At)}flushToast(){var t;const e=this.toast;clearTimeout(this.toastTimer),this.toast=null,(t=e==null?void 0:e.commit)==null||t.call(e)}undo(){var t;const e=this.toast;clearTimeout(this.toastTimer),this.toast=null,(t=e==null?void 0:e.undo)==null||t.call(e)}async addFiles(e){const t=Array.from(e??[]);if(!t.length)return;const i=[];for(const a of t){if(this.files.length+i.length>=et){this.showToast($.fill(this.msg.tooManyFiles,{n:et}));break}if(!jt.test(a.name)&&!a.type.startsWith("text/")){this.showToast($.fill(this.msg.fileType,{name:a.name}));continue}if(a.size>tt){this.showToast($.fill(this.msg.fileTooLarge,{name:a.name,size:$.formatSize(tt)}));continue}i.push({name:a.name,size:a.size,content:await a.text()})}i.length&&(this.files=[...this.files,...i],this.emit("singlebase-chat-files",{files:i.map(({name:a,size:r})=>({name:a,size:r}))}))}async scrollToBottom(){await this.updateComplete;const e=this.renderRoot.querySelector(".scroller");e&&(e.scrollTop=e.scrollHeight),this.showJump=!1}onScroll(e){const t=e.currentTarget;this.stick=t.scrollHeight-t.scrollTop-t.clientHeight<80,this.stick&&(this.showJump=!1)}jumpToLatest(){this.stick=!0,this.scrollToBottom()}onKeydown(e){if(e.key==="Escape"){if(this.menuOpen)this.menuOpen=!1;else if(this.panel)this.panel=null;else if(this.sidebarOpen&&!this.docked)this.sidebarOpen=!1;else if(this.expanded)this.collapse();else if(this.embed==="launcher"&&this.isOpen)this.close();else return;e.stopPropagation()}}onComposerKey(e){e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&(e.preventDefault(),this.send())}onComposerInput(e){const t=e.target;t.style.height="auto",t.style.height=`${Math.min(176,t.scrollHeight)}px`,this.draft=t.value}onDragEnter(e){var t;!this.allowUpload||!Array.from(((t=e.dataTransfer)==null?void 0:t.types)??[]).includes("Files")||(e.preventDefault(),this.dragging=!0)}onDragLeave(e){e.currentTarget.contains(e.relatedTarget)||(this.dragging=!1)}onDrop(e){var t;e.preventDefault(),this.dragging=!1,this.allowUpload&&this.addFiles((t=e.dataTransfer)==null?void 0:t.files)}render(){if(this.embed==="launcher")return this.renderLauncher();const e=["frame",this.embed==="inline"?"inline boxed":"",this.expanded?"expanded boxed":""].join(" ");return s.html`<div class=${e} part="frame">${this.renderWorkspace()}</div>`}renderLauncher(){const e=this.msg,t=["frame launcher boxed",this.expanded?"expanded":"",this.mobile?"full":""].join(" "),i=this.isOpen?s.html`<div class=${t} role="dialog" aria-label=${this.assistantName} part="frame">
2315
- ${this.renderWorkspace()}
2316
- </div>`:s.nothing,a=this.bubble&&!this.isOpen?s.html`<div class="bubble" part="bubble">
2317
- <button type="button" class="bubble-text" @click=${()=>this.open()}>
2318
- ${this.bubbleText||e.bubbleText}
2319
- </button>
2320
- <button
2321
- type="button"
2322
- class="icon sm"
2323
- aria-label=${e.dismiss}
2324
- title=${e.dismiss}
2325
- @click=${()=>this.bubble=!1}
2326
- >
2327
- ${v.close()}
2328
- </button>
2329
- </div>`:s.nothing,l=this.isOpen&&(this.expanded||this.mobile)?s.nothing:s.html`<button
2330
- type="button"
2331
- class="launcher-btn"
2332
- part="launcher"
2333
- aria-label=${this.isOpen?e.closeChat:e.openChat}
2334
- aria-expanded=${this.isOpen?"true":"false"}
2335
- @click=${()=>this.isOpen?this.close():this.open()}
2336
- >
2337
- ${this.isOpen?v.chevronDown():v.chat()}
2338
- ${this.unreadBadge&&!this.seen&&!this.isOpen?s.html`<span class="badge"></span>`:s.nothing}
2339
- </button>`;return s.html`${i}${a}${l}`}renderWorkspace(){const e=!this.docked;return s.html`<div class="root" @keydown=${this.onKeydown}>
2340
- ${this.sidebarOpen&&e?s.html`<div class="scrim" @click=${()=>this.sidebarOpen=!1}></div>`:s.nothing}
2341
- ${this.sidebarOpen?this.renderSidebar(e):s.nothing}
2342
- <main
2343
- class="main"
2344
- @dragenter=${this.onDragEnter}
2345
- @dragover=${t=>t.preventDefault()}
2346
- >
2347
- ${this.renderHeader()}
2348
- ${this.offline?s.html`<div class="banner" role="status">${this.msg.offline}</div>`:s.nothing}
2349
- <div
2350
- class="scroller"
2351
- role="log"
2352
- aria-live="polite"
2353
- aria-busy=${this.busy?"true":"false"}
2354
- part="messages"
2355
- @scroll=${this.onScroll}
2356
- >
2357
- ${this.msgs.length||this.loadingThread||this.threadError?this.renderThread():this.renderWelcome()}
2358
- </div>
2359
- ${this.showJump?s.html`<button type="button" class="jump" @click=${this.jumpToLatest}>
2360
- ↓ ${this.msg.newReply}
2361
- </button>`:s.nothing}
2362
- ${this.renderComposer()}
2363
- ${this.branding?s.html`<div class="branding" part="branding">
2364
- <a href="https://singlebase.cloud" target="_blank" rel="noopener noreferrer"
2365
- >${this.msg.brandingLabel}</a
2366
- >
2367
- </div>`:s.nothing}
2368
- ${this.toast?s.html`<div class="toast" role="status">
2369
- <span>${this.toast.text}</span>
2370
- ${this.toast.undo?s.html`<button type="button" @click=${this.undo}>${this.msg.undo}</button>`:s.nothing}
2371
- </div>`:s.nothing}
2372
- ${this.dragging?s.html`<div
2373
- class="drop"
2374
- @dragover=${t=>t.preventDefault()}
2375
- @dragleave=${this.onDragLeave}
2376
- @drop=${this.onDrop}
2377
- >
2378
- <strong>${this.msg.dropTitle}</strong><span>${this.msg.dropSub}</span>
2379
- </div>`:s.nothing}
2380
- </main>
2381
- ${this.renderPanel()}
2382
- </div>`}renderSidebar(e){const t=this.msg,i=this.search.trim().toLowerCase(),a=this.chatList.filter(c=>!i||(c.title??"").toLowerCase().includes(i)),r=[[t.groupBookmarked,a.filter(c=>c.bookmarked)],[t.groupToday,a.filter(c=>!c.bookmarked&&Ue(c._modified_at??c._created_at)==="today")],[t.groupYesterday,a.filter(c=>!c.bookmarked&&Ue(c._modified_at??c._created_at)==="yesterday")],[t.groupWeek,a.filter(c=>!c.bookmarked&&Ue(c._modified_at??c._created_at)==="week")],[t.groupOlder,a.filter(c=>!c.bookmarked&&Ue(c._modified_at??c._created_at)==="older")]];let l;return this.listState==="loading"&&!this.chatList.length?l=s.html`<div aria-label=${t.loadingChats}>
2383
- ${[1,2,3,4].map(()=>s.html`<div class="skeleton"></div>`)}
2384
- </div>`:a.length?l=r.filter(([,c])=>c.length).map(([c,m])=>s.html`<div class="group">${c}</div>
2385
- ${m.map(x=>this.renderThreadRow(x))}`):l=s.html`<span class="side-note"
2386
- >${i?$.fill(t.noMatch,{query:this.search.trim()}):t.noChats}</span
2387
- >`,s.html`<aside
2388
- class="sidebar ${e?"overlay":"docked"}"
2389
- part="sidebar"
2390
- aria-label=${t.chats}
2391
- >
2392
- <div class="side-head">
2393
- <span class="label">${t.chats}</span>
2394
- <button
2395
- type="button"
2396
- class="icon"
2397
- title=${t.hideSidebar}
2398
- aria-label=${t.hideSidebar}
2399
- @click=${()=>this.sidebarOpen=!1}
2400
- >
2401
- ${v.sidebar()}
2402
- </button>
2403
- </div>
2404
- <div class="side-tools">
2405
- <button type="button" class="new-chat" @click=${()=>this.newChat()}>
2406
- ${v.plus()}<span>${t.newChat}</span>
2407
- </button>
2408
- <input
2409
- class="search"
2410
- type="search"
2411
- placeholder=${t.searchChats}
2412
- aria-label=${t.searchChats}
2413
- .value=${this.search}
2414
- @input=${c=>this.search=c.target.value}
2415
- />
2416
- </div>
2417
- <div class="threads">${l}</div>
2418
- </aside>`}renderThreadRow(e){const t=this.msg,i=e._id===this.activeId,a=e.title||t.untitled;if(this.renamingId===e._id)return s.html`<div class="thread active">
2419
- <input
2420
- class="thread-rename"
2421
- maxlength="80"
2422
- .value=${a}
2423
- aria-label=${t.renameChat}
2424
- @keydown=${l=>{l.key==="Enter"&&this.commitRename(e._id,l.target.value),l.key==="Escape"&&(l.stopPropagation(),this.renamingId="")}}
2425
- @blur=${l=>this.commitRename(e._id,l.target.value)}
2426
- />
2427
- </div>`;const r=l=>c=>{c.stopPropagation(),l()};return s.html`<div
2428
- class="thread ${i?"active":""}"
2429
- role="button"
2430
- tabindex="0"
2431
- aria-current=${i?"true":"false"}
2432
- @click=${()=>this.openChat(e._id)}
2433
- @keydown=${l=>l.key==="Enter"&&this.openChat(e._id)}
2434
- >
2435
- <span class="thread-title">${a}</span>
2436
- <span class="thread-actions">
2437
- <button
2438
- type="button"
2439
- class="icon sm ${e.bookmarked?"on":""}"
2440
- title=${e.bookmarked?t.unbookmarkChat:t.bookmarkChat}
2441
- aria-label=${e.bookmarked?t.unbookmarkChat:t.bookmarkChat}
2442
- @click=${r(()=>this.toggleChatBookmark(e._id))}
2443
- >
2444
- ${v.bookmark(!!e.bookmarked)}
2445
- </button>
2446
- <button
2447
- type="button"
2448
- class="icon sm"
2449
- title=${t.renameChat}
2450
- aria-label=${t.renameChat}
2451
- @click=${r(()=>{this.renamingId=e._id,this.focusNext="input.thread-rename"})}
2452
- >
2453
- ${v.pencil()}
2454
- </button>
2455
- <button
2456
- type="button"
2457
- class="icon sm danger"
2458
- title=${t.deleteChat}
2459
- aria-label=${t.deleteChat}
2460
- @click=${r(()=>this.deleteChat(e._id))}
2461
- >
2462
- ${v.trash()}
2463
- </button>
2464
- </span>
2465
- </div>`}renderHeader(){const e=this.msg,t=!!this.activeId,i=(this.embed==="inline"||this.embed==="launcher")&&!this.mobile,a=this.embed==="launcher"?()=>this.close():this.expanded?()=>this.collapse():null;let r=s.nothing;return this.showTitle&&(r=this.editingTitle?s.html`<input
2466
- class="title-input"
2467
- maxlength="80"
2468
- .value=${this.chatTitle}
2469
- aria-label=${e.renameChat}
2470
- @keydown=${l=>{l.key==="Enter"&&this.commitTitle(l.target.value),l.key==="Escape"&&(l.stopPropagation(),this.editingTitle=!1)}}
2471
- @blur=${l=>this.commitTitle(l.target.value)}
2472
- />`:s.html`<button
2473
- type="button"
2474
- class="title"
2475
- part="title"
2476
- ?disabled=${!t}
2477
- title=${t?e.renameChat:""}
2478
- @click=${()=>{this.editingTitle=!0,this.focusNext="input.title-input"}}
2479
- >
2480
- ${this.chatTitle||e.untitled}
2481
- </button>`),s.html`<header class="header" part="header">
2482
- <div class="header-left">
2483
- ${this.sidebarOpen&&this.docked?s.nothing:s.html`<button
2484
- type="button"
2485
- class="icon"
2486
- title=${e.showChats}
2487
- aria-label=${e.showChats}
2488
- @click=${()=>this.sidebarOpen=!0}
2489
- >
2490
- ${v.sidebar()}
2491
- </button>`}
2492
- ${r}
2493
- </div>
2494
- <div class="header-right">
2495
- <button
2496
- type="button"
2497
- class="icon ${this.bookmarked?"on":""}"
2498
- ?disabled=${!t}
2499
- title=${this.bookmarked?e.unbookmarkChat:e.bookmarkChat}
2500
- aria-label=${this.bookmarked?e.unbookmarkChat:e.bookmarkChat}
2501
- @click=${()=>this.activeId&&this.toggleChatBookmark(this.activeId)}
2502
- >
2503
- ${v.bookmark(this.bookmarked)}
2504
- </button>
2505
- ${this.allowExport?s.html`<div class="menu-wrap">
2506
- <button
2507
- type="button"
2508
- class="icon ${this.menuOpen?"on":""}"
2509
- ?disabled=${!this.msgs.length}
2510
- title=${e.exportChat}
2511
- aria-label=${e.exportChat}
2512
- aria-haspopup="menu"
2513
- aria-expanded=${this.menuOpen?"true":"false"}
2514
- @click=${()=>this.menuOpen=!this.menuOpen}
2515
- >
2516
- ${v.download()}
2517
- </button>
2518
- ${this.menuOpen?this.renderExportMenu():s.nothing}
2519
- </div>`:s.nothing}
2520
- <button
2521
- type="button"
2522
- class="icon danger"
2523
- ?disabled=${!t}
2524
- title=${e.deleteChat}
2525
- aria-label=${e.deleteChat}
2526
- @click=${()=>this.activeId&&this.deleteChat(this.activeId)}
2527
- >
2528
- ${v.trash()}
2529
- </button>
2530
- ${i||a?s.html`<span class="divider"></span> ${i?s.html`<button
2531
- type="button"
2532
- class="icon"
2533
- title=${this.expanded?e.restore:e.expand}
2534
- aria-label=${this.expanded?e.restore:e.expand}
2535
- @click=${()=>this.expanded?this.collapse():this.expand()}
2536
- >
2537
- ${this.expanded?v.restore():v.expand()}
2538
- </button>`:s.nothing}
2539
- ${a?s.html`<button
2540
- type="button"
2541
- class="icon"
2542
- title=${e.minimize}
2543
- aria-label=${e.minimize}
2544
- @click=${a}
2545
- >
2546
- ${v.minimize()}
2547
- </button>`:s.nothing}`:s.nothing}
2548
- </div>
2549
- </header>`}renderExportMenu(){const e=this.msg,t=[[e.exportMarkdown,".md","md"],[e.exportJson,".json","json"],[e.exportText,".txt","txt"],[e.exportCopy,"","copy"]];return s.html`<div class="menu-scrim" @click=${()=>this.menuOpen=!1}></div>
2550
- <div class="menu" role="menu">
2551
- <span class="label">${e.exportHeading}</span>
2552
- ${t.map(([i,a,r])=>s.html`<button
2553
- type="button"
2554
- role="menuitem"
2555
- class="menu-item"
2556
- @click=${()=>this.exportChat(r)}
2557
- >
2558
- <span>${i}</span><span class="ext">${a}</span>
2559
- </button>`)}
2560
- </div>`}promptList(){const e=this.prompts;return Array.isArray(e)&&e.length?e.map(t=>typeof t=="string"?{text:t}:t).filter(t=>t==null?void 0:t.text).slice(0,4):typeof e=="string"&&e.trim()?e.split("|").map(t=>t.trim()).filter(Boolean).slice(0,4).map(t=>({text:t})):(st[this.mode]??st.chat).map(([t,i])=>({label:t,text:i}))}renderWelcome(){const e=this.msg,t=this.mode==="rag"?"Rag":this.mode==="rich"?"Rich":"Chat",i=a=>e[`${a}${t}`];return s.html`<div class="welcome" part="welcome">
2561
- <div class="welcome-head">
2562
- ${this.logoUrl&&Qe(this.logoUrl,!0)?s.html`<img class="welcome-logo" src=${this.logoUrl} alt="" />`:s.nothing}
2563
- <span class="label">${i("eyebrow")}</span>
2564
- <h2>${this.heading||i("heading")}</h2>
2565
- <p>${this.description||i("description")}</p>
2566
- </div>
2567
- <div class="prompts">
2568
- ${this.promptList().map(a=>s.html`<button
2569
- type="button"
2570
- class="prompt"
2571
- part="prompt"
2572
- @click=${()=>this.send(a.text)}
2573
- >
2574
- <span class="label">${a.label||"Suggested"}</span>
2575
- <span class="prompt-text">${a.text}</span>
2576
- </button>`)}
2577
- </div>
2578
- </div>`}renderThread(){const e=this.msgs.map(t=>t.role).lastIndexOf("assistant");return s.html`<div class="thread-view">
2579
- ${this.threadError?s.html`<div class="error-card" role="alert">
2580
- <span>${this.threadError}</span>
2581
- ${this.activeId?s.html`<button
2582
- type="button"
2583
- class="btn"
2584
- @click=${()=>this.openChat(this.activeId)}
2585
- >
2586
- ${this.msg.retry}
2587
- </button>`:s.nothing}
2588
- </div>`:s.nothing}
2589
- ${this.loadingThread?s.html`${[1,2].map(()=>s.html`<div class="skeleton" style="height:48px"></div>`)}`:s.nothing}
2590
- ${ft.repeat(this.msgs,t=>t.key,(t,i)=>t.role==="user"?this.renderUser(t):this.renderBot(t,i===e))}
2591
- </div>`}renderUser(e){const t=this.msg,i=e.at?new Date(e.at).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}):"",a=e.attachments??[];return s.html`<div class="msg user" part="message user">
2592
- ${a.length?s.html`<div class="attachments">
2593
- ${a.map(r=>s.html`<span class="doc-chip"><span class="ext">${rt(r.name)}</span><span class="name">${r.name}</span></span>`)}
2594
- </div>`:s.nothing}
2595
- ${this.editingKey===e.key?s.html`<div class="edit-box">
2596
- <textarea
2597
- rows="3"
2598
- class="edit-input"
2599
- .value=${this.editDraft}
2600
- @input=${r=>this.editDraft=r.target.value}
2601
- @keydown=${r=>{r.key==="Escape"&&(r.stopPropagation(),this.editingKey="")}}
2602
- ></textarea>
2603
- <div class="row-end">
2604
- <button type="button" class="btn" @click=${()=>this.editingKey=""}>
2605
- ${t.cancel}
2606
- </button>
2607
- <button type="button" class="btn primary" @click=${()=>this.saveEdit(e)}>
2608
- ${t.saveResend}
2609
- </button>
2610
- </div>
2611
- </div>`:s.html`<div class="bubble-user">${e.content}</div>
2612
- <div class="toolbar">
2613
- ${e.bookmarked?s.html`<span class="saved">${v.bookmark(!0)}${t.saved}</span>`:s.nothing}
2614
- <span class="time">${i}</span>
2615
- ${this.busy?s.nothing:s.html`<button
2616
- type="button"
2617
- class="icon"
2618
- title=${t.edit}
2619
- aria-label=${t.edit}
2620
- @click=${()=>{this.editingKey=e.key,this.editDraft=e.content,this.focusNext="textarea.edit-input"}}
2621
- >
2622
- ${v.pencil()}
2623
- </button>`}
2624
- <button
2625
- type="button"
2626
- class="icon"
2627
- title=${this.copiedKey===e.key?t.copied:t.copy}
2628
- aria-label=${t.copy}
2629
- @click=${()=>this.copy(e.key,e.content)}
2630
- >
2631
- ${v.copy()}
2632
- </button>
2633
- ${e.id?s.html`<button
2634
- type="button"
2635
- class="icon ${e.bookmarked?"on":""}"
2636
- title=${e.bookmarked?t.unbookmarkMessage:t.bookmarkMessage}
2637
- aria-label=${e.bookmarked?t.unbookmarkMessage:t.bookmarkMessage}
2638
- @click=${()=>this.toggleMessageBookmark(e)}
2639
- >
2640
- ${v.bookmark(e.bookmarked)}
2641
- </button>`:s.nothing}
2642
- <button
2643
- type="button"
2644
- class="icon danger"
2645
- title=${t.deleteMessage}
2646
- aria-label=${t.deleteMessage}
2647
- @click=${()=>this.deleteMessage(e)}
2648
- >
2649
- ${v.trash()}
2650
- </button>
2651
- </div>`}
2652
- </div>`}pillLabel(){return this.mode==="rag"?this.msg.searching:this.mode==="rich"?this.msg.building:this.msg.thinking}renderBot(e,t){const i=this.msg,a=e.phase==="pending",r=e.phase==="done",l=e.sources.length,c=Pe(e.content),m=e.sources.map((b,T)=>_(b,T+1)),x=c.size?m.filter(b=>c.has(b.n)):m,f=e.at?new Date(e.at).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}):"",S=e.content+(x.length?`
2653
-
2654
- Sources:
2655
- ${x.map(b=>`[${b.n}] ${b.title}`).join(`
2656
- `)}`:""),C=this.retrievalOpen.has(e.key);return s.html`<div class="msg bot" part="message assistant">
2657
- ${a?s.html`<div class="halo"></div>`:s.nothing}
2658
- ${this.arrivedKey===e.key?s.html`<div class="arrived">
2659
- <div class="wash"></div>
2660
- <div class="ring"></div>
2661
- <div class="sweep"></div>
2662
- </div>`:s.nothing}
2663
- <div class="bot-body">
2664
- ${e.bookmarked?s.html`<span class="saved">${v.bookmark(!0)}${i.saved}</span>`:s.nothing}
2665
- ${a?s.html`<div class="pill" role="status">
2666
- <span class="ring"></span><span class="dot"></span>
2667
- <span class="shimmer">${this.pillLabel()}</span>
2668
- </div>`:s.nothing}
2669
- ${l&&!a?s.html`<div class="retrieval">
2670
- <button
2671
- type="button"
2672
- class="retrieval-toggle"
2673
- aria-expanded=${C?"true":"false"}
2674
- @click=${()=>{const b=new Set(this.retrievalOpen);b.has(e.key)?b.delete(e.key):b.add(e.key),this.retrievalOpen=b}}
2675
- >
2676
- <span class="chev">${C?"▾":"▸"}</span>
2677
- <span style="flex:1">${$.fill(i.searchedSources,{n:l})}</span>
2678
- ${e.execTime!==void 0?s.html`<span class="ms">${e.execTime.toFixed(1)}s</span>`:s.nothing}
2679
- </button>
2680
- ${C?s.html`<div class="retrieval-list">
2681
- ${m.map(b=>s.html`<button
2682
- type="button"
2683
- class="passage"
2684
- @click=${()=>this.panel={key:e.key,n:b.n}}
2685
- >
2686
- <span class="n">${b.n}</span>
2687
- <span class="what"
2688
- ><span>${b.title}</span><span>${b.collection||b.path}</span></span
2689
- >
2690
- ${b.score!==null?s.html`<span class="relevance"
2691
- ><span class="score">${b.score.toFixed(2)}</span>
2692
- <span class="relevance-track"
2693
- ><span
2694
- class="relevance-fill"
2695
- style="width:${Math.round(b.score*100)}%"
2696
- ></span></span
2697
- ></span>`:s.html`<span></span>`}
2698
- </button>`)}
2699
- </div>`:s.nothing}
2700
- </div>`:s.nothing}
2701
- ${a?s.nothing:this.renderAnswer(e)}
2702
- ${e.phase==="streaming"?s.html`<span class="caret"></span>`:s.nothing}
2703
- ${e.phase==="error"?s.html`<div class="error-card" role="alert">
2704
- <span>${e.error}</span>
2705
- <button type="button" class="btn" @click=${()=>this.retry(e)}>
2706
- ${i.retry}
2707
- </button>
2708
- </div>`:s.nothing}
2709
- ${r&&x.length?s.html`<div class="cards">
2710
- <span class="label">${c.size?i.sourcesCited:i.sourcesRetrieved}</span>
2711
- <div class="card-grid">
2712
- ${x.map(b=>{var T;return s.html`<button
2713
- type="button"
2714
- class="source-card ${((T=this.panel)==null?void 0:T.key)===e.key&&this.panel.n===b.n?"active":""}"
2715
- @click=${()=>this.panel={key:e.key,n:b.n}}
2716
- >
2717
- <span class="top"
2718
- ><span class="num">${b.n}</span
2719
- >${b.collection?s.html`<span class="label">${b.collection}</span>`:s.nothing}</span
2720
- >
2721
- <span class="t">${b.title}</span>
2722
- <span class="s">${b.text}</span>
2723
- </button>`})}
2724
- </div>
2725
- </div>`:s.nothing}
2726
- ${r?s.html`<div class="toolbar ${t?"pinned":""}">
2727
- <button
2728
- type="button"
2729
- class="icon"
2730
- title=${this.copiedKey===e.key?i.copied:i.copy}
2731
- aria-label=${i.copy}
2732
- @click=${()=>this.copy(e.key,S)}
2733
- >
2734
- ${v.copy()}
2735
- </button>
2736
- ${t&&!this.busy?s.html`<button
2737
- type="button"
2738
- class="icon"
2739
- title=${i.regenerate}
2740
- aria-label=${i.regenerate}
2741
- @click=${()=>this.regenerate()}
2742
- >
2743
- ${v.refresh()}
2744
- </button>`:s.nothing}
2745
- ${e.id?s.html`<button
2746
- type="button"
2747
- class="icon ${e.bookmarked?"on":""}"
2748
- title=${e.bookmarked?i.unbookmarkMessage:i.bookmarkMessage}
2749
- aria-label=${e.bookmarked?i.unbookmarkMessage:i.bookmarkMessage}
2750
- @click=${()=>this.toggleMessageBookmark(e)}
2751
- >
2752
- ${v.bookmark(e.bookmarked)}
2753
- </button>`:s.nothing}
2754
- <button
2755
- type="button"
2756
- class="icon danger"
2757
- title=${i.deleteMessage}
2758
- aria-label=${i.deleteMessage}
2759
- @click=${()=>this.deleteMessage(e)}
2760
- >
2761
- ${v.trash()}
2762
- </button>
2763
- <span class="time">${f}</span>
2764
- ${e.stopped?s.html`<span class="note">${i.stopped}</span>`:s.nothing}
2765
- <span class="spacer"></span>
2766
- ${e.feedback?s.html`<span class="note"
2767
- >${e.feedback==="up"?i.markedHelpful:i.thanksFeedback}</span
2768
- >`:s.html`<button
2769
- type="button"
2770
- class="icon"
2771
- title=${i.helpful}
2772
- aria-label=${i.helpful}
2773
- @click=${()=>this.feedback(e,"up")}
2774
- >
2775
- ${v.thumb()}
2776
- </button>
2777
- <button
2778
- type="button"
2779
- class="icon"
2780
- title=${i.notHelpful}
2781
- aria-label=${i.notHelpful}
2782
- @click=${()=>this.feedback(e,"down")}
2783
- >
2784
- ${v.thumb(!0)}
2785
- </button>`}
2786
- </div>`:s.nothing}
2787
- ${r&&t&&!this.busy&&e.followups.length?s.html`<div class="followups">
2788
- ${e.followups.map(b=>s.html`<button type="button" class="followup" @click=${()=>this.send(b)}>
2789
- <span class="arrow">↳</span><span>${b}</span>
2790
- </button>`)}
2791
- </div>`:s.nothing}
2792
- </div>
2793
- </div>`}renderAnswer(e){if(e.phase==="error"&&!e.content)return s.nothing;if(e.phase==="done"&&!e.content)return e.stopped?s.nothing:s.html`<div class="answer"><p class="note">${this.msg.emptyReply}</p></div>`;const t=ht(ct(e.content),this.renderAs),i=this.renderAs==="text"?0:e.sources.length;return s.html`<div class="answer" part="answer">
2794
- ${t.map((a,r)=>this.renderBlock(a,e,i,r))}
2795
- </div>`}renderInline(e,t,i){return pt(e,i).map(a=>{var r;switch(a.type){case"bold":return s.html`<strong>${a.text}</strong>`;case"code":return s.html`<code class="inline">${a.text}</code>`;case"link":return s.html`<a href=${a.href} target="_blank" rel="noopener noreferrer nofollow"
2796
- >${a.text}</a
2797
- >`;case"cite":{const l=((r=this.panel)==null?void 0:r.key)===t.key&&this.panel.n===a.n?"cite active":"cite",c=$.fill(this.msg.openSource,{n:a.n}),m=()=>this.panel={key:t.key,n:a.n};return s.html`<button type="button" class=${l} aria-label=${c} @click=${m}>${a.n}</button>`}default:return a.text}})}renderBlock(e,t,i,a){switch(e.type){case"p":return s.html`<p>${this.renderInline(e.text,t,i)}</p>`;case"raw":return s.html`<p class="raw">${e.text}</p>`;case"h":return s.html`<h3>${this.renderInline(e.text,t,i)}</h3>`;case"list":{const r=e.items.map(l=>s.html`<li>${this.renderInline(l,t,i)}</li>`);return e.ordered?s.html`<ol>
2798
- ${r}
2799
- </ol>`:s.html`<ul>
2800
- ${r}
2801
- </ul>`}case"quote":return s.html`<div class="quote">${this.renderInline(e.text,t,i)}</div>`;case"code":{const r=`${t.key}:${a}`;return s.html`<div class="code">
2802
- <div class="code-head">
2803
- <span class="label">${e.lang}</span>
2804
- <button type="button" class="text-btn" @click=${()=>this.copy(r,e.text)}>
2805
- ${this.copiedKey===r?this.msg.copied:this.msg.copy}
2806
- </button>
2807
- </div>
2808
- <pre><code>${e.text}</code></pre>
2809
- </div>`}case"table":return s.html`<div class="table">
2810
- <table>
2811
- <thead>
2812
- <tr>
2813
- ${e.head.map(r=>s.html`<th>${this.renderInline(r,t,i)}</th>`)}
2814
- </tr>
2815
- </thead>
2816
- <tbody>
2817
- ${e.rows.map(r=>s.html`<tr>
2818
- ${r.map(l=>s.html`<td>${this.renderInline(l,t,i)}</td>`)}
2819
- </tr>`)}
2820
- </tbody>
2821
- </table>
2822
- </div>`;case"chart":return this.renderChart(e.spec);case"chartPending":return s.html`<div class="chart-pending"><span class="label">Rendering chart</span></div>`;case"img":return s.html`<div class="gallery ${e.images.length>1?"many":""}">
2823
- ${e.images.map(r=>s.html`<figure>
2824
- ${r.src&&Qe(r.src,!0)?s.html`<img
2825
- src=${r.src}
2826
- alt=${r.alt}
2827
- loading="lazy"
2828
- referrerpolicy="no-referrer"
2829
- />`:s.html`<div class="img-missing"><span class="label">Image</span></div>`}
2830
- ${r.alt?s.html`<figcaption>${r.alt}</figcaption>`:s.nothing}
2831
- </figure>`)}
2832
- </div>`;default:return s.nothing}}renderChart(e){const t=e.series.length>1?s.html`<span class="legend">
2833
- ${e.series.map((l,c)=>s.html`<span
2834
- ><span
2835
- class="swatch"
2836
- style="background:${z[c%z.length]}"
2837
- ></span
2838
- >${l.name}</span
2839
- >`)}
2840
- </span>`:s.nothing,i=s.html`<div class="chart-head">
2841
- <span class="chart-title">${e.title}</span>${t}
2842
- </div>`;if(e.type==="line"){const l=Math.max(0,...e.series.flatMap(f=>f.values)),c=Math.pow(10,Math.floor(Math.log10(l||1))),m=Math.ceil(l/c*2)/2*c||1,x=Math.max(e.labels.length,...e.series.map(f=>f.values.length));return s.html`<figure class="chart" part="chart" aria-label=${e.title}>
2843
- ${i}
2844
- <div class="line-chart">
2845
- <div class="plot">
2846
- ${[1,.5,0].map(f=>s.html`<div class="tick ${f===0?"base":""}" style="top:${(1-f)*100}%">
2847
- <span>${Re(Math.round(m*f),e.unit)}</span>
2848
- </div>`)}
2849
- <svg
2850
- viewBox="0 0 600 170"
2851
- preserveAspectRatio="none"
2852
- role="img"
2853
- aria-label=${e.title}
2854
- >
2855
- ${e.series.map((f,S)=>s.svg`<polyline pathLength="1" stroke=${z[S%z.length]}
2856
- points=${f.values.map((C,b)=>`${(x>1?b/(x-1)*600:300).toFixed(1)},${(170-C/m*170).toFixed(1)}`).join(" ")}><title>${f.name}: ${f.values.map(C=>Re(C,e.unit)).join(", ")}</title></polyline>`)}
2857
- </svg>
2858
- </div>
2859
- <div class="x-labels">${e.labels.map(f=>s.html`<span>${f}</span>`)}</div>
2860
- </div>
2861
- </figure>`}const a=e.labels.map((l,c)=>e.series.reduce((m,x)=>m+(x.values[c]||0),0)),r=Math.max(0,...a)||1;return s.html`<figure class="chart" part="chart" aria-label=${e.title}>
2862
- ${i}
2863
- <div class="bars">
2864
- ${e.labels.map((l,c)=>s.html`<div class="bar-row" title="${l}: ${Re(a[c],e.unit)}">
2865
- <span class="bar-label">${l}</span>
2866
- <span class="bar-track"
2867
- ><span class="bar-fill" style="width:${Math.max(0,a[c])/r*100}%">
2868
- ${e.series.map((m,x)=>s.html`<span
2869
- style="flex:${Math.max(0,m.values[c]||0)};background:${e.series.length>1?z[x%z.length]:"var(--c-ink)"}"
2870
- ></span>`)}
2871
- </span></span
2872
- >
2873
- <span class="bar-value">${Re(a[c],e.unit)}</span>
2874
- </div>`)}
2875
- </div>
2876
- </figure>`}renderPanel(){if(!this.panel)return s.nothing;const e=this.msgs.find(f=>f.key===this.panel.key),t=e==null?void 0:e.sources[this.panel.n-1];if(!e||!t)return s.nothing;const i=this.msg,a=_(t,this.panel.n),r=Pe(e.content),l=e.sources.map((f,S)=>_(f,S+1)).filter(f=>f.n!==a.n&&(!r.size||r.has(f.n))),c=`ref:${e.key}:${a.n}`,m=`"${a.text}"
2877
- — ${a.title} [${a.n}]${a.path?`
2878
- ${a.path}`:""}${a.updated?` · Updated ${a.updated}`:""}`,x=[a.updated?`Updated ${a.updated}`:"",a.score!==null?`Relevance ${a.score.toFixed(2)}`:""].filter(Boolean).join(" · ");return s.html`<aside
2879
- class="panel ${this.panelDocked?"docked":"overlay"}"
2880
- part="panel"
2881
- role="region"
2882
- aria-label=${$.fill(i.sourceLabel,{n:a.n})}
2883
- >
2884
- <div class="panel-head">
2885
- <span class="label"
2886
- >${$.fill(i.sourceLabel,{n:a.n})}${a.collection?` · ${a.collection}`:""}</span
2887
- >
2888
- <button type="button" class="text-btn underline" @click=${()=>this.panel=null}>
2889
- ${i.close}
2890
- </button>
2891
- </div>
2892
- <div class="panel-body">
2893
- <div class="panel-meta">
2894
- <h3>${a.title}</h3>
2895
- ${a.path?s.html`<span class="path">${a.path}</span>`:s.nothing}
2896
- ${x?s.html`<span class="meta">${x}</span>`:s.nothing}
2897
- </div>
2898
- <div class="passage-box">
2899
- <span class="text">${a.text}</span>
2900
- <div class="passage-foot">
2901
- <span class="label">${i.citedPassage}</span>
2902
- <button
2903
- type="button"
2904
- class="copy-ref"
2905
- title=${i.copyReference}
2906
- aria-label=${i.copyReference}
2907
- @click=${()=>this.copy(c,m)}
2908
- >
2909
- ${v.copy()}<span>${this.copiedKey===c?i.copied:i.copy}</span>
2910
- </button>
2911
- </div>
2912
- </div>
2913
- </div>
2914
- ${l.length?s.html`<div class="panel-foot">
2915
- <span class="label">${i.alsoCited}</span>
2916
- <div class="chips">
2917
- ${l.map(f=>s.html`<button
2918
- type="button"
2919
- class="chip"
2920
- @click=${()=>this.panel={key:e.key,n:f.n}}
2921
- >
2922
- ${f.n} · ${f.title}
2923
- </button>`)}
2924
- </div>
2925
- </div>`:s.nothing}
2926
- </aside>`}renderComposer(){const e=this.msg,t=this.mode==="rag"?e.placeholderRag:this.mode==="rich"?e.placeholderRich:$.fill(e.placeholderChat,{name:this.assistantName}),i=!this.draft.trim();return s.html`<div class="composer-wrap">
2927
- <div class="composer-col">
2928
- <input
2929
- type="file"
2930
- multiple
2931
- hidden
2932
- accept=".md,.markdown,.txt,.csv,.tsv,.json,.html,.htm,.yaml,.yml,.xml,.log,text/*"
2933
- @change=${a=>{const r=a.target;this.addFiles(r.files).then(()=>r.value="")}}
2934
- />
2935
- <div class="composer-box">
2936
- ${this.busy?s.html`<div class="composer-glow"></div>`:s.nothing}
2937
- <div class="composer ${this.busy?"busy":""}" part="composer">
2938
- ${this.files.length?s.html`<div class="pending-files">
2939
- ${this.files.map(a=>s.html`<div class="pending-file">
2940
- <span class="ext">${rt(a.name)}</span>
2941
- <span class="meta"
2942
- ><span class="name">${a.name}</span
2943
- ><span class="size">${$.formatSize(a.size)}</span></span
2944
- >
2945
- <button
2946
- type="button"
2947
- aria-label=${e.removeFile}
2948
- title=${e.removeFile}
2949
- @click=${()=>this.files=this.files.filter(r=>r!==a)}
2950
- >
2951
- ×
2952
- </button>
2953
- </div>`)}
2954
- </div>`:s.nothing}
2955
- <textarea
2956
- class="input"
2957
- rows="1"
2958
- placeholder=${t}
2959
- aria-label=${t}
2960
- .value=${this.draft}
2961
- @input=${this.onComposerInput}
2962
- @keydown=${this.onComposerKey}
2963
- ></textarea>
2964
- <div class="composer-row">
2965
- <div>
2966
- ${this.allowUpload?s.html`<button
2967
- type="button"
2968
- class="attach"
2969
- title=${e.attach}
2970
- aria-label=${e.attach}
2971
- @click=${()=>{var a;return(a=this.renderRoot.querySelector("input[type=file]"))==null?void 0:a.click()}}
2972
- >
2973
- ${v.clip()}
2974
- </button>`:s.nothing}
2975
- </div>
2976
- ${this.busy?s.html`<button
2977
- type="button"
2978
- class="send stop"
2979
- title=${e.stop}
2980
- aria-label=${e.stop}
2981
- @click=${()=>this.stop()}
2982
- >
2983
- ${v.stop()}
2984
- </button>`:s.html`<button
2985
- type="button"
2986
- class="send"
2987
- title=${e.send}
2988
- aria-label=${e.send}
2989
- ?disabled=${i}
2990
- @click=${()=>this.send()}
2991
- >
2992
- ${v.up()}
2993
- </button>`}
2994
- </div>
2995
- </div>
2996
- ${this.busy?s.html`<div class="composer-ring"><div class="ring"></div></div>`:s.nothing}
2997
- </div>
2998
- <span class="footnote">${$.fill(e.footnote,{name:this.assistantName})}</span>
2999
- </div>
3000
- </div>`}},I=new WeakMap,L=new WeakMap,j=new WeakMap,A=new WeakMap,E=new WeakMap,N=new WeakMap,B=new WeakMap,D=new WeakMap,R=new WeakMap,U=new WeakMap,F=new WeakMap,K=new WeakMap,P=new WeakMap,H=new WeakMap,J=new WeakMap,W=new WeakMap,q=new WeakMap,G=new WeakMap,V=new WeakMap,X=new WeakMap,Y=new WeakMap,Q=new WeakMap,Z=new WeakMap,ee=new WeakMap,te=new WeakMap,ie=new WeakMap,se=new WeakMap,ae=new WeakMap,re=new WeakMap,ne=new WeakMap,oe=new WeakMap,le=new WeakMap,ce=new WeakMap,de=new WeakMap,pe=new WeakMap,he=new WeakMap,ue=new WeakMap,ge=new WeakMap,me=new WeakMap,be=new WeakMap,fe=new WeakMap,xe=new WeakMap,ve=new WeakMap,ye=new WeakMap,ke=new WeakMap,we=new WeakMap,$e=new WeakMap,Ce=new WeakMap,Se=new WeakMap,Te=new WeakMap,ze=new WeakMap,Me=new WeakMap,Oe=new WeakMap,_e=new WeakMap,Ie=new WeakMap,Le=new WeakMap,je=new WeakMap,Ae=new WeakMap,Ee=new WeakMap,Ne=new WeakMap,Be=new WeakMap,nt);Mt(exports.SinglebaseChat,"styles",[$.tokenDefaults,vt]);g([u.property({attribute:!1})],exports.SinglebaseChat.prototype,"client",1);g([u.property({attribute:!1})],exports.SinglebaseChat.prototype,"messages",1);g([u.property({reflect:!0})],exports.SinglebaseChat.prototype,"theme",1);g([u.property({reflect:!0})],exports.SinglebaseChat.prototype,"mode",1);g([u.property({attribute:"render-as"})],exports.SinglebaseChat.prototype,"renderAs",1);g([u.property({reflect:!0})],exports.SinglebaseChat.prototype,"glow",1);g([u.property({converter:M})],exports.SinglebaseChat.prototype,"followups",1);g([u.property({converter:M,attribute:"auto-title"})],exports.SinglebaseChat.prototype,"autoTitle",1);g([u.property()],exports.SinglebaseChat.prototype,"model",1);g([u.property({converter:Je})],exports.SinglebaseChat.prototype,"params",1);g([u.property({attribute:"system-message"})],exports.SinglebaseChat.prototype,"systemMessage",1);g([u.property({converter:Je})],exports.SinglebaseChat.prototype,"retrieval",1);g([u.property({converter:Je})],exports.SinglebaseChat.prototype,"metadata",1);g([u.property({reflect:!0})],exports.SinglebaseChat.prototype,"embed",1);g([u.property({reflect:!0})],exports.SinglebaseChat.prototype,"position",1);g([u.property({converter:Ot})],exports.SinglebaseChat.prototype,"sidebar",1);g([u.property({converter:M,attribute:"show-title"})],exports.SinglebaseChat.prototype,"showTitle",1);g([u.property({attribute:"chat-id"})],exports.SinglebaseChat.prototype,"chatIdAttr",1);g([u.property({attribute:"assistant-name"})],exports.SinglebaseChat.prototype,"assistantName",1);g([u.property({attribute:"logo-url"})],exports.SinglebaseChat.prototype,"logoUrl",1);g([u.property()],exports.SinglebaseChat.prototype,"heading",1);g([u.property()],exports.SinglebaseChat.prototype,"description",1);g([u.property()],exports.SinglebaseChat.prototype,"prompts",1);g([u.property({attribute:"bubble-text"})],exports.SinglebaseChat.prototype,"bubbleText",1);g([u.property({type:Boolean,attribute:"greeting-bubble"})],exports.SinglebaseChat.prototype,"greetingBubble",1);g([u.property({type:Boolean,attribute:"unread-badge"})],exports.SinglebaseChat.prototype,"unreadBadge",1);g([u.property({converter:M,attribute:"allow-upload"})],exports.SinglebaseChat.prototype,"allowUpload",1);g([u.property({converter:M,attribute:"allow-export"})],exports.SinglebaseChat.prototype,"allowExport",1);g([u.property({converter:M})],exports.SinglebaseChat.prototype,"branding",1);g([u.state()],exports.SinglebaseChat.prototype,"chatList",1);g([u.state()],exports.SinglebaseChat.prototype,"listState",1);g([u.state()],exports.SinglebaseChat.prototype,"activeId",1);g([u.state()],exports.SinglebaseChat.prototype,"chatTitle",1);g([u.state()],exports.SinglebaseChat.prototype,"bookmarked",1);g([u.state()],exports.SinglebaseChat.prototype,"msgs",1);g([u.state()],exports.SinglebaseChat.prototype,"loadingThread",1);g([u.state()],exports.SinglebaseChat.prototype,"threadError",1);g([u.state()],exports.SinglebaseChat.prototype,"busy",1);g([u.state()],exports.SinglebaseChat.prototype,"draft",1);g([u.state()],exports.SinglebaseChat.prototype,"files",1);g([u.state()],exports.SinglebaseChat.prototype,"search",1);g([u.state()],exports.SinglebaseChat.prototype,"sidebarOpen",1);g([u.state()],exports.SinglebaseChat.prototype,"width",1);g([u.state()],exports.SinglebaseChat.prototype,"panel",1);g([u.state()],exports.SinglebaseChat.prototype,"menuOpen",1);g([u.state()],exports.SinglebaseChat.prototype,"editingKey",1);g([u.state()],exports.SinglebaseChat.prototype,"editDraft",1);g([u.state()],exports.SinglebaseChat.prototype,"editingTitle",1);g([u.state()],exports.SinglebaseChat.prototype,"renamingId",1);g([u.state()],exports.SinglebaseChat.prototype,"toast",1);g([u.state()],exports.SinglebaseChat.prototype,"copiedKey",1);g([u.state()],exports.SinglebaseChat.prototype,"retrievalOpen",1);g([u.state()],exports.SinglebaseChat.prototype,"arrivedKey",1);g([u.state()],exports.SinglebaseChat.prototype,"dragging",1);g([u.state()],exports.SinglebaseChat.prototype,"showJump",1);g([u.state()],exports.SinglebaseChat.prototype,"offline",1);g([u.state()],exports.SinglebaseChat.prototype,"isOpen",1);g([u.state()],exports.SinglebaseChat.prototype,"expanded",1);g([u.state()],exports.SinglebaseChat.prototype,"bubble",1);g([u.state()],exports.SinglebaseChat.prototype,"seen",1);g([u.state()],exports.SinglebaseChat.prototype,"mobile",1);exports.SinglebaseChat=g([u.customElement("singlebase-chat")],exports.SinglebaseChat);exports.adaptBlocks=ht;exports.citedNumbers=Pe;exports.defaultChatMessages=ot;exports.describeSource=_;exports.parseInline=pt;exports.parseMarkdown=ct;exports.resolveChatMessages=lt;exports.splitFollowups=He;
3001
- //# sourceMappingURL=chat-DRenTJlI.cjs.map