bunnyquery 1.8.5 → 1.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # BunnyQuery
1
+ # BunnyQuery Widget
2
2
 
3
3
  An embeddable, dependency-free AI chat widget for [Skapi](https://www.skapi.com)-powered
4
4
  projects. Drop it into any web page and your users get a full chat experience:
package/bunnyquery.css CHANGED
@@ -37,6 +37,8 @@
37
37
  --bq-info-bg: #e8f0fb;
38
38
  --bq-info-border: #3c94ff;
39
39
  --bq-placeholder: #aaaaaa;
40
+ /* hard offset shadow for bubbles; swapped for a light edge in dark */
41
+ --bq-shadow: rgba(0, 0, 0, 0.12);
40
42
  --bq-code-bg: #1e1e1e;
41
43
  --bq-code-fg: #f5f5f5;
42
44
  --bq-icon-invert: 0;
@@ -48,7 +50,8 @@
48
50
  --bq-ink: #ebebeb;
49
51
  --bq-paper: #000;
50
52
  --bq-muted: #a0a0a0;
51
- --bq-line: #3d3d3d;
53
+ /* was #3d3d3d — brighter edges, matching the admin's dark tokens */
54
+ --bq-line: #484848;
52
55
  --bq-hover-bg: #252525;
53
56
  --bq-main: #f06292;
54
57
  --bq-light-main: #f48fb1;
@@ -65,6 +68,8 @@
65
68
  --bq-info-bg: #162230;
66
69
  --bq-info-border: #42a5f5;
67
70
  --bq-placeholder: #787878;
71
+ /* light edge — a black hard shadow is invisible on the dark paper */
72
+ --bq-shadow: rgba(255, 255, 255, 0.16);
68
73
  --bq-icon-invert: 1;
69
74
  }
70
75
 
@@ -570,28 +575,25 @@
570
575
  gap: 0.5rem;
571
576
  }
572
577
 
