bunnyquery 1.3.4 → 1.3.5

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/dist/engine.d.mts CHANGED
@@ -475,6 +475,8 @@ declare class ChatSession {
475
475
  private typewriterQueue;
476
476
  enqueueTypewrite(idx: number, fullText: string, localId?: string): Promise<any>;
477
477
  typewriteLatestReply(key: string): Promise<any>;
478
+ _removeStrayPendingAssistants(): void;
479
+ _clearPendingUserBubble(itemId: string): void;
478
480
  resumePendingRequest(token: number): Promise<void>;
479
481
  handleHistoryItemResolution(itemId: string, response: any, platform: string): void;
480
482
  applyHistoryItemResolution(itemId: string, response: any, platform: string): void;
package/dist/engine.d.ts CHANGED
@@ -475,6 +475,8 @@ declare class ChatSession {
475
475
  private typewriterQueue;
476
476
  enqueueTypewrite(idx: number, fullText: string, localId?: string): Promise<any>;
477
477
  typewriteLatestReply(key: string): Promise<any>;
478
+ _removeStrayPendingAssistants(): void;
479
+ _clearPendingUserBubble(itemId: string): void;
478
480
  resumePendingRequest(token: number): Promise<void>;
479
481
  handleHistoryItemResolution(itemId: string, response: any, platform: string): void;
480
482
  applyHistoryItemResolution(itemId: string, response: any, platform: string): void;
package/dist/engine.mjs CHANGED
@@ -1246,6 +1246,7 @@ var ChatSession = class {
1246
1246
  this.enqueueTypewrite(aiIdx, answer, lid);
1247
1247
  }
1248
1248
  }
1249
+ this._removeStrayPendingAssistants();
1249
1250
  this.promoteNextQueuedToRunning();
1250
1251
  this.updateHistoryCache();
1251
1252
  this.host.notify();
@@ -1288,6 +1289,7 @@ var ChatSession = class {
1288
1289
  if (thPos2 !== -1) this.state.messages.splice(thPos2, 1);
1289
1290
  }
1290
1291
  if (serverId) this.cancelledServerIds.delete(serverId);
1292
+ this._removeStrayPendingAssistants();
1291
1293
  this.promoteNextQueuedToRunning();
1292
1294
  this.updateHistoryCache();
1293
1295
  this.host.notify();
@@ -1301,6 +1303,7 @@ var ChatSession = class {
1301
1303
  return;
1302
1304
  }
1303
1305
  this.insertAtTarget({ role: "assistant", content: getErrorMessage(err), isError: true }, targetIdx);
1306
+ this._removeStrayPendingAssistants();
1304
1307
  this.promoteNextQueuedToRunning();
1305
1308
  this.updateHistoryCache();
1306
1309
  this.host.notify();
@@ -1462,16 +1465,48 @@ var ChatSession = class {
1462
1465
  if (pendingIdx === -1) return Promise.resolve();
1463
1466
  if (latest.isError || !latest.content) {
1464
1467
  this.state.messages[pendingIdx] = { role: "assistant", content: latest.content || "", isError: !!latest.isError };
1468
+ this._removeStrayPendingAssistants();
1465
1469
  this.host.notify();
1466
1470
  this.promoteNextQueuedToRunning();
1467
1471
  return Promise.resolve();
1468
1472
  }
1469
1473
  var lid = this._newLocalId();
1470
1474
  this.state.messages[pendingIdx] = { role: "assistant", content: "", isPending: false, _localId: lid };
1475
+ this._removeStrayPendingAssistants();
1471
1476
  this.host.notify();
1472
1477
  this.promoteNextQueuedToRunning();
1473
1478
  return this.enqueueTypewrite(pendingIdx, latest.content, lid);
1474
1479
  }
1480
+ // Remove any leftover non-background pending ("Thinking…") assistant bubbles.
1481
+ // There is normally at most ONE such bubble at a time (promoteNext* refuses to
1482
+ // add a second), so any extra is a duplicate — it appears when a concurrent
1483
+ // history refetch re-maps the still-"running" turn into a pending placeholder
1484
+ // (with a real _serverItemId) while the local pending bubble (no _serverItemId)
1485
+ // is rescued and re-appended (see loadHistory rescue below). Each resolve path
1486
+ // only replaces the FIRST pending bubble, so without this a stray "Thinking…"
1487
+ // survives next to the reply/error. MUST run AFTER the resolved bubble has been
1488
+ // made non-pending and BEFORE promoteNext*() (so a freshly-promoted Thinking,
1489
+ // which is added only once no pending assistant remains, is preserved).
1490
+ _removeStrayPendingAssistants() {
1491
+ for (var k = this.state.messages.length - 1; k >= 0; k--) {
1492
+ var m = this.state.messages[k];
1493
+ if (m.isPending && m.role === "assistant" && !m.isBackgroundTask) this.state.messages.splice(k, 1);
1494
+ }
1495
+ }
1496
+ // Drop the pending flags on the resolved turn's USER bubble (preserving its
1497
+ // content + background-task marker). Needed because a bg "Indexing:" turn's user
1498
+ // bubble carries isPendingInProcess; leaving it set keeps the bubble visually
1499
+ // stuck and keeps its bgTaskQueue entry alive forever.
1500
+ _clearPendingUserBubble(itemId) {
1501
+ var uIdx = this.state.messages.findIndex(function(m) {
1502
+ return m.role === "user" && m._serverItemId === itemId && (m.isPendingInProcess || m.isPendingQueued || m.isSendingToServer);
1503
+ });
1504
+ if (uIdx === -1) return;
1505
+ var u = this.state.messages[uIdx];
1506
+ var cleaned = { role: "user", content: u.content, _serverItemId: itemId };
1507
+ if (u.isBackgroundTask) cleaned.isBackgroundTask = true;
1508
+ this.state.messages[uIdx] = cleaned;
1509
+ }
1475
1510
  // If an immediate-send request for the current cache key is still in flight
1476
1511
  // (e.g. the view unmounted then remounted mid-request), show the sending
1477
1512
  // state, await it, then render the reply from the cache. Skipped when the
@@ -1510,6 +1545,7 @@ var ChatSession = class {
1510
1545
  return m.isPending && m._serverItemId === itemId;
1511
1546
  });
