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/bunnyquery.js
CHANGED
|
@@ -1036,10 +1036,18 @@ ${options.inlineContentPlaceholder}
|
|
|
1036
1036
|
}
|
|
1037
1037
|
|
|
1038
1038
|
// src/engine/session.ts
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1039
|
+
var _g = typeof globalThis !== "undefined" ? globalThis : {};
|
|
1040
|
+
function nowMs() {
|
|
1041
|
+
return _g.performance && typeof _g.performance.now === "function" ? _g.performance.now() : Date.now();
|
|
1042
|
+
}
|
|
1043
|
+
function nextFrame(cb) {
|
|
1044
|
+
if (typeof _g.requestAnimationFrame === "function") {
|
|
1045
|
+
_g.requestAnimationFrame(cb);
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
setTimeout(function() {
|
|
1049
|
+
cb(nowMs());
|
|
1050
|
+
}, 16);
|
|
1043
1051
|
}
|
|
1044
1052
|
var ChatSession = class {
|
|
1045
1053
|
constructor(host) {
|
|
@@ -1126,35 +1134,26 @@ ${options.inlineContentPlaceholder}
|
|
|
1126
1134
|
if (dispatchItemId) self.historyItemPolls.delete(dispatchItemId);
|
|
1127
1135
|
var existing = self.aiChatHistoryCache[params.key] || { messages: [], endOfList: false, startKeyHistory: [] };
|
|
1128
1136
|
var reply = { role: "assistant", content: result.content, isError: result.isError };
|
|
1129
|
-
var
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
} else {
|
|
1137
|
-
var msgs = existing.messages.slice();
|
|
1138
|
-
var idx = -1;
|
|
1139
|
-
for (var i = msgs.length - 1; i >= 0; i--) {
|
|
1140
|
-
var m = msgs[i];
|
|
1141
|
-
if (m && m.isPending && m.role === "assistant" && !m.isBackgroundTask) {
|
|
1142
|
-
idx = i;
|
|
1143
|
-
break;
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
if (idx !== -1) {
|
|
1147
|
-
reply._serverItemId = msgs[idx]._serverItemId;
|
|
1148
|
-
msgs[idx] = reply;
|
|
1149
|
-
} else {
|
|
1150
|
-
msgs.push(reply);
|
|
1137
|
+
var msgs = existing.messages.slice();
|
|
1138
|
+
var idx = -1;
|
|
1139
|
+
for (var i = msgs.length - 1; i >= 0; i--) {
|
|
1140
|
+
var m = msgs[i];
|
|
1141
|
+
if (m && m.isPending && m.role === "assistant" && !m.isBackgroundTask) {
|
|
1142
|
+
idx = i;
|
|
1143
|
+
break;
|
|
1151
1144
|
}
|
|
1152
|
-
self.aiChatHistoryCache[params.key] = {
|
|
1153
|
-
messages: msgs,
|
|
1154
|
-
endOfList: existing.endOfList,
|
|
1155
|
-
startKeyHistory: existing.startKeyHistory
|
|
1156
|
-
};
|
|
1157
1145
|
}
|
|
1146
|
+
if (idx !== -1) {
|
|
1147
|
+
reply._serverItemId = msgs[idx]._serverItemId;
|
|
1148
|
+
msgs[idx] = reply;
|
|
1149
|
+
} else {
|
|
1150
|
+
msgs.push(reply);
|
|
1151
|
+
}
|
|
1152
|
+
self.aiChatHistoryCache[params.key] = {
|
|
1153
|
+
messages: msgs,
|
|
1154
|
+
endOfList: existing.endOfList,
|
|
1155
|
+
startKeyHistory: existing.startKeyHistory
|
|
1156
|
+
};
|
|
1158
1157
|
return result;
|
|
1159
1158
|
});
|
|
1160
1159
|
this.pendingAgentRequests[params.key] = run;
|
|
@@ -1297,7 +1296,9 @@ ${options.inlineContentPlaceholder}
|
|
|
1297
1296
|
if (existing._serverItemId !== void 0) promoted._serverItemId = existing._serverItemId;
|
|
1298
1297
|
if (existing.isSendingToServer) promoted.isSendingToServer = true;
|
|
1299
1298
|
this.state.messages[nextIdx] = promoted;
|
|
1300
|
-
|
|
1299
|
+
var placeholder = { role: "assistant", content: "", isPending: true };
|
|
1300
|
+
if (existing._serverItemId !== void 0) placeholder._serverItemId = existing._serverItemId;
|
|
1301
|
+
this.state.messages.splice(nextIdx + 1, 0, placeholder);
|
|
1301
1302
|
this.host.notify();
|
|
1302
1303
|
}
|
|
1303
1304
|
resolveQueuedUserBubble(serverId) {
|
|
@@ -1507,61 +1508,118 @@ ${options.inlineContentPlaceholder}
|
|
|
1507
1508
|
});
|
|
1508
1509
|
}
|
|
1509
1510
|
// --- typewriter -------------------------------------------------------
|
|
1511
|
+
// Reveal `fullText` into a message bubble at a constant wall-clock RATE
|
|
1512
|
+
// (chars/second) driven by requestAnimationFrame, rather than a fixed number
|
|
1513
|
+
// of characters per fixed-delay tick. This is what keeps typing smooth and
|
|
1514
|
+
// cheap on slow machines:
|
|
1515
|
+
//
|
|
1516
|
+
// * Each frame reveals `elapsed_ms * CHARS_PER_SEC` characters, so the
|
|
1517
|
+
// visual speed is the same regardless of how long a frame actually took.
|
|
1518
|
+
// * As the bubble's markdown grows, each re-render gets more expensive, so
|
|
1519
|
+
// frames get longer — which makes each frame reveal MORE characters and
|
|
1520
|
+
// therefore do FEWER, larger renders. That converts the old O(n^2)
|
|
1521
|
+
// "re-render the whole growing string once per 3 characters" (which got
|
|
1522
|
+
// slower and slower and pegged the CPU) into roughly O(n): the number of
|
|
1523
|
+
// renders self-throttles to what the machine can actually paint.
|
|
1524
|
+
// * rAF paces us to the browser's paint cycle and pauses in background
|
|
1525
|
+
// tabs, so we never queue work faster than it can be drawn.
|
|
1510
1526
|
typewriteIntoIndex(idx, fullText, localId) {
|
|
1511
1527
|
var self = this;
|
|
1512
1528
|
if (!fullText) return Promise.resolve();
|
|
1513
|
-
var
|
|
1514
|
-
var
|
|
1515
|
-
var
|
|
1529
|
+
var CHARS_PER_SEC = 300;
|
|
1530
|
+
var MIN_STEP = 1;
|
|
1531
|
+
var MAX_FRAME_MS = 1e3;
|
|
1532
|
+
var regions = [], m;
|
|
1516
1533
|
var fenceRegex = /```[\w.-]+\.[a-zA-Z0-9]+\n[\s\S]*?```/g;
|
|
1517
|
-
while ((m = fenceRegex.exec(fullText)) !== null)
|
|
1518
|
-
var linkRegions = [], lm;
|
|
1534
|
+
while ((m = fenceRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
|
|
1519
1535
|
var linkRegex = createInlineLinkRegex();
|
|
1520
|
-
while ((
|
|
1536
|
+
while ((m = linkRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
|
|
1537
|
+
regions.sort(function(a, b) {
|
|
1538
|
+
return a.start - b.start;
|
|
1539
|
+
});
|
|
1521
1540
|
this.state.typing = true;
|
|
1522
1541
|
this.state.typingAbort = false;
|
|
1523
1542
|
var i = 0;
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
var
|
|
1527
|
-
var
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
if (region) step = Math.max(charsPerTick, Math.ceil((region.end - i) / fenceTicks));
|
|
1534
|
-
else if (linkRegion) step = Math.max(charsPerTick, linkRegion.end - i);
|
|
1535
|
-
else {
|
|
1536
|
-
var nextLink = linkRegions.find(function(r) {
|
|
1537
|
-
return i < r.start && i + step > r.start;
|
|
1538
|
-
});
|
|
1539
|
-
if (nextLink) step = nextLink.end - i;
|
|
1543
|
+
var last = nowMs();
|
|
1544
|
+
return new Promise(function(resolve) {
|
|
1545
|
+
var done = false;
|
|
1546
|
+
var doc = _g.document;
|
|
1547
|
+
function isHidden() {
|
|
1548
|
+
return !!(doc && doc.hidden);
|
|
1549
|
+
}
|
|
1550
|
+
function cleanup() {
|
|
1551
|
+
if (doc && doc.removeEventListener) doc.removeEventListener("visibilitychange", onVisibility);
|
|
1540
1552
|
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1553
|
+
function finish() {
|
|
1554
|
+
if (done) return;
|
|
1555
|
+
done = true;
|
|
1556
|
+
cleanup();
|
|
1557
|
+
if (!self.state.typingAbort) {
|
|
1558
|
+
var fi = localId ? self.state.messages.findIndex(function(mm) {
|
|
1559
|
+
return mm._localId === localId;
|
|
1560
|
+
}) : idx;
|
|
1561
|
+
if (fi !== -1) {
|
|
1562
|
+
var t = self.state.messages[fi];
|
|
1563
|
+
if (t) {
|
|
1564
|
+
t.content = fullText;
|
|
1565
|
+
self.host.refreshMessageBubble(fi);
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
self.state.typing = false;
|
|
1570
|
+
resolve();
|
|
1571
|
+
}
|
|
1572
|
+
function onVisibility() {
|
|
1573
|
+
if (isHidden()) finish();
|
|
1574
|
+
}
|
|
1575
|
+
if (doc && doc.addEventListener) doc.addEventListener("visibilitychange", onVisibility);
|
|
1576
|
+
function frame(t) {
|
|
1577
|
+
if (done) return;
|
|
1578
|
+
if (self.state.typingAbort || i >= fullText.length || isHidden()) {
|
|
1579
|
+
finish();
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
var dt = t - last;
|
|
1583
|
+
last = t;
|
|
1584
|
+
if (!(dt > 0)) dt = 16;
|
|
1585
|
+
if (dt > MAX_FRAME_MS) dt = MAX_FRAME_MS;
|
|
1586
|
+
var step = Math.round(dt * CHARS_PER_SEC / 1e3);
|
|
1587
|
+
if (step < MIN_STEP) step = MIN_STEP;
|
|
1588
|
+
var next = Math.min(fullText.length, i + step);
|
|
1589
|
+
for (var changed = true; changed; ) {
|
|
1590
|
+
changed = false;
|
|
1591
|
+
for (var k = 0; k < regions.length; k++) {
|
|
1592
|
+
var r = regions[k];
|
|
1593
|
+
if (next > r.start && i < r.end && r.end > next) {
|
|
1594
|
+
next = r.end;
|
|
1595
|
+
changed = true;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
if (next > fullText.length) next = fullText.length;
|
|
1600
|
+
i = next;
|
|
1601
|
+
var currentIdx = localId ? self.state.messages.findIndex(function(mm) {
|
|
1556
1602
|
return mm._localId === localId;
|
|
1557
1603
|
}) : idx;
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
self.host.refreshMessageBubble(fi !== -1 ? fi : idx);
|
|
1604
|
+
if (currentIdx === -1) {
|
|
1605
|
+
finish();
|
|
1606
|
+
return;
|
|
1562
1607
|
}
|
|
1608
|
+
var target = self.state.messages[currentIdx];
|
|
1609
|
+
if (!target) {
|
|
1610
|
+
finish();
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
target.content = fullText.slice(0, i);
|
|
1614
|
+
self.host.refreshMessageBubble(currentIdx);
|
|
1615
|
+
self.host.scrollToBottomIfSticky();
|
|
1616
|
+
nextFrame(frame);
|
|
1617
|
+
}
|
|
1618
|
+
if (isHidden()) {
|
|
1619
|
+
finish();
|
|
1620
|
+
return;
|
|
1563
1621
|
}
|
|
1564
|
-
|
|
1622
|
+
nextFrame(frame);
|
|
1565
1623
|
});
|
|
1566
1624
|
}
|
|
1567
1625
|
enqueueTypewrite(idx, fullText, localId) {
|
|
@@ -1875,7 +1933,7 @@ ${options.inlineContentPlaceholder}
|
|
|
1875
1933
|
if (item.status !== "running" && item.status !== "pending") return;
|
|
1876
1934
|
if (!item.poll || !item.id) return;
|
|
1877
1935
|
if (self.historyItemPolls.has(item.id)) return;
|
|
1878
|
-
if (
|
|
1936
|
+
if (self.pendingAgentRequests[self.getHistoryCacheKey()] && !item._isBgTask && !item._isOnBgQueue) return;
|
|
1879
1937
|
self.historyItemPolls.set(item.id, true);
|
|
1880
1938
|
var capturedId = item.id;
|
|
1881
1939
|
var pp = item.poll({
|
|
@@ -2118,7 +2176,7 @@ ${options.inlineContentPlaceholder}
|
|
|
2118
2176
|
(function() {
|
|
2119
2177
|
var MCP_PROD = "https://mcp.broadwayinc.computer";
|
|
2120
2178
|
var MCP_DEV = "https://mcp-dev.broadwayinc.computer";
|
|
2121
|
-
var BQ_VERSION = "1.4.
|
|
2179
|
+
var BQ_VERSION = "1.4.6" ;
|
|
2122
2180
|
var ATTACHMENT_URL_EXPIRES_SECONDS = 600;
|
|
2123
2181
|
var GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
2124
2182
|
var GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
@@ -4851,7 +4909,6 @@ ${options.inlineContentPlaceholder}
|
|
|
4851
4909
|
CS.settingsBtnEl = null;
|
|
4852
4910
|
CS.composerEl = null;
|
|
4853
4911
|
CS.gateRefreshToken += 1;
|
|
4854
|
-
historyItemPolls.clear();
|
|
4855
4912
|
if (CS.pollTimer) {
|
|
4856
4913
|
clearInterval(CS.pollTimer);
|
|
4857
4914
|
CS.pollTimer = null;
|
package/dist/engine.cjs
CHANGED
|
@@ -1070,10 +1070,18 @@ function mapHistoryListToMessages(list, platform, opts) {
|
|
|
1070
1070
|
}
|
|
1071
1071
|
|
|
1072
1072
|
// src/engine/session.ts
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1073
|
+
var _g = typeof globalThis !== "undefined" ? globalThis : {};
|
|
1074
|
+
function nowMs() {
|
|
1075
|
+
return _g.performance && typeof _g.performance.now === "function" ? _g.performance.now() : Date.now();
|
|
1076
|
+
}
|
|
1077
|
+
function nextFrame(cb) {
|
|
1078
|
+
if (typeof _g.requestAnimationFrame === "function") {
|
|
1079
|
+
_g.requestAnimationFrame(cb);
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
setTimeout(function() {
|
|
1083
|
+
cb(nowMs());
|
|
1084
|
+
}, 16);
|
|
1077
1085
|
}
|
|
1078
1086
|
var ChatSession = class {
|
|
1079
1087
|
constructor(host) {
|
|
@@ -1160,35 +1168,26 @@ var ChatSession = class {
|
|
|
1160
1168
|
if (dispatchItemId) self.historyItemPolls.delete(dispatchItemId);
|
|
1161
1169
|
var existing = self.aiChatHistoryCache[params.key] || { messages: [], endOfList: false, startKeyHistory: [] };
|
|
1162
1170
|
var reply = { role: "assistant", content: result.content, isError: result.isError };
|
|
1163
|
-
var
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
} else {
|
|
1171
|
-
var msgs = existing.messages.slice();
|
|
1172
|
-
var idx = -1;
|
|
1173
|
-
for (var i = msgs.length - 1; i >= 0; i--) {
|
|
1174
|
-
var m = msgs[i];
|
|
1175
|
-
if (m && m.isPending && m.role === "assistant" && !m.isBackgroundTask) {
|
|
1176
|
-
idx = i;
|
|
1177
|
-
break;
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
if (idx !== -1) {
|
|
1181
|
-
reply._serverItemId = msgs[idx]._serverItemId;
|
|
1182
|
-
msgs[idx] = reply;
|
|
1183
|
-
} else {
|
|
1184
|
-
msgs.push(reply);
|
|
1171
|
+
var msgs = existing.messages.slice();
|
|
1172
|
+
var idx = -1;
|
|
1173
|
+
for (var i = msgs.length - 1; i >= 0; i--) {
|
|
1174
|
+
var m = msgs[i];
|
|
1175
|
+
if (m && m.isPending && m.role === "assistant" && !m.isBackgroundTask) {
|
|
1176
|
+
idx = i;
|
|
1177
|
+
break;
|
|
1185
1178
|
}
|
|
1186
|
-
self.aiChatHistoryCache[params.key] = {
|
|
1187
|
-
messages: msgs,
|
|
1188
|
-
endOfList: existing.endOfList,
|
|
1189
|
-
startKeyHistory: existing.startKeyHistory
|
|
1190
|
-
};
|
|
1191
1179
|
}
|
|
1180
|
+
if (idx !== -1) {
|
|
1181
|
+
reply._serverItemId = msgs[idx]._serverItemId;
|
|
1182
|
+
msgs[idx] = reply;
|
|
1183
|
+
} else {
|
|
1184
|
+
msgs.push(reply);
|
|
1185
|
+
}
|
|
1186
|
+
self.aiChatHistoryCache[params.key] = {
|
|
1187
|
+
messages: msgs,
|
|
1188
|
+
endOfList: existing.endOfList,
|
|
1189
|
+
startKeyHistory: existing.startKeyHistory
|
|
1190
|
+
};
|
|
1192
1191
|
return result;
|
|
1193
1192
|
});
|
|
1194
1193
|
this.pendingAgentRequests[params.key] = run;
|
|
@@ -1331,7 +1330,9 @@ var ChatSession = class {
|
|
|
1331
1330
|
if (existing._serverItemId !== void 0) promoted._serverItemId = existing._serverItemId;
|
|
1332
1331
|
if (existing.isSendingToServer) promoted.isSendingToServer = true;
|
|
1333
1332
|
this.state.messages[nextIdx] = promoted;
|
|
1334
|
-
|
|
1333
|
+
var placeholder = { role: "assistant", content: "", isPending: true };
|
|
1334
|
+
if (existing._serverItemId !== void 0) placeholder._serverItemId = existing._serverItemId;
|
|
1335
|
+
this.state.messages.splice(nextIdx + 1, 0, placeholder);
|
|
1335
1336
|
this.host.notify();
|
|
1336
1337
|
}
|
|
1337
1338
|
resolveQueuedUserBubble(serverId) {
|
|
@@ -1541,61 +1542,118 @@ var ChatSession = class {
|
|
|
1541
1542
|
});
|
|
1542
1543
|
}
|
|
1543
1544
|
// --- typewriter -------------------------------------------------------
|
|
1545
|
+
// Reveal `fullText` into a message bubble at a constant wall-clock RATE
|
|
1546
|
+
// (chars/second) driven by requestAnimationFrame, rather than a fixed number
|
|
1547
|
+
// of characters per fixed-delay tick. This is what keeps typing smooth and
|
|
1548
|
+
// cheap on slow machines:
|
|
1549
|
+
//
|
|
1550
|
+
// * Each frame reveals `elapsed_ms * CHARS_PER_SEC` characters, so the
|
|
1551
|
+
// visual speed is the same regardless of how long a frame actually took.
|
|
1552
|
+
// * As the bubble's markdown grows, each re-render gets more expensive, so
|
|
1553
|
+
// frames get longer — which makes each frame reveal MORE characters and
|
|
1554
|
+
// therefore do FEWER, larger renders. That converts the old O(n^2)
|
|
1555
|
+
// "re-render the whole growing string once per 3 characters" (which got
|
|
1556
|
+
// slower and slower and pegged the CPU) into roughly O(n): the number of
|
|
1557
|
+
// renders self-throttles to what the machine can actually paint.
|
|
1558
|
+
// * rAF paces us to the browser's paint cycle and pauses in background
|
|
1559
|
+
// tabs, so we never queue work faster than it can be drawn.
|
|
1544
1560
|
typewriteIntoIndex(idx, fullText, localId) {
|
|
1545
1561
|
var self = this;
|
|
1546
1562
|
if (!fullText) return Promise.resolve();
|
|
1547
|
-
var
|
|
1548
|
-
var
|
|
1549
|
-
var
|
|
1563
|
+
var CHARS_PER_SEC = 300;
|
|
1564
|
+
var MIN_STEP = 1;
|
|
1565
|
+
var MAX_FRAME_MS = 1e3;
|
|
1566
|
+
var regions = [], m;
|
|
1550
1567
|
var fenceRegex = /```[\w.-]+\.[a-zA-Z0-9]+\n[\s\S]*?```/g;
|
|
1551
|
-
while ((m = fenceRegex.exec(fullText)) !== null)
|
|
1552
|
-
var linkRegions = [], lm;
|
|
1568
|
+
while ((m = fenceRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
|
|
1553
1569
|
var linkRegex = createInlineLinkRegex();
|
|
1554
|
-
while ((
|
|
1570
|
+
while ((m = linkRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
|
|
1571
|
+
regions.sort(function(a, b) {
|
|
1572
|
+
return a.start - b.start;
|
|
1573
|
+
});
|
|
1555
1574
|
this.state.typing = true;
|
|
1556
1575
|
this.state.typingAbort = false;
|
|
1557
1576
|
var i = 0;
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
var
|
|
1561
|
-
var
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1577
|
+
var last = nowMs();
|
|
1578
|
+
return new Promise(function(resolve) {
|
|
1579
|
+
var done = false;
|
|
1580
|
+
var doc = _g.document;
|
|
1581
|
+
function isHidden() {
|
|
1582
|
+
return !!(doc && doc.hidden);
|
|
1583
|
+
}
|
|
1584
|
+
function cleanup() {
|
|
1585
|
+
if (doc && doc.removeEventListener) doc.removeEventListener("visibilitychange", onVisibility);
|
|
1586
|
+
}
|
|
1587
|
+
function finish() {
|
|
1588
|
+
if (done) return;
|
|
1589
|
+
done = true;
|
|
1590
|
+
cleanup();
|
|
1591
|
+
if (!self.state.typingAbort) {
|
|
1592
|
+
var fi = localId ? self.state.messages.findIndex(function(mm) {
|
|
1593
|
+
return mm._localId === localId;
|
|
1594
|
+
}) : idx;
|
|
1595
|
+
if (fi !== -1) {
|
|
1596
|
+
var t = self.state.messages[fi];
|
|
1597
|
+
if (t) {
|
|
1598
|
+
t.content = fullText;
|
|
1599
|
+
self.host.refreshMessageBubble(fi);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
self.state.typing = false;
|
|
1604
|
+
resolve();
|
|
1605
|
+
}
|
|
1606
|
+
function onVisibility() {
|
|
1607
|
+
if (isHidden()) finish();
|
|
1574
1608
|
}
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
var
|
|
1609
|
+
if (doc && doc.addEventListener) doc.addEventListener("visibilitychange", onVisibility);
|
|
1610
|
+
function frame(t) {
|
|
1611
|
+
if (done) return;
|
|
1612
|
+
if (self.state.typingAbort || i >= fullText.length || isHidden()) {
|
|
1613
|
+
finish();
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
var dt = t - last;
|
|
1617
|
+
last = t;
|
|
1618
|
+
if (!(dt > 0)) dt = 16;
|
|
1619
|
+
if (dt > MAX_FRAME_MS) dt = MAX_FRAME_MS;
|
|
1620
|
+
var step = Math.round(dt * CHARS_PER_SEC / 1e3);
|
|
1621
|
+
if (step < MIN_STEP) step = MIN_STEP;
|
|
1622
|
+
var next = Math.min(fullText.length, i + step);
|
|
1623
|
+
for (var changed = true; changed; ) {
|
|
1624
|
+
changed = false;
|
|
1625
|
+
for (var k = 0; k < regions.length; k++) {
|
|
1626
|
+
var r = regions[k];
|
|
1627
|
+
if (next > r.start && i < r.end && r.end > next) {
|
|
1628
|
+
next = r.end;
|
|
1629
|
+
changed = true;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
if (next > fullText.length) next = fullText.length;
|
|
1634
|
+
i = next;
|
|
1635
|
+
var currentIdx = localId ? self.state.messages.findIndex(function(mm) {
|
|
1590
1636
|
return mm._localId === localId;
|
|
1591
1637
|
}) : idx;
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
self.host.refreshMessageBubble(fi !== -1 ? fi : idx);
|
|
1638
|
+
if (currentIdx === -1) {
|
|
1639
|
+
finish();
|
|
1640
|
+
return;
|
|
1596
1641
|
}
|
|
1642
|
+
var target = self.state.messages[currentIdx];
|
|
1643
|
+
if (!target) {
|
|
1644
|
+
finish();
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
target.content = fullText.slice(0, i);
|
|
1648
|
+
self.host.refreshMessageBubble(currentIdx);
|
|
1649
|
+
self.host.scrollToBottomIfSticky();
|
|
1650
|
+
nextFrame(frame);
|
|
1651
|
+
}
|
|
1652
|
+
if (isHidden()) {
|
|
1653
|
+
finish();
|
|
1654
|
+
return;
|
|
1597
1655
|
}
|
|
1598
|
-
|
|
1656
|
+
nextFrame(frame);
|
|
1599
1657
|
});
|
|
1600
1658
|
}
|
|
1601
1659
|
enqueueTypewrite(idx, fullText, localId) {
|
|
@@ -1909,7 +1967,7 @@ var ChatSession = class {
|
|
|
1909
1967
|
if (item.status !== "running" && item.status !== "pending") return;
|
|
1910
1968
|
if (!item.poll || !item.id) return;
|
|
1911
1969
|
if (self.historyItemPolls.has(item.id)) return;
|
|
1912
|
-
if (
|
|
1970
|
+
if (self.pendingAgentRequests[self.getHistoryCacheKey()] && !item._isBgTask && !item._isOnBgQueue) return;
|
|
1913
1971
|
self.historyItemPolls.set(item.id, true);
|
|
1914
1972
|
var capturedId = item.id;
|
|
1915
1973
|
var pp = item.poll({
|