573
- /* read-only agent (platform + model) badge */
574
- .bq-agent-badge {
575
- display: inline-flex;
576
- align-items: center;
577
- gap: 0.45rem;
578
- padding: 0.3rem 0.6rem;
579
- border: 1px solid var(--bq-main);
580
- background: var(--bq-main-bg);
581
- font-size: 0.75rem;
582
- font-family: var(--bq-mono);
583
- color: var(--bq-main);
584
- max-width: 100%;
585
- overflow: hidden;
578
+ /* landing-style brand header on the chat view: [bunny] BunnyQuery · project */
579
+ .bq-brand {
580
+ min-width: 0;
581
+ font-size: 0.8rem;
582
+ color: var(--bq-muted);
586
583
  }
587
- .bq-agent-badge-logo {
584
+ .bq-brand-icon {
588
585
  width: 1.1rem;
589
586
  height: 1.1rem;
590
587
  object-fit: contain;
591
588
  flex: 0 0 auto;
592
589
  }
593
- .bq-agent-badge-model {
594
- color: var(--bq-muted);
590
+ .bq-brand-name,
591
+ .bq-brand-sep {
592
+ flex: 0 0 auto;
593
+ white-space: nowrap;
594
+ }
595
+ .bq-brand-project {
596
+ min-width: 0;
595
597
  overflow: hidden;
596
598
  text-overflow: ellipsis;
597
599
  white-space: nowrap;
@@ -760,7 +762,7 @@
760
762
  cursor: pointer;
761
763
  z-index: 1;
762
764
  }
763
- .bq-attach-btn:hover:not(:disabled) { color: var(--bq-main); }
765
+ .bq-attach-btn:hover:not(:disabled) { color: var(--bq-main);transform: none; }
764
766
  .bq-attach-btn:disabled { opacity: 0.5; cursor: not-allowed; }
765
767
  .bq-attach-input { display: none; }
766
768
  .bq-input {
@@ -824,6 +826,40 @@
824
826
  pointer-events: none;
825
827
  }
826
828
  .bq-attachment.is-uploading > * { position: relative; z-index: 1; }
829
+ /* The two indeterminate phases, both drawn as a barber pole over the full chip
830
+ because neither has a percentage to show (mirror of agent.vue):
831
+ is-preparing: before the first byte-progress event, while get-signed-url
832
+ is in flight. A bar at 0% here reads as a stalled upload.
833
+ is-finalizing: bytes done, post-upload work (signed url, src:: record,
834
+ indexing dispatch) still running. A bar frozen at a solid
835
+ 100% reads as hung.
836
+ Between them the bar is determinate and driven by --att-progress. */
837
+ .bq-attachment.is-preparing::before,
838
+ .bq-attachment.is-finalizing::before {
839
+ width: 100%;
840
+ background: repeating-linear-gradient(
841
+ -45deg,
842
+ color-mix(in srgb, var(--bq-main) 22%, transparent) 0 8px,
843
+ color-mix(in srgb, var(--bq-main) 10%, transparent) 8px 16px
844
+ );
845
+ background-size: 22.6px 100%;
846
+ animation: bq-att-barber 0.8s linear infinite;
847
+ transition: none;
848
+ }
849
+ .bq-attachment.is-preparing .bq-attachment-meta::after,
850
+ .bq-attachment.is-finalizing .bq-attachment-meta::after {
851
+ content: ".";
852
+ display: inline-block;
853
+ width: 1.1em;
854
+ text-align: left;
855
+ animation: bq-att-dots 1.2s steps(1) infinite;
856
+ }
857
+ @keyframes bq-att-barber { to { background-position: 22.6px 0; } }
858
+ @keyframes bq-att-dots {
859
+ 0% { content: "."; }
860
+ 33% { content: ".."; }
861
+ 66% { content: "..."; }
862
+ }
827
863
  .bq-attachment.is-error { border-color: var(--bq-danger); background: var(--bq-danger-bg); }
828
864
  .bq-attachment.is-error .bq-attachment-meta,
829
865
  .bq-attachment.is-error .bq-attachment-name { color: var(--bq-danger); }
@@ -1024,19 +1060,58 @@
1024
1060
  .bq-message.is-assistant { justify-content: flex-start; }
1025
1061
 
1026
1062
  .bq-bubble {
1063
+ max-width: 100%;
1027
1064
  padding: 0.55rem 0.7rem;
1028
1065
  border: 1px solid var(--bq-line);
1029
1066
  white-space: pre-wrap;
1030
1067
  line-height: 1.45;
1031
1068
  font-size: 0.83rem;
1032
1069
  background: var(--bq-paper);
1070
+ /* the house hard shadow (same as buttons/cards); themed so the edge
1071
+ stays visible on a dark paper (fallback = the light value) */
1072
+ box-shadow: 2px 2px var(--bq-shadow, rgba(0, 0, 0, 0.12));
1033
1073
  }
1034
1074
  .bq-bubble span { word-break: break-word; }
1035
- .bq-message.is-user .bq-bubble { background: var(--bq-paper); }
1036
- .bq-message.is-assistant:not(.is-error) .bq-bubble {
1037
- background: var(--bq-success-bg);
1038
- border-color: var(--bq-success-border);
1075
+ /* User asks in the accent tint, the assistant answers on plain paper (the
1076
+ base .bq-bubble already carries paper + line, so assistant needs no rule).
1077
+ --bq-main-bg is the widget's own token; the admin bridges it to
1078
+ --bq-pink-bg. */
1079
+ .bq-message.is-user .bq-bubble {
1080
+ background: var(--bq-main-bg);
1081
+ /* flat: the hard shadow stays on replies only */
1082
+ box-shadow: none;
1039
1083
  }
1084
+
1085
+ /* Bunny mark opening every ordinary reply: floated so it sits INSIDE the
1086
+ bubble on the first text line with the copy wrapping beside it. Deliberately
1087
+ absent from everything that is not a plain answer: user bubbles, error and
1088
+ cancelled bubbles, indexing passes (the collapsed rows' members), and the
1089
+ empty-chat greeting. Inlined data URI so both consumers get it without
1090
+ markup or asset-hosting changes. */
1091
+ .bq-message.is-assistant:not(.is-error):not(.is-cancelled):not(.bq-index-pass):not(.bq-empty-greeting) .bq-bubble::before {
1092
+ content: "";
1093
+ /* block, not float: the bunny takes the first line by itself and the
1094
+ message starts on the next line below it */
1095
+ display: block;
1096
+ width: 2.6em;
1097
+ height: 2.6em;
1098
+ left: -4px;
1099
+ top: -4px;
1100
+ position: relative;
1101
+ background: url("data:image/png;base64,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") center / contain no-repeat;
1102
+ }
1103
+ /* While the reply is still "Thinking..." the bubble holds only the dot-trail
1104
+ loader: put the bunny INLINE with the dots instead of stacking above them.
1105
+ Settled replies keep the block bunny with the message on the next line. */
1106
+ .bq-message.is-assistant:not(.is-error):not(.is-cancelled):not(.bq-index-pass):not(.bq-empty-greeting) .bq-bubble:has(> .bq-loader)::before {
1107
+ display: inline-block;
1108
+ vertical-align: middle;
1109
+ margin-right: 0.4rem;
1110
+ }
1111
+ .bq-message.is-assistant:not(.is-error):not(.is-cancelled):not(.bq-index-pass):not(.bq-empty-greeting) .bq-bubble:has(> .bq-loader) > .bq-loader {
1112
+ vertical-align: middle;
1113
+ }
1114
+
1040
1115
  .bq-message.is-error .bq-bubble {
1041
1116
  background: var(--bq-danger-bg);
1042
1117
  border-color: var(--bq-danger);
@@ -1180,6 +1255,24 @@
1180
1255
  state does not know. A slow fade says "pending" without claiming progress. */
1181
1256
  .bq-index-group.is-resolving .bq-index-icon svg { animation: bq-index-fade 1.6s ease-in-out infinite; }
1182
1257
  @keyframes bq-index-fade { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
1258
+ /* Expand-triggered history fetch: spinning arrows in the row head while the
1259
+ run's passes are being paged in. A SEPARATE element from the status icon on
1260
+ purpose — the row keeps its verdict (green check, grey clock) and this only
1261
+ says "fetching more detail about it", whatever that verdict is. */
1262
+ .bq-index-fetch {
1263
+ width: 0.85rem;
1264
+ height: 0.85rem;
1265
+ flex: none;
1266
+ margin-left: 0.35rem;
1267
+ color: var(--bq-muted);
1268
+ display: inline-flex;
1269
+ }
1270
+ .bq-index-fetch svg { width: 100%; height: 100%; display: block; animation: bq-index-spin 1.1s linear infinite; }
1271
+ /* The in-row loading note under an OPEN row while its passes stream in. */
1272
+ .bq-index-note .bq-loader { margin-left: 0.15rem; }
1273
+ @media (prefers-reduced-motion: reduce) {
1274
+ .bq-index-fetch svg { animation-duration: 3s; }
1275
+ }
1183
1276
  @media (prefers-reduced-motion: reduce) {
1184
1277
  .bq-index-group.is-active .bq-index-icon svg { animation-duration: 3s; }
1185
1278
  /* A fade has no end state to settle on, so it stops rather than slows. */
@@ -1217,7 +1310,7 @@
1217
1310
  line-height: 1.3;
1218
1311
  letter-spacing: 0.02em;
1219
1312
  cursor: pointer;
1220
- box-shadow: none;
1313
+ box-shadow: 2px 2px rgba(0, 0, 0, 0.12);
1221
1314
  opacity: 0.8;
1222
1315
  }
1223
1316
  .bq-index-cancel:hover:not(.is-disabled) { background: var(--bq-warning-bg); color: var(--bq-warning); opacity: 1; }
@@ -1242,6 +1335,18 @@
1242
1335
  border-left: 2px solid var(--bq-line);
1243
1336
  }
1244
1337
  .bq-message.bq-index-pass .bq-bubble { font-size: 0.78rem; }
1338
+ /* Passes inside a collapsed indexing row keep the pre-swap, flat look: no
1339
+ hard shadow, requests on plain paper, responses in the success tint. The
1340
+ state tints stay on top of this — error/cancelled danger and the queued
1341
+ warning are excluded here so those rules keep winning. */
1342
+ .bq-message.bq-index-pass .bq-bubble { box-shadow: none; }
1343
+ .bq-message.bq-index-pass.is-user:not(.is-cancelled):not(.is-pending-older) .bq-bubble {
1344
+ background: var(--bq-paper);
1345
+ }
1346
+ .bq-message.bq-index-pass.is-assistant:not(.is-error):not(.is-cancelled) .bq-bubble {
1347
+ background: var(--bq-success-bg);
1348
+ border-color: var(--bq-success-border);
1349
+ }
1245
1350
  /* Close the run: the next ordinary message needs its normal breathing room.
1246
1351
  NOT scoped to .bq-message: the trailing loader below is a run member too, and
1247
1352
  requiring .bq-message would silently drop the gap whenever it is the last one. */
@@ -1259,10 +1364,12 @@
1259
1364
  font-size: 0.78rem;
1260
1365
  color: var(--bq-muted);
1261
1366
  }
1262
- /* An open row animates for as long as the file is indexing, which can be minutes.
1263
- Readers who ask for less motion get the static end state. */
1367
+ /* An open row animates for as long as the file is indexing, which can be
1368
+ minutes, and the user-side drafting bubble animates for as long as a draft
1369
+ sits in the composer. Readers who ask for less motion get the static dots. */
1264
1370
  @media (prefers-reduced-motion: reduce) {
1265
- .bq-index-tail .bq-loader::after { animation: none; content: '...'; }
1371
+ .bq-index-tail .bq-loader::after,
1372
+ .bq-user-drafting .bq-loader::after { animation: none; content: '...'; }
1266
1373
  }
1267
1374
  .bq-index-note {
1268
1375
  padding: 0 0.6rem 0.45rem;
@@ -1428,3 +1535,38 @@
1428
1535
  .bq-md strong { font-weight: 600; }
1429
1536
  .bq-md em { font-style: italic; }
1430
1537
  .bq-md del { text-decoration: line-through; }
1538
+ /* ---- host-page insulation -------------------------------------------------*/
1539
+ /* The markdown above renders into whatever page this chat sits in: the admin
1540
+ app with its own global stylesheet, or - for the embedded widget - a HOST
1541
+ page with arbitrary CSS. Element-level globals leak straight into it, and
1542
+ form controls are the class nothing above styles on purpose: the admin app
1543
+ styles every <input> as a 3rem bordered mono text field, which turned a GFM
1544
+ task-list checkbox into a giant text box. `revert` rolls each property back
1545
+ to the BROWSER default (as if no author CSS existed), which is the honest
1546
+ baseline for a control the markdown produced; `initial`/`unset` would
1547
+ instead strip even the user-agent's own control styling. */
1548
+ .bq-md input,
1549
+ .bq-md select,
1550
+ .bq-md textarea,
1551
+ .bq-md button {
1552
+ all: revert;
1553
+ }
1554
+ /* GFM task list: `- [x] item` renders as a disabled checkbox in the list item.
1555
+ Re-state the little we DO want on top of the revert: sit on the text
1556
+ baseline with a small gap, brand accent. The geometry (width/height/
1557
+ min-height/padding) is pinned explicitly, at higher specificity than the
1558
+ revert rule, so a host sheet whose input rules are more specific than
1559
+ `.bq-md input` still loses the properties that actually break layout. */
1560
+ .bq-md input[type="checkbox"] {
1561
+ width: auto;
1562
+ height: auto;
1563
+ min-height: 0;
1564
+ padding: 0;
1565
+ margin: 0 0.4em 0.1em 0;
1566
+ vertical-align: middle;
1567
+ accent-color: var(--bq-main);
1568
+ }
1569
+ /* GitHub-style: a task-list item shows the checkbox INSTEAD of a bullet, not
1570
+ next to one. :has() is safe here - every supported browser ships it, and a
1571
+ miss only means a redundant bullet. */
1572
+ .bq-md li:has(> input[type="checkbox"]:first-child) { list-style: none; }