bunnyquery 1.9.4 → 1.9.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 +37 -12
- package/dist/engine.cjs +38 -11
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.mts +52 -1
- package/dist/engine.d.ts +52 -1
- package/dist/engine.mjs +37 -12
- package/dist/engine.mjs.map +1 -1
- package/package.json +1 -1
- package/src/engine/history.ts +111 -5
- package/src/engine/index.ts +5 -0
- package/src/engine/session.ts +24 -9
package/bunnyquery.js
CHANGED
|
@@ -2204,6 +2204,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
2204
2204
|
const fetch2 = getChatHistory;
|
|
2205
2205
|
const bgQueue = bgIndexingQueueName(params.userId, params.service);
|
|
2206
2206
|
const base = { service: params.service, owner: params.owner, platform: params.platform };
|
|
2207
|
+
const surfaceScope = params.scopeSurfaceToQueue && params.userId ? { queue: params.userId, queue_exact: true } : { queue_exclude: bgQueue };
|
|
2207
2208
|
const fetchMore = !!(fetchOptions && fetchOptions.fetchMore);
|
|
2208
2209
|
const limit = fetchOptions && fetchOptions.limit;
|
|
2209
2210
|
const firstLoad = !splitHistoryStates[key];
|
|
@@ -2231,13 +2232,13 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
2231
2232
|
} else {
|
|
2232
2233
|
const sOpts = { fetchMore };
|
|
2233
2234
|
if (limit) sOpts.limit = limit;
|
|
2234
|
-
let s = await fetch2({ ...base,
|
|
2235
|
+
let s = await fetch2({ ...base, ...surfaceScope }, sOpts);
|
|
2235
2236
|
let hops = 0;
|
|
2236
2237
|
while (s && !s.endOfList && !(s.list || []).length && hops < SURFACE_EMPTY_MAX_PAGES) {
|
|
2237
2238
|
hops++;
|
|
2238
2239
|
const nOpts = { fetchMore: true };
|
|
2239
2240
|
if (limit) nOpts.limit = limit;
|
|
2240
|
-
s = await fetch2({ ...base,
|
|
2241
|
+
s = await fetch2({ ...base, ...surfaceScope }, nOpts);
|
|
2241
2242
|
}
|
|
2242
2243
|
state.pendingSurface = {
|
|
2243
2244
|
list: s && Array.isArray(s.list) ? s.list : [],
|
|
@@ -2370,6 +2371,14 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
2370
2371
|
firstLoad
|
|
2371
2372
|
};
|
|
2372
2373
|
}
|
|
2374
|
+
function chatCacheKey(projectId, platform, userId) {
|
|
2375
|
+
if (!projectId || platform === "none") return "";
|
|
2376
|
+
return projectId + "#" + platform + "#" + (userId || "");
|
|
2377
|
+
}
|
|
2378
|
+
function indexScopeKey(projectId, platform) {
|
|
2379
|
+
if (!projectId || platform === "none") return "";
|
|
2380
|
+
return projectId + "#" + platform;
|
|
2381
|
+
}
|
|
2373
2382
|
function mapHistoryListToMessages(list, platform, opts) {
|
|
2374
2383
|
var mapped = [], runningItemIds = [];
|
|
2375
2384
|
var extractAssistantText = platform === "openai" ? extractOpenAIText : extractClaudeText;
|
|
@@ -2456,7 +2465,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
2456
2465
|
}
|
|
2457
2466
|
});
|
|
2458
2467
|
if (opts.projectId) {
|
|
2459
|
-
var ownerKey = opts.projectId
|
|
2468
|
+
var ownerKey = chatCacheKey(opts.projectId, platform, opts.userId);
|
|
2460
2469
|
for (var oi = 0; oi < mapped.length; oi++) mapped[oi]._ownerKey = ownerKey;
|
|
2461
2470
|
}
|
|
2462
2471
|
return { messages: mapped, runningItemIds };
|
|
@@ -2983,7 +2992,8 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
2983
2992
|
/** Storage paths are project-relative, and one ChatSession serves every
|
|
2984
2993
|
* project, so a claim has to be scoped the way a stop is (_indexKeyOf). */
|
|
2985
2994
|
_indexClaimKey(storagePath) {
|
|
2986
|
-
|
|
2995
|
+
var id = this.host.getIdentity();
|
|
2996
|
+
return indexScopeKey(id.projectId, id.platform) + "|" + storagePath;
|
|
2987
2997
|
}
|
|
2988
2998
|
/**
|
|
2989
2999
|
* Take this file's indexing slot, or report that someone already has it.
|
|
@@ -3425,8 +3435,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
3425
3435
|
*/
|
|
3426
3436
|
getHistoryCacheKey() {
|
|
3427
3437
|
var id = this.host.getIdentity();
|
|
3428
|
-
|
|
3429
|
-
return id.projectId + "#" + id.platform + "#" + (id.userId || "");
|
|
3438
|
+
return chatCacheKey(id.projectId, id.platform, id.userId);
|
|
3430
3439
|
}
|
|
3431
3440
|
/** Re-apply memoized hydrated texts onto freshly-mapped messages. Both
|
|
3432
3441
|
* clients call this right after their mapper runs (loadHistory does it
|
|
@@ -3976,7 +3985,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
3976
3985
|
}
|
|
3977
3986
|
if (stageId) delete this._liveStages[stageId];
|
|
3978
3987
|
var llmComposed = composedForLlm || composed;
|
|
3979
|
-
var key =
|
|
3988
|
+
var key = chatCacheKey(id.projectId, id.platform, id.userId);
|
|
3980
3989
|
var offChat = !!key && key !== this.getHistoryCacheKey();
|
|
3981
3990
|
var isQueuedSend = !offChat && (useBgQueue || this.state.sending || this.state.messages.some(function(m) {
|
|
3982
3991
|
return (m.isPending || m.isPendingQueued) && !m.isBackgroundTask && !m._useBgQueue;
|
|
@@ -4542,7 +4551,8 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
4542
4551
|
cancelIndexingGroup(group) {
|
|
4543
4552
|
var self = this;
|
|
4544
4553
|
if (!group || !group.key) return;
|
|
4545
|
-
var
|
|
4554
|
+
var idn = this.host.getIdentity();
|
|
4555
|
+
var scoped = indexScopeKey(idn.projectId, idn.platform) + "|" + group.key;
|
|
4546
4556
|
this.cancelledIndexKeys.add(scoped);
|
|
4547
4557
|
if (!group.finished) {
|
|
4548
4558
|
var stoppedIds = {};
|
|
@@ -5010,7 +5020,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
5010
5020
|
if (!entry) return "";
|
|
5011
5021
|
var file = entry.storagePath || entry.filename;
|
|
5012
5022
|
if (!file) return "";
|
|
5013
|
-
return entry.projectId
|
|
5023
|
+
return indexScopeKey(entry.projectId, entry.platform) + "|" + file;
|
|
5014
5024
|
}
|
|
5015
5025
|
/**
|
|
5016
5026
|
* Reconcile the bg queue with the files the user has stopped.
|
|
@@ -5537,7 +5547,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
5537
5547
|
loadHistory(fetchMore, token) {
|
|
5538
5548
|
var self = this;
|
|
5539
5549
|
var id = this.host.getIdentity();
|
|
5540
|
-
var loadKey =
|
|
5550
|
+
var loadKey = chatCacheKey(id.projectId, id.platform, id.userId);
|
|
5541
5551
|
if (token === void 0) token = this.state.gateRefreshToken;
|
|
5542
5552
|
if (this.state.loadingHistory && this.state.historyRequestToken === token || id.platform === "none" || !id.projectId) {
|
|
5543
5553
|
return Promise.resolve();
|
|
@@ -5556,7 +5566,17 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
5556
5566
|
if (fetchMore && this.state.historyStartKeyHistory.length) options.startKeyHistory = this.state.historyStartKeyHistory.slice();
|
|
5557
5567
|
if (!fetchMore) options.deferBg = true;
|
|
5558
5568
|
var fetchHistory = function() {
|
|
5559
|
-
return getSplitChatHistory({
|
|
5569
|
+
return getSplitChatHistory({
|
|
5570
|
+
service: projectId,
|
|
5571
|
+
owner,
|
|
5572
|
+
platform,
|
|
5573
|
+
userId: id.userId,
|
|
5574
|
+
// An anonymous visitor's history is scoped server side by
|
|
5575
|
+
// ip + "(" + user_agent + ")", which two devices behind one NAT
|
|
5576
|
+
// share. Read this device's own queue instead. See
|
|
5577
|
+
// scopeSurfaceToQueue.
|
|
5578
|
+
scopeSurfaceToQueue: !!id.anonymous
|
|
5579
|
+
}, options);
|
|
5560
5580
|
};
|
|
5561
5581
|
return Promise.resolve().then(fetchHistory).catch(function(err) {
|
|
5562
5582
|
if (isAuthExpiredError(err) && !isNonRetryableRequestError(err)) return self.host.refreshSession().then(fetchHistory);
|
|
@@ -5578,6 +5598,10 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
5578
5598
|
var mapped = mapHistoryListToMessages(list, platform, {
|
|
5579
5599
|
clearedAt: self.host.getClearedAt(),
|
|
5580
5600
|
projectId: id.projectId,
|
|
5601
|
+
// So the `_ownerKey` stamped on server history matches loadKey and
|
|
5602
|
+
// the cache key. Without it every mapped bubble carries a
|
|
5603
|
+
// two-segment stamp that no comparison can ever match.
|
|
5604
|
+
userId: id.userId,
|
|
5581
5605
|
formatIndexingLabel: self.host.formatIndexingLabel
|
|
5582
5606
|
}).messages;
|
|
5583
5607
|
self.applyHydratedBodies(mapped);
|
|
@@ -5786,6 +5810,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
5786
5810
|
var m2 = mapHistoryListToMessages(sorted, platform, {
|
|
5787
5811
|
clearedAt: self.host.getClearedAt(),
|
|
5788
5812
|
projectId: id.projectId,
|
|
5813
|
+
userId: id.userId,
|
|
5789
5814
|
formatIndexingLabel: self.host.formatIndexingLabel
|
|
5790
5815
|
}).messages;
|
|
5791
5816
|
self.applyHydratedBodies(m2);
|
|
@@ -6578,7 +6603,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
6578
6603
|
(function() {
|
|
6579
6604
|
var MCP_PROD = "https://mcp.broadwayinc.computer";
|
|
6580
6605
|
var MCP_DEV = "https://mcp-dev.broadwayinc.computer";
|
|
6581
|
-
var BQ_VERSION = "1.9.
|
|
6606
|
+
var BQ_VERSION = "1.9.6" ;
|
|
6582
6607
|
var ATTACHMENT_URL_EXPIRES_SECONDS = 600;
|
|
6583
6608
|
var GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
6584
6609
|
var GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
|
package/dist/engine.cjs
CHANGED
|
@@ -2346,6 +2346,7 @@ async function _getSplitChatHistoryLocked(key, params, fetchOptions, releaseLock
|
|
|
2346
2346
|
const fetch = _fetchImpl || getChatHistory;
|
|
2347
2347
|
const bgQueue = bgIndexingQueueName(params.userId, params.service);
|
|
2348
2348
|
const base = { service: params.service, owner: params.owner, platform: params.platform };
|
|
2349
|
+
const surfaceScope = params.scopeSurfaceToQueue && params.userId ? { queue: params.userId, queue_exact: true } : { queue_exclude: bgQueue };
|
|
2349
2350
|
const fetchMore = !!(fetchOptions && fetchOptions.fetchMore);
|
|
2350
2351
|
const limit = fetchOptions && fetchOptions.limit;
|
|
2351
2352
|
const firstLoad = !splitHistoryStates[key];
|
|
@@ -2373,13 +2374,13 @@ async function _getSplitChatHistoryLocked(key, params, fetchOptions, releaseLock
|
|
|
2373
2374
|
} else {
|
|
2374
2375
|
const sOpts = { fetchMore };
|
|
2375
2376
|
if (limit) sOpts.limit = limit;
|
|
2376
|
-
let s = await fetch({ ...base,
|
|
2377
|
+
let s = await fetch({ ...base, ...surfaceScope }, sOpts);
|
|
2377
2378
|
let hops = 0;
|
|
2378
2379
|
while (s && !s.endOfList && !(s.list || []).length && hops < SURFACE_EMPTY_MAX_PAGES) {
|
|
2379
2380
|
hops++;
|
|
2380
2381
|
const nOpts = { fetchMore: true };
|
|
2381
2382
|
if (limit) nOpts.limit = limit;
|
|
2382
|
-
s = await fetch({ ...base,
|
|
2383
|
+
s = await fetch({ ...base, ...surfaceScope }, nOpts);
|
|
2383
2384
|
}
|
|
2384
2385
|
state.pendingSurface = {
|
|
2385
2386
|
list: s && Array.isArray(s.list) ? s.list : [],
|
|
@@ -2512,6 +2513,14 @@ async function _getSplitChatHistoryLocked(key, params, fetchOptions, releaseLock
|
|
|
2512
2513
|
firstLoad
|
|
2513
2514
|
};
|
|
2514
2515
|
}
|
|
2516
|
+
function chatCacheKey(projectId, platform, userId) {
|
|
2517
|
+
if (!projectId || platform === "none") return "";
|
|
2518
|
+
return projectId + "#" + platform + "#" + (userId || "");
|
|
2519
|
+
}
|
|
2520
|
+
function indexScopeKey(projectId, platform) {
|
|
2521
|
+
if (!projectId || platform === "none") return "";
|
|
2522
|
+
return projectId + "#" + platform;
|
|
2523
|
+
}
|
|
2515
2524
|
function mapHistoryListToMessages(list, platform, opts) {
|
|
2516
2525
|
var mapped = [], runningItemIds = [];
|
|
2517
2526
|
var extractAssistantText = platform === "openai" ? extractOpenAIText : extractClaudeText;
|
|
@@ -2598,7 +2607,7 @@ function mapHistoryListToMessages(list, platform, opts) {
|
|
|
2598
2607
|
}
|
|
2599
2608
|
});
|
|
2600
2609
|
if (opts.projectId) {
|
|
2601
|
-
var ownerKey = opts.projectId
|
|
2610
|
+
var ownerKey = chatCacheKey(opts.projectId, platform, opts.userId);
|
|
2602
2611
|
for (var oi = 0; oi < mapped.length; oi++) mapped[oi]._ownerKey = ownerKey;
|
|
2603
2612
|
}
|
|
2604
2613
|
return { messages: mapped, runningItemIds };
|
|
@@ -3125,7 +3134,8 @@ var ChatSession = class {
|
|
|
3125
3134
|
/** Storage paths are project-relative, and one ChatSession serves every
|
|
3126
3135
|
* project, so a claim has to be scoped the way a stop is (_indexKeyOf). */
|
|
3127
3136
|
_indexClaimKey(storagePath) {
|
|
3128
|
-
|
|
3137
|
+
var id = this.host.getIdentity();
|
|
3138
|
+
return indexScopeKey(id.projectId, id.platform) + "|" + storagePath;
|
|
3129
3139
|
}
|
|
3130
3140
|
/**
|
|
3131
3141
|
* Take this file's indexing slot, or report that someone already has it.
|
|
@@ -3567,8 +3577,7 @@ var ChatSession = class {
|
|
|
3567
3577
|
*/
|
|
3568
3578
|
getHistoryCacheKey() {
|
|
3569
3579
|
var id = this.host.getIdentity();
|
|
3570
|
-
|
|
3571
|
-
return id.projectId + "#" + id.platform + "#" + (id.userId || "");
|
|
3580
|
+
return chatCacheKey(id.projectId, id.platform, id.userId);
|
|
3572
3581
|
}
|
|
3573
3582
|
/** Re-apply memoized hydrated texts onto freshly-mapped messages. Both
|
|
3574
3583
|
* clients call this right after their mapper runs (loadHistory does it
|
|
@@ -4118,7 +4127,7 @@ var ChatSession = class {
|
|
|
4118
4127
|
}
|
|
4119
4128
|
if (stageId) delete this._liveStages[stageId];
|
|
4120
4129
|
var llmComposed = composedForLlm || composed;
|
|
4121
|
-
var key =
|
|
4130
|
+
var key = chatCacheKey(id.projectId, id.platform, id.userId);
|
|
4122
4131
|
var offChat = !!key && key !== this.getHistoryCacheKey();
|
|
4123
4132
|
var isQueuedSend = !offChat && (useBgQueue || this.state.sending || this.state.messages.some(function(m) {
|
|
4124
4133
|
return (m.isPending || m.isPendingQueued) && !m.isBackgroundTask && !m._useBgQueue;
|
|
@@ -4684,7 +4693,8 @@ var ChatSession = class {
|
|
|
4684
4693
|
cancelIndexingGroup(group) {
|
|
4685
4694
|
var self = this;
|
|
4686
4695
|
if (!group || !group.key) return;
|
|
4687
|
-
var
|
|
4696
|
+
var idn = this.host.getIdentity();
|
|
4697
|
+
var scoped = indexScopeKey(idn.projectId, idn.platform) + "|" + group.key;
|
|
4688
4698
|
this.cancelledIndexKeys.add(scoped);
|
|
4689
4699
|
if (!group.finished) {
|
|
4690
4700
|
var stoppedIds = {};
|
|
@@ -5152,7 +5162,7 @@ var ChatSession = class {
|
|
|
5152
5162
|
if (!entry) return "";
|
|
5153
5163
|
var file = entry.storagePath || entry.filename;
|
|
5154
5164
|
if (!file) return "";
|
|
5155
|
-
return entry.projectId
|
|
5165
|
+
return indexScopeKey(entry.projectId, entry.platform) + "|" + file;
|
|
5156
5166
|
}
|
|
5157
5167
|
/**
|
|
5158
5168
|
* Reconcile the bg queue with the files the user has stopped.
|
|
@@ -5679,7 +5689,7 @@ var ChatSession = class {
|
|
|
5679
5689
|
loadHistory(fetchMore, token) {
|
|
5680
5690
|
var self = this;
|
|
5681
5691
|
var id = this.host.getIdentity();
|
|
5682
|
-
var loadKey =
|
|
5692
|
+
var loadKey = chatCacheKey(id.projectId, id.platform, id.userId);
|
|
5683
5693
|
if (token === void 0) token = this.state.gateRefreshToken;
|
|
5684
5694
|
if (this.state.loadingHistory && this.state.historyRequestToken === token || id.platform === "none" || !id.projectId) {
|
|
5685
5695
|
return Promise.resolve();
|
|
@@ -5698,7 +5708,17 @@ var ChatSession = class {
|
|
|
5698
5708
|
if (fetchMore && this.state.historyStartKeyHistory.length) options.startKeyHistory = this.state.historyStartKeyHistory.slice();
|
|
5699
5709
|
if (!fetchMore) options.deferBg = true;
|
|
5700
5710
|
var fetchHistory = function() {
|
|
5701
|
-
return getSplitChatHistory({
|
|
5711
|
+
return getSplitChatHistory({
|
|
5712
|
+
service: projectId,
|
|
5713
|
+
owner,
|
|
5714
|
+
platform,
|
|
5715
|
+
userId: id.userId,
|
|
5716
|
+
// An anonymous visitor's history is scoped server side by
|
|
5717
|
+
// ip + "(" + user_agent + ")", which two devices behind one NAT
|
|
5718
|
+
// share. Read this device's own queue instead. See
|
|
5719
|
+
// scopeSurfaceToQueue.
|
|
5720
|
+
scopeSurfaceToQueue: !!id.anonymous
|
|
5721
|
+
}, options);
|
|
5702
5722
|
};
|
|
5703
5723
|
return Promise.resolve().then(fetchHistory).catch(function(err) {
|
|
5704
5724
|
if (isAuthExpiredError(err) && !isNonRetryableRequestError(err)) return self.host.refreshSession().then(fetchHistory);
|
|
@@ -5720,6 +5740,10 @@ var ChatSession = class {
|
|
|
5720
5740
|
var mapped = mapHistoryListToMessages(list, platform, {
|
|
5721
5741
|
clearedAt: self.host.getClearedAt(),
|
|
5722
5742
|
projectId: id.projectId,
|
|
5743
|
+
// So the `_ownerKey` stamped on server history matches loadKey and
|
|
5744
|
+
// the cache key. Without it every mapped bubble carries a
|
|
5745
|
+
// two-segment stamp that no comparison can ever match.
|
|
5746
|
+
userId: id.userId,
|
|
5723
5747
|
formatIndexingLabel: self.host.formatIndexingLabel
|
|
5724
5748
|
}).messages;
|
|
5725
5749
|
self.applyHydratedBodies(mapped);
|
|
@@ -5928,6 +5952,7 @@ var ChatSession = class {
|
|
|
5928
5952
|
var m2 = mapHistoryListToMessages(sorted, platform, {
|
|
5929
5953
|
clearedAt: self.host.getClearedAt(),
|
|
5930
5954
|
projectId: id.projectId,
|
|
5955
|
+
userId: id.userId,
|
|
5931
5956
|
formatIndexingLabel: self.host.formatIndexingLabel
|
|
5932
5957
|
}).messages;
|
|
5933
5958
|
self.applyHydratedBodies(m2);
|
|
@@ -6787,6 +6812,7 @@ exports.callClaudeWithMcp = callClaudeWithMcp;
|
|
|
6787
6812
|
exports.callClaudeWithPublicMcp = callClaudeWithPublicMcp;
|
|
6788
6813
|
exports.callOpenAIWithPublicMcp = callOpenAIWithPublicMcp;
|
|
6789
6814
|
exports.canonicalizePathForm = canonicalizePathForm;
|
|
6815
|
+
exports.chatCacheKey = chatCacheKey;
|
|
6790
6816
|
exports.chatEngineConfig = chatEngineConfig;
|
|
6791
6817
|
exports.classifyInlineLink = classifyInlineLink;
|
|
6792
6818
|
exports.clearAttachmentParsers = clearAttachmentParsers;
|
|
@@ -6830,6 +6856,7 @@ exports.groupAttachmentFailures = groupAttachmentFailures;
|
|
|
6830
6856
|
exports.hasBom = hasBom;
|
|
6831
6857
|
exports.hydrateImagePreviews = hydrateImagePreviews;
|
|
6832
6858
|
exports.indexDoneUniqueId = indexDoneUniqueId;
|
|
6859
|
+
exports.indexScopeKey = indexScopeKey;
|
|
6833
6860
|
exports.indexingAccessGroup = indexingAccessGroup;
|
|
6834
6861
|
exports.isAuthExpiredError = isAuthExpiredError;
|
|
6835
6862
|
exports.isBgIndexingQueue = isBgIndexingQueue;
|