bunnyquery 1.10.4 → 1.10.6

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.10.4",
3
+ "version": "1.10.6",
4
4
  "description": "Embeddable BunnyQuery AI chat widget + its framework-agnostic chat engine",
5
5
  "main": "bunnyquery.js",
6
6
  "exports": {
@@ -81,6 +81,13 @@ const INDEX_DISPATCH_CLAIM_MS = 2 * 60 * 1000;
81
81
  // that is still alive. Fixed and finite: this must never become a poll.
82
82
  const WORKER_PASS_ADOPT_ATTEMPTS = [0, 2000, 6000];
83
83
 
84
+ /** How recent a loaded indexing pass has to be to count as evidence that a worker
85
+ * chain may still be advancing. Generous on purpose: it only has to outlast the
86
+ * gap between two passes of one file, and the cost of being wrong is three queue
87
+ * round trips, while the cost of being too tight is a file that reads "Indexed"
88
+ * while it is still being read. */
89
+ const RECENT_INDEX_PASS_EVIDENCE_MS = 10 * 60 * 1000;
90
+
84
91
  // awaitIndexingDrained: how often it re-asks the background-indexing queue, and
85
92
  // how many consecutive empty answers it needs before believing the chains are
86
93
  // over. More than one for the same reason the adopt ladder above looks twice —
@@ -4435,7 +4442,38 @@ export class ChatSession {
4435
4442
  // full passive ladder for indexing that does not exist.
4436
4443
  var found = false;
4437
4444
  this.historyItemPolls.forEach(function (h: any) { if (h && h.kind === 'bg') found = true; });
4438
- return found;
4445
+ if (found) return true;
4446
+
4447
+ // A chain this client did not START leaves none of the three signals above,
4448
+ // and they are all signals of LOCAL DISPATCH: the bgTaskQueue entry covers
4449
+ // only the pass this page sent and is spliced out as soon as it settles, a
4450
+ // reload clears that array outright, and liveIndexKeys is empty in exactly
4451
+ // the moment the probe just missed. A run begun on the db-files page and
4452
+ // then opened in the chat has none of them, so the ladder never climbed for
4453
+ // it: one probe landing in the gap between pass N resolving and pass N+1
4454
+ // being enqueued marked the file finished, and with no local pass left to
4455
+ // settle, nothing asked again. The row stayed green on a file still being
4456
+ // read.
4457
+ //
4458
+ // The passes themselves are the evidence in that case. Bounded by recency,
4459
+ // because the thing this gate exists to prevent is the climb running on an
4460
+ // idle tab whose indexing finished long ago - and such a chat's newest
4461
+ // indexing pass is hours or days old, so it still does not climb.
4462
+ // Date.now(), NOT nowMs(): `_ts` is a wall-clock epoch (the same clock the
4463
+ // run:: records are stamped with), while nowMs() is performance.now() --
4464
+ // milliseconds since process start. Subtracting the window from that gives a
4465
+ // NEGATIVE cutoff, every epoch `_ts` clears it, and the gate would then be
4466
+ // true for any chat that has ever indexed anything: exactly the always-climb
4467
+ // this gate was added to stop.
4468
+ var cutoff = Date.now() - RECENT_INDEX_PASS_EVIDENCE_MS;
4469
+ var msgs = this.state.messages;
4470
+ for (var mi = msgs.length - 1; mi >= 0; mi--) {
4471
+ var m = msgs[mi];
4472
+ if (!m || !m._indexFile) continue;
4473
+ if (typeof m._ts !== 'number') continue;
4474
+ if (m._ts >= cutoff) return true;
4475
+ }
4476
+ return false;
4439
4477
  }
4440
4478
 
4441
4479
  /** Any of these ids still queued or still polled, i.e. surviving work. */