bunnyquery 1.5.2 → 1.5.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bunnyquery",
3
- "version": "1.5.2",
3
+ "version": "1.5.4",
4
4
  "description": "Embeddable BunnyQuery AI chat widget + its framework-agnostic chat engine",
5
5
  "main": "bunnyquery.js",
6
6
  "exports": {
@@ -774,18 +774,26 @@ export class ChatSession {
774
774
  var id = this.host.getIdentity();
775
775
  var svcId = id.serviceId, plat = id.platform;
776
776
  if (!svcId || plat === 'none' || !this.host.isViewMounted()) return;
777
+ // Index messages by _serverItemId ONCE, so the per-entry presence/pending
778
+ // checks below are O(1) instead of a full messages.some() scan each. With a
779
+ // large bg queue (bulk uploads) the old nested scan was O(queue x messages)
780
+ // per drain, and the drain runs once per uploaded file (O(n^3) overall).
781
+ var presentIds: { [id: string]: boolean } = {};
782
+ var pendingIds: { [id: string]: boolean } = {};
783
+ this.state.messages.forEach(function (m) {
784
+ var sid = m._serverItemId;
785
+ if (sid == null) return;
786
+ presentIds[sid] = true;
787
+ if (m.isPending || m.isPendingInProcess || m.isPendingQueued) pendingIds[sid] = true;
788
+ });
777
789
  for (var i = this.bgTaskQueue.length - 1; i >= 0; i--) {
778
790
  var e = this.bgTaskQueue[i];
779
791
  if (e.serviceId !== svcId || e.platform !== plat) continue;
780
- var present = this.state.messages.some(function (m) { return m._serverItemId === e.id; });
781
- var stillPending = this.state.messages.some(function (m) {
782
- return m._serverItemId === e.id && (m.isPending || m.isPendingInProcess || m.isPendingQueued);
783
- });
784
- if (present && !stillPending) this.bgTaskQueue.splice(i, 1);
792
+ if (presentIds[e.id] && !pendingIds[e.id]) this.bgTaskQueue.splice(i, 1);
785
793
  }
786
794
  this.bgTaskQueue.forEach(function (entry) {
787
795
  if (entry.serviceId !== svcId || entry.platform !== plat) return;
788
- if (self.state.messages.some(function (m) { return m._serverItemId === entry.id; })) return;
796
+ if (presentIds[entry.id]) return;
789
797
  var isRunning = entry.status === 'running';
790
798
  var userBubble: ChatMessage = { role: 'user', content: self.host.formatIndexingLabel(entry.filename, entry.mime, entry.size, entry.storagePath, entry.isReindex), isBackgroundTask: true, _serverItemId: entry.id };
791
799
  if (isRunning) userBubble.isPendingInProcess = true; else userBubble.isPendingQueued = true;
@@ -793,6 +801,7 @@ export class ChatSession {
793
801
  if (isRunning) {
794
802
  self.state.messages.push({ role: 'assistant', content: '', isPending: true, isPendingInProcess: true, isBackgroundTask: true, _serverItemId: entry.id });
795
803
  }
804
+ presentIds[entry.id] = true; // keep the index consistent with the pushed bubbles
796
805
  self.host.notify(); self.updateHistoryCache(); self.host.scrollToBottom(false);
797
806
  if (!self.historyItemPolls.has(entry.id) && typeof entry.poll === 'function') {
798
807
  self.historyItemPolls.set(entry.id, true);
package/src/widget.css CHANGED
@@ -241,14 +241,16 @@
241
241
  /* ============================================================================
242
242
  * AUTH VIEWS (login / signup / forgot / verify / settings)
243
243
  * ==========================================================================*/
244
- /* padded parent that nests a standalone page (login / signup / verify / …) */
244
+ /* padded parent that nests a standalone page (login / signup / verify / …).
245
+ Sits below the shared .bq-section-title header (the top-left service badge),
246
+ so the top padding is small — the header supplies the top spacing. */
245
247
  .bq-page {
246
248
  flex: 1;
247
249
  min-height: 0;
248
250
  overflow-y: auto;
249
251
  display: flex;
250
252
  flex-direction: column;
251
- padding: 2.5rem 1.5rem;
253
+ padding: 1rem 1.5rem 2.5rem;
252
254
  }
253
255
  .bq-settings {
254
256
  flex: 1;
@@ -259,6 +261,15 @@
259
261
  color: var(--bq-ink);
260
262
  }
261
263
 
264
+ /* full-box loading view: fill the space above the footer and center the bunny */
265
+ .bq-page-loading {
266
+ flex: 1;
267
+ min-height: 0;
268
+ display: flex;
269
+ align-items: center;
270
+ justify-content: center;
271
+ }
272
+
262
273
  .bq-page-footer {
263
274
  flex-shrink: 0;
264
275
  text-align: center;
@@ -271,6 +282,12 @@
271
282
  text-decoration: none;
272
283
  }
273
284
  .bq-page-footer-link:hover { text-decoration: underline; }
285
+ .bq-page-footer-version {
286
+ font-family: var(--bq-mono);
287
+ font-size: 0.7rem;
288
+ color: var(--bq-muted);
289
+ margin-top: 0.25rem;
290
+ }
274
291
 
275
292
  .bq-settings-title {
276
293
  font-size: 1.5rem;
@@ -554,11 +571,11 @@
554
571
  align-items: center;
555
572
  gap: 0.45rem;
556
573
  padding: 0.3rem 0.6rem;
557
- border: 1px solid var(--bq-line);
558
- background: var(--bq-paper);
574
+ border: 1px solid var(--bq-main);
575
+ background: var(--bq-main-bg);
559
576
  font-size: 0.75rem;
560
577
  font-family: var(--bq-mono);
561
- color: var(--bq-ink);
578
+ color: var(--bq-main);
562
579
  max-width: 100%;
563
580
  overflow: hidden;
564
581
  }
@@ -603,7 +620,16 @@
603
620
  margin: 0 auto;
604
621
  padding: 1.25rem 0 2rem;
605
622
  }
606
- .bq-chat-settings-loading { text-align: center; padding: 2.5rem 0; color: var(--bq-muted); }
623
+ /* fill the messages box and center the bunny (matches .bq-history-loading.is-initial).
624
+ Resolves against .bq-messages (position: relative), not the max-width settings wrap. */
625
+ .bq-chat-settings-loading {
626
+ position: absolute;
627
+ inset: 0;
628
+ display: flex;
629
+ align-items: center;
630
+ justify-content: center;
631
+ color: var(--bq-muted);
632
+ }
607
633
 
608
634
  /* chat container + scroll area */
609
635
  .bq-chat {
@@ -751,6 +777,8 @@
751
777
  .bq-input::placeholder { color: var(--bq-placeholder); }
752
778
  .bq-input:focus { outline: none; border-color: var(--bq-ink); }
753
779
  .bq-input:disabled { opacity: 0.5; cursor: default; }
780
+ /* Attach button hidden (frozen DB): reclaim the reserved left gutter. */
781
+ .bq-input.bq-input--noattach { padding-left: 0.7rem; }
754
782
  .bq-input-row .btn {
755
783
  align-self: flex-end;
756
784
  min-width: 5.5rem;