1512
1547
  if (idx !== -1) {
1548
+ this._clearPendingUserBubble(itemId);
1513
1549
  if (isErr) {
1514
1550
  this.state.messages[idx] = { role: "assistant", content: answer, isError: true, _serverItemId: itemId };
1515
1551
  this.host.notify();
@@ -1659,12 +1695,16 @@ var ChatSession = class {
1659
1695
  self.state.messages.forEach(function(m) {
1660
1696
  if (m.isCancelled && m._serverItemId) locallyCancelled[m._serverItemId] = 1;
1661
1697
  });
1698
+ var mappedHasPendingAssistant = mapped.some(function(m) {
1699
+ return m.isPending && m.role === "assistant" && !m.isBackgroundTask;
1700
+ });
1662
1701
  var rescued = [];
1663
1702
  for (var ri = 0; ri < self.state.messages.length; ri++) {
1664
1703
  var mm = self.state.messages[ri];
1665
1704
  if (mm.isBackgroundTask) continue;
1666
1705
  if (mm._serverItemId && serverIds[mm._serverItemId]) continue;
1667
1706
  if (!mm._serverItemId) {
1707
+ if (mappedHasPendingAssistant) continue;
1668
1708
  if (mm.isSendingToServer || mm.isPendingQueued || mm.isPendingInProcess || mm.isPending) rescued.push(mm);
1669
1709
  else if (self.state.sending && mm.role === "user") {
1670
1710
  var next = self.state.messages[ri + 1];