bunnyquery 1.4.5 → 1.4.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/bunnyquery.js +134 -77
- package/dist/engine.cjs +133 -75
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.mjs +133 -75
- package/dist/engine.mjs.map +1 -1
- package/package.json +1 -1
- package/src/engine/session.ts +167 -70
package/dist/engine.mjs
CHANGED
|
@@ -1068,10 +1068,18 @@ function mapHistoryListToMessages(list, platform, opts) {
|
|
|
1068
1068
|
}
|
|
1069
1069
|
|
|
1070
1070
|
// src/engine/session.ts
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1071
|
+
var _g = typeof globalThis !== "undefined" ? globalThis : {};
|
|
1072
|
+
function nowMs() {
|
|
1073
|
+
return _g.performance && typeof _g.performance.now === "function" ? _g.performance.now() : Date.now();
|
|
1074
|
+
}
|
|
1075
|
+
function nextFrame(cb) {
|
|
1076
|
+
if (typeof _g.requestAnimationFrame === "function") {
|
|
1077
|
+
_g.requestAnimationFrame(cb);
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
setTimeout(function() {
|
|
1081
|
+
cb(nowMs());
|
|
1082
|
+
}, 16);
|
|
1075
1083
|
}
|
|
1076
1084
|
var ChatSession = class {
|
|
1077
1085
|
constructor(host) {
|
|
@@ -1158,35 +1166,26 @@ var ChatSession = class {
|
|
|
1158
1166
|
if (dispatchItemId) self.historyItemPolls.delete(dispatchItemId);
|
|
1159
1167
|
var existing = self.aiChatHistoryCache[params.key] || { messages: [], endOfList: false, startKeyHistory: [] };
|
|
1160
1168
|
var reply = { role: "assistant", content: result.content, isError: result.isError };
|
|
1161
|
-
var
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
} else {
|
|
1169
|
-
var msgs = existing.messages.slice();
|
|
1170
|
-
var idx = -1;
|
|
1171
|
-
for (var i = msgs.length - 1; i >= 0; i--) {
|
|
1172
|
-
var m = msgs[i];
|
|
1173
|
-
if (m && m.isPending && m.role === "assistant" && !m.isBackgroundTask) {
|
|
1174
|
-
idx = i;
|
|
1175
|
-
break;
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
if (idx !== -1) {
|
|
1179
|
-
reply._serverItemId = msgs[idx]._serverItemId;
|
|
1180
|
-
msgs[idx] = reply;
|
|
1181
|
-
} else {
|
|
1182
|
-
msgs.push(reply);
|
|
1169
|
+
var msgs = existing.messages.slice();
|
|
1170
|
+
var idx = -1;
|
|
1171
|
+
for (var i = msgs.length - 1; i >= 0; i--) {
|
|
1172
|
+
var m = msgs[i];
|
|
1173
|
+
if (m && m.isPending && m.role === "assistant" && !m.isBackgroundTask) {
|
|
1174
|
+
idx = i;
|
|
1175
|
+
break;
|
|
1183
1176
|
}
|
|
1184
|
-
self.aiChatHistoryCache[params.key] = {
|
|
1185
|
-
messages: msgs,
|
|
1186
|
-
endOfList: existing.endOfList,
|
|
1187
|
-
startKeyHistory: existing.startKeyHistory
|
|
1188
|
-
};
|
|
1189
1177
|
}
|
|
1178
|
+
if (idx !== -1) {
|
|
1179
|
+
reply._serverItemId = msgs[idx]._serverItemId;
|
|
1180
|
+
msgs[idx] = reply;
|
|
1181
|
+
} else {
|
|
1182
|
+
msgs.push(reply);
|
|
1183
|
+
}
|
|
1184
|
+
self.aiChatHistoryCache[params.key] = {
|
|
1185
|
+
messages: msgs,
|
|
1186
|
+
endOfList: existing.endOfList,
|
|
1187
|
+
startKeyHistory: existing.startKeyHistory
|
|
1188
|
+
};
|
|
1190
1189
|
return result;
|
|
1191
1190
|
});
|
|
1192
1191
|
this.pendingAgentRequests[params.key] = run;
|
|
@@ -1329,7 +1328,9 @@ var ChatSession = class {
|
|
|
1329
1328
|
if (existing._serverItemId !== void 0) promoted._serverItemId = existing._serverItemId;
|
|
1330
1329
|
if (existing.isSendingToServer) promoted.isSendingToServer = true;
|
|
1331
1330
|
this.state.messages[nextIdx] = promoted;
|
|
1332
|
-
|
|
1331
|
+
var placeholder = { role: "assistant", content: "", isPending: true };
|
|
1332
|
+
if (existing._serverItemId !== void 0) placeholder._serverItemId = existing._serverItemId;
|
|
1333
|
+
this.state.messages.splice(nextIdx + 1, 0, placeholder);
|
|
1333
1334
|
this.host.notify();
|
|
1334
1335
|
}
|
|
1335
1336
|
resolveQueuedUserBubble(serverId) {
|
|
@@ -1539,61 +1540,118 @@ var ChatSession = class {
|
|
|
1539
1540
|
});
|
|
1540
1541
|
}
|
|
1541
1542
|
// --- typewriter -------------------------------------------------------
|
|
1543
|
+
// Reveal `fullText` into a message bubble at a constant wall-clock RATE
|
|
1544
|
+
// (chars/second) driven by requestAnimationFrame, rather than a fixed number
|
|
1545
|
+
// of characters per fixed-delay tick. This is what keeps typing smooth and
|
|
1546
|
+
// cheap on slow machines:
|
|
1547
|
+
//
|
|
1548
|
+
// * Each frame reveals `elapsed_ms * CHARS_PER_SEC` characters, so the
|
|
1549
|
+
// visual speed is the same regardless of how long a frame actually took.
|
|
1550
|
+
// * As the bubble's markdown grows, each re-render gets more expensive, so
|
|
1551
|
+
// frames get longer — which makes each frame reveal MORE characters and
|
|
1552
|
+
// therefore do FEWER, larger renders. That converts the old O(n^2)
|
|
1553
|
+
// "re-render the whole growing string once per 3 characters" (which got
|
|
1554
|
+
// slower and slower and pegged the CPU) into roughly O(n): the number of
|
|
1555
|
+
// renders self-throttles to what the machine can actually paint.
|
|
1556
|
+
// * rAF paces us to the browser's paint cycle and pauses in background
|
|
1557
|
+
// tabs, so we never queue work faster than it can be drawn.
|
|
1542
1558
|
typewriteIntoIndex(idx, fullText, localId) {
|
|
1543
1559
|
var self = this;
|
|
1544
1560
|
if (!fullText) return Promise.resolve();
|
|
1545
|
-
var
|
|
1546
|
-
var
|
|
1547
|
-
var
|
|
1561
|
+
var CHARS_PER_SEC = 300;
|
|
1562
|
+
var MIN_STEP = 1;
|
|
1563
|
+
var MAX_FRAME_MS = 1e3;
|
|
1564
|
+
var regions = [], m;
|
|
1548
1565
|
var fenceRegex = /```[\w.-]+\.[a-zA-Z0-9]+\n[\s\S]*?```/g;
|
|
1549
|
-
while ((m = fenceRegex.exec(fullText)) !== null)
|
|
1550
|
-
var linkRegions = [], lm;
|
|
1566
|
+
while ((m = fenceRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
|
|
1551
1567
|
var linkRegex = createInlineLinkRegex();
|
|
1552
|
-
while ((
|
|
1568
|
+
while ((m = linkRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
|
|
1569
|
+
regions.sort(function(a, b) {
|
|
1570
|
+
return a.start - b.start;
|
|
1571
|
+
});
|
|
1553
1572
|
this.state.typing = true;
|
|
1554
1573
|
this.state.typingAbort = false;
|
|
1555
1574
|
var i = 0;
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
var
|
|
1559
|
-
var
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1575
|
+
var last = nowMs();
|
|
1576
|
+
return new Promise(function(resolve) {
|
|
1577
|
+
var done = false;
|
|
1578
|
+
var doc = _g.document;
|
|
1579
|
+
function isHidden() {
|
|
1580
|
+
return !!(doc && doc.hidden);
|
|
1581
|
+
}
|
|
1582
|
+
function cleanup() {
|
|
1583
|
+
if (doc && doc.removeEventListener) doc.removeEventListener("visibilitychange", onVisibility);
|
|
1584
|
+
}
|
|
1585
|
+
function finish() {
|
|
1586
|
+
if (done) return;
|
|
1587
|
+
done = true;
|
|
1588
|
+
cleanup();
|
|
1589
|
+
if (!self.state.typingAbort) {
|
|
1590
|
+
var fi = localId ? self.state.messages.findIndex(function(mm) {
|
|
1591
|
+
return mm._localId === localId;
|
|
1592
|
+
}) : idx;
|
|
1593
|
+
if (fi !== -1) {
|
|
1594
|
+
var t = self.state.messages[fi];
|
|
1595
|
+
if (t) {
|
|
1596
|
+
t.content = fullText;
|
|
1597
|
+
self.host.refreshMessageBubble(fi);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
self.state.typing = false;
|
|
1602
|
+
resolve();
|
|
1603
|
+
}
|
|
1604
|
+
function onVisibility() {
|
|
1605
|
+
if (isHidden()) finish();
|
|
1572
1606
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
var
|
|
1607
|
+
if (doc && doc.addEventListener) doc.addEventListener("visibilitychange", onVisibility);
|
|
1608
|
+
function frame(t) {
|
|
1609
|
+
if (done) return;
|
|
1610
|
+
if (self.state.typingAbort || i >= fullText.length || isHidden()) {
|
|
1611
|
+
finish();
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
var dt = t - last;
|
|
1615
|
+
last = t;
|
|
1616
|
+
if (!(dt > 0)) dt = 16;
|
|
1617
|
+
if (dt > MAX_FRAME_MS) dt = MAX_FRAME_MS;
|
|
1618
|
+
var step = Math.round(dt * CHARS_PER_SEC / 1e3);
|
|
1619
|
+
if (step < MIN_STEP) step = MIN_STEP;
|
|
1620
|
+
var next = Math.min(fullText.length, i + step);
|
|
1621
|
+
for (var changed = true; changed; ) {
|
|
1622
|
+
changed = false;
|
|
1623
|
+
for (var k = 0; k < regions.length; k++) {
|
|
1624
|
+
var r = regions[k];
|
|
1625
|
+
if (next > r.start && i < r.end && r.end > next) {
|
|
1626
|
+
next = r.end;
|
|
1627
|
+
changed = true;
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
if (next > fullText.length) next = fullText.length;
|
|
1632
|
+
i = next;
|
|
1633
|
+
var currentIdx = localId ? self.state.messages.findIndex(function(mm) {
|
|
1588
1634
|
return mm._localId === localId;
|
|
1589
1635
|
}) : idx;
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
self.host.refreshMessageBubble(fi !== -1 ? fi : idx);
|
|
1636
|
+
if (currentIdx === -1) {
|
|
1637
|
+
finish();
|
|
1638
|
+
return;
|
|
1594
1639
|
}
|
|
1640
|
+
var target = self.state.messages[currentIdx];
|
|
1641
|
+
if (!target) {
|
|
1642
|
+
finish();
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
target.content = fullText.slice(0, i);
|
|
1646
|
+
self.host.refreshMessageBubble(currentIdx);
|
|
1647
|
+
self.host.scrollToBottomIfSticky();
|
|
1648
|
+
nextFrame(frame);
|
|
1649
|
+
}
|
|
1650
|
+
if (isHidden()) {
|
|
1651
|
+
finish();
|
|
1652
|
+
return;
|
|
1595
1653
|
}
|
|
1596
|
-
|
|
1654
|
+
nextFrame(frame);
|
|
1597
1655
|
});
|
|
1598
1656
|
}
|
|
1599
1657
|
enqueueTypewrite(idx, fullText, localId) {
|
|
@@ -1907,7 +1965,7 @@ var ChatSession = class {
|
|
|
1907
1965
|
if (item.status !== "running" && item.status !== "pending") return;
|
|
1908
1966
|
if (!item.poll || !item.id) return;
|
|
1909
1967
|
if (self.historyItemPolls.has(item.id)) return;
|
|
1910
|
-
if (
|
|
1968
|
+
if (self.pendingAgentRequests[self.getHistoryCacheKey()] && !item._isBgTask && !item._isOnBgQueue) return;
|
|
1911
1969
|
self.historyItemPolls.set(item.id, true);
|
|
1912
1970
|
var capturedId = item.id;
|
|
1913
1971
|
var pp = item.poll({
|