bunnyquery 1.8.0 → 1.8.1
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 +273 -32
- package/dist/engine.cjs +288 -29
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.mts +135 -2
- package/dist/engine.d.ts +135 -2
- package/dist/engine.mjs +280 -30
- package/dist/engine.mjs.map +1 -1
- package/package.json +1 -1
- package/src/engine/ai_agent.ts +80 -0
- package/src/engine/budget.ts +113 -7
- package/src/engine/history.ts +48 -18
- package/src/engine/index.ts +8 -0
- package/src/engine/requests.ts +11 -2
- package/src/engine/session.ts +202 -3
package/dist/engine.cjs
CHANGED
|
@@ -757,25 +757,74 @@ function truncateLabelForDisplay(label) {
|
|
|
757
757
|
// src/engine/budget.ts
|
|
758
758
|
var CONTEXT_WINDOW_DEFAULT = { claude: 2e5, openai: 128e3 };
|
|
759
759
|
var CONTEXT_WINDOW_BY_MODEL = {
|
|
760
|
-
|
|
760
|
+
// exact ids
|
|
761
|
+
"claude-opus-5": 1e6,
|
|
762
|
+
"claude-opus-4-8": 1e6,
|
|
763
|
+
"claude-opus-4-7": 1e6,
|
|
764
|
+
"claude-sonnet-5": 1e6,
|
|
765
|
+
"claude-sonnet-4-6": 1e6,
|
|
761
766
|
"claude-sonnet-4": 2e5,
|
|
762
|
-
"
|
|
767
|
+
"claude-haiku-4-5": 2e5,
|
|
768
|
+
"gpt-5.4": 128e3,
|
|
769
|
+
"gpt-5.6-luna": 128e3,
|
|
770
|
+
// family keys
|
|
771
|
+
"claude-opus": 1e6,
|
|
772
|
+
"claude-sonnet": 1e6,
|
|
773
|
+
"claude-haiku": 2e5,
|
|
774
|
+
"gpt-5.6": 128e3,
|
|
775
|
+
"gpt-5": 128e3
|
|
763
776
|
};
|
|
777
|
+
var apiReportedContextWindows = {};
|
|
778
|
+
function registerModelContextWindows(models) {
|
|
779
|
+
if (!Array.isArray(models)) return;
|
|
780
|
+
for (var i = 0; i < models.length; i++) {
|
|
781
|
+
var m = models[i];
|
|
782
|
+
var id = (m && m.id ? String(m.id) : "").trim().toLowerCase();
|
|
783
|
+
var reported = m ? Number(m.max_input_tokens) : NaN;
|
|
784
|
+
if (id && Number.isFinite(reported) && reported > 0) {
|
|
785
|
+
apiReportedContextWindows[id] = Math.floor(reported);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
var projectContextWindows = {};
|
|
790
|
+
function setProjectContextWindow(serviceId, tokens) {
|
|
791
|
+
var key = (serviceId || "").trim();
|
|
792
|
+
if (!key) return;
|
|
793
|
+
var n = Number(tokens);
|
|
794
|
+
if (Number.isFinite(n) && n > 0) projectContextWindows[key] = Math.floor(n);
|
|
795
|
+
else delete projectContextWindows[key];
|
|
796
|
+
}
|
|
797
|
+
function getProjectContextWindow(serviceId) {
|
|
798
|
+
var key = (serviceId || "").trim();
|
|
799
|
+
return key && projectContextWindows[key] ? projectContextWindows[key] : null;
|
|
800
|
+
}
|
|
764
801
|
var OUTPUT_TOKEN_RESERVE = 22e3;
|
|
765
802
|
var TOOL_AND_RESPONSE_BUFFER = 4e3;
|
|
766
803
|
var MIN_INPUT_TOKEN_BUDGET = 8e3;
|
|
767
804
|
var CLAUDE_PER_REQUEST_INPUT_CAP = 28e3;
|
|
768
805
|
var MAX_HISTORY_MESSAGES = 20;
|
|
769
806
|
var HISTORY_TOKEN_BUDGET = 8e3;
|
|
807
|
+
var CLAUDE_INPUT_CAP_RATIO = 0.16;
|
|
808
|
+
var HISTORY_BUDGET_RATIO = 0.08;
|
|
770
809
|
function estimateTextTokens(text) {
|
|
771
810
|
return Math.ceil((text || "").length / 3);
|
|
772
811
|
}
|
|
773
812
|
function estimateMessageTokens(msg) {
|
|
774
813
|
return estimateTextTokens(msg.content) + estimateTextTokens(msg.role) + 6;
|
|
775
814
|
}
|
|
776
|
-
function getContextWindow(platform, model) {
|
|
815
|
+
function getContextWindow(platform, model, serviceId) {
|
|
816
|
+
var override = serviceId ? getProjectContextWindow(serviceId) : null;
|
|
817
|
+
if (override) return override;
|
|
777
818
|
var normalized = (model || "").trim().toLowerCase();
|
|
778
|
-
if (normalized
|
|
819
|
+
if (normalized) {
|
|
820
|
+
if (apiReportedContextWindows[normalized]) return apiReportedContextWindows[normalized];
|
|
821
|
+
if (CONTEXT_WINDOW_BY_MODEL[normalized]) return CONTEXT_WINDOW_BY_MODEL[normalized];
|
|
822
|
+
var parts = normalized.split("-");
|
|
823
|
+
for (var end = parts.length - 1; end > 0; end--) {
|
|
824
|
+
var family = parts.slice(0, end).join("-");
|
|
825
|
+
if (CONTEXT_WINDOW_BY_MODEL[family]) return CONTEXT_WINDOW_BY_MODEL[family];
|
|
826
|
+
}
|
|
827
|
+
}
|
|
779
828
|
return CONTEXT_WINDOW_DEFAULT[platform];
|
|
780
829
|
}
|
|
781
830
|
function stripFileBlocksFromHistory(content) {
|
|
@@ -783,15 +832,19 @@ function stripFileBlocksFromHistory(content) {
|
|
|
783
832
|
return content.replace(/```([^\n`]+?\.[^\s.`]+)\n[\s\S]*?```/g, "[file previously attached: $1]");
|
|
784
833
|
}
|
|
785
834
|
function buildBoundedChatMessages(options) {
|
|
786
|
-
var contextWindow = getContextWindow(options.platform, options.model);
|
|
835
|
+
var contextWindow = getContextWindow(options.platform, options.model, options.serviceId);
|
|
787
836
|
var contextBasedBudget = Math.max(
|
|
788
837
|
MIN_INPUT_TOKEN_BUDGET,
|
|
789
838
|
contextWindow - OUTPUT_TOKEN_RESERVE - TOOL_AND_RESPONSE_BUFFER
|
|
790
839
|
);
|
|
791
|
-
var
|
|
840
|
+
var scaled = !!(options.serviceId && getProjectContextWindow(options.serviceId));
|
|
841
|
+
var claudeInputCap = scaled ? Math.max(CLAUDE_PER_REQUEST_INPUT_CAP, Math.round(contextBasedBudget * CLAUDE_INPUT_CAP_RATIO)) : CLAUDE_PER_REQUEST_INPUT_CAP;
|
|
842
|
+
var availableInputBudget = options.platform === "claude" ? Math.min(contextBasedBudget, claudeInputCap) : contextBasedBudget;
|
|
792
843
|
var systemCost = estimateTextTokens(options.systemPrompt) + 12;
|
|
793
|
-
var
|
|
794
|
-
var
|
|
844
|
+
var historyAllowance = scaled ? Math.max(HISTORY_TOKEN_BUDGET, Math.round(contextBasedBudget * HISTORY_BUDGET_RATIO)) : HISTORY_TOKEN_BUDGET;
|
|
845
|
+
var budgetForHistory = Math.max(1e3, Math.min(historyAllowance, availableInputBudget - systemCost));
|
|
846
|
+
var maxHistoryMessages = scaled ? Math.max(MAX_HISTORY_MESSAGES, Math.round(MAX_HISTORY_MESSAGES * (budgetForHistory / HISTORY_TOKEN_BUDGET))) : MAX_HISTORY_MESSAGES;
|
|
847
|
+
var windowed = options.history.slice(-maxHistoryMessages);
|
|
795
848
|
var latestIndex = windowed.length - 1;
|
|
796
849
|
var trimmed = windowed.map(function(m, i2) {
|
|
797
850
|
if (i2 === latestIndex) return m;
|
|
@@ -836,6 +889,40 @@ function formatChatTimestamp(ms) {
|
|
|
836
889
|
}
|
|
837
890
|
}
|
|
838
891
|
|
|
892
|
+
// src/engine/ai_agent.ts
|
|
893
|
+
function normalizePlatform(raw) {
|
|
894
|
+
var p = (raw || "").trim().toLowerCase();
|
|
895
|
+
return p === "claude" || p === "openai" ? p : null;
|
|
896
|
+
}
|
|
897
|
+
function parseAiAgentValue(value) {
|
|
898
|
+
var raw = (value || "").trim();
|
|
899
|
+
if (!raw || raw.toLowerCase() === "none") {
|
|
900
|
+
return { platform: null, model: "", contextWindow: null, hasPlatform: false };
|
|
901
|
+
}
|
|
902
|
+
var firstHash = raw.indexOf("#");
|
|
903
|
+
if (firstHash === -1) {
|
|
904
|
+
var only = normalizePlatform(raw);
|
|
905
|
+
return { platform: only, model: "", contextWindow: null, hasPlatform: !!only };
|
|
906
|
+
}
|
|
907
|
+
var platform = normalizePlatform(raw.slice(0, firstHash));
|
|
908
|
+
var rest = raw.slice(firstHash + 1);
|
|
909
|
+
var secondHash = rest.indexOf("#");
|
|
910
|
+
var model = (secondHash === -1 ? rest : rest.slice(0, secondHash)).trim();
|
|
911
|
+
var windowRaw = secondHash === -1 ? "" : rest.slice(secondHash + 1).trim();
|
|
912
|
+
var parsedWindow = windowRaw ? Number(windowRaw) : NaN;
|
|
913
|
+
var contextWindow = Number.isFinite(parsedWindow) && parsedWindow > 0 ? Math.floor(parsedWindow) : null;
|
|
914
|
+
return { platform, model, contextWindow, hasPlatform: !!platform };
|
|
915
|
+
}
|
|
916
|
+
function buildAiAgentValue(platform, model, contextWindow) {
|
|
917
|
+
var p = (platform || "").trim().toLowerCase();
|
|
918
|
+
if (!p || p === "none") return "none";
|
|
919
|
+
var m = (model || "").trim();
|
|
920
|
+
if (!m) return p;
|
|
921
|
+
var n = Number(contextWindow);
|
|
922
|
+
if (!Number.isFinite(n) || n <= 0) return p + "#" + m;
|
|
923
|
+
return p + "#" + m + "#" + Math.floor(n);
|
|
924
|
+
}
|
|
925
|
+
|
|
839
926
|
// src/engine/requests.ts
|
|
840
927
|
var ANTHROPIC_MESSAGES_API_URL = "https://api.anthropic.com/v1/messages";
|
|
841
928
|
var ANTHROPIC_MODELS_API_URL = "https://api.anthropic.com/v1/models";
|
|
@@ -1344,7 +1431,8 @@ async function getChatHistory(params, fetchOptions) {
|
|
|
1344
1431
|
method: "POST"
|
|
1345
1432
|
},
|
|
1346
1433
|
{ service: params.service, owner: params.owner },
|
|
1347
|
-
params.queue ? { queue: params.queue } : {}
|
|
1434
|
+
params.queue ? { queue: params.queue } : {},
|
|
1435
|
+
params.status ? { status: params.status } : {}
|
|
1348
1436
|
);
|
|
1349
1437
|
return chatEngineConfig().clientSecretRequestHistory(
|
|
1350
1438
|
p,
|
|
@@ -1381,6 +1469,25 @@ function extractLastUserTextFromRequest(requestBody) {
|
|
|
1381
1469
|
}
|
|
1382
1470
|
return "";
|
|
1383
1471
|
}
|
|
1472
|
+
function isIndexingRequestText(userText) {
|
|
1473
|
+
if (typeof userText !== "string") return false;
|
|
1474
|
+
return userText.indexOf("A new file has just been uploaded") === 0 || userText.indexOf("CONTINUE indexing") === 0;
|
|
1475
|
+
}
|
|
1476
|
+
function parseIndexingRequestText(userText) {
|
|
1477
|
+
if (typeof userText !== "string" || !userText) return null;
|
|
1478
|
+
var nameMatch = userText.match(/^- name: (.+)$/m);
|
|
1479
|
+
if (!nameMatch) return null;
|
|
1480
|
+
var mimeMatch = userText.match(/^- mime type: (.+)$/m);
|
|
1481
|
+
var sizeMatch = userText.match(/^- size \(bytes\): (\d+)$/m);
|
|
1482
|
+
var pathMatch = userText.match(/^- storage path: (.+)$/m);
|
|
1483
|
+
return {
|
|
1484
|
+
name: nameMatch[1].trim(),
|
|
1485
|
+
path: pathMatch ? pathMatch[1].trim() : void 0,
|
|
1486
|
+
mime: mimeMatch ? mimeMatch[1].trim() : void 0,
|
|
1487
|
+
size: sizeMatch ? Number(sizeMatch[1]) : void 0,
|
|
1488
|
+
continued: userText.indexOf("CONTINUE indexing") === 0
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1384
1491
|
function mapHistoryListToMessages(list, platform, opts) {
|
|
1385
1492
|
var mapped = [], runningItemIds = [];
|
|
1386
1493
|
var extractAssistantText = platform === "openai" ? extractOpenAIText : extractClaudeText;
|
|
@@ -1405,27 +1512,17 @@ function mapHistoryListToMessages(list, platform, opts) {
|
|
|
1405
1512
|
var displayContent;
|
|
1406
1513
|
var indexFile = void 0;
|
|
1407
1514
|
if (item._isBgTask) {
|
|
1408
|
-
var
|
|
1409
|
-
if (
|
|
1410
|
-
var mimeMatch = userText.match(/^- mime type: (.+)$/m);
|
|
1411
|
-
var sizeMatch = userText.match(/^- size \(bytes\): (\d+)$/m);
|
|
1412
|
-
var pathMatch = userText.match(/^- storage path: (.+)$/m);
|
|
1413
|
-
var isContinuePass = userText.indexOf("CONTINUE indexing") === 0;
|
|
1515
|
+
var ref = parseIndexingRequestText(userText);
|
|
1516
|
+
if (ref) {
|
|
1414
1517
|
displayContent = opts.formatIndexingLabel(
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1518
|
+
ref.name,
|
|
1519
|
+
ref.mime || "",
|
|
1520
|
+
typeof ref.size === "number" ? ref.size : null,
|
|
1521
|
+
ref.path,
|
|
1419
1522
|
false,
|
|
1420
|
-
|
|
1523
|
+
ref.continued
|
|
1421
1524
|
);
|
|
1422
|
-
indexFile =
|
|
1423
|
-
name: nameMatch[1].trim(),
|
|
1424
|
-
path: pathMatch ? pathMatch[1].trim() : void 0,
|
|
1425
|
-
mime: mimeMatch ? mimeMatch[1].trim() : void 0,
|
|
1426
|
-
size: sizeMatch ? Number(sizeMatch[1]) : void 0,
|
|
1427
|
-
continued: isContinuePass
|
|
1428
|
-
};
|
|
1525
|
+
indexFile = ref;
|
|
1429
1526
|
} else {
|
|
1430
1527
|
displayContent = userText;
|
|
1431
1528
|
}
|
|
@@ -1554,6 +1651,8 @@ function createHistoryFiller(base) {
|
|
|
1554
1651
|
}
|
|
1555
1652
|
|
|
1556
1653
|
// src/engine/session.ts
|
|
1654
|
+
var WORKER_PASS_ADOPT_LIMIT = 20;
|
|
1655
|
+
var WORKER_PASS_ADOPT_ATTEMPTS = [0, 2e3, 6e3];
|
|
1557
1656
|
var _g = typeof globalThis !== "undefined" ? globalThis : {};
|
|
1558
1657
|
function nowMs() {
|
|
1559
1658
|
return _g.performance && typeof _g.performance.now === "function" ? _g.performance.now() : Date.now();
|
|
@@ -1573,6 +1672,35 @@ function isPollStopped(res) {
|
|
|
1573
1672
|
var ChatSession = class {
|
|
1574
1673
|
constructor(host) {
|
|
1575
1674
|
this.typewriterQueue = Promise.resolve();
|
|
1675
|
+
/**
|
|
1676
|
+
* Pick up indexing passes the WORKER minted, which no client ever dispatched.
|
|
1677
|
+
*
|
|
1678
|
+
* For a PDF (and for text/grid when windowed indexing is on) the worker writes
|
|
1679
|
+
* pass N+1's row itself, inside pass N's invocation, right after saving pass
|
|
1680
|
+
* N's result. That row reaches this client through nothing at all: it is not in
|
|
1681
|
+
* bgTaskQueue (the client never asked for it) and it is not in state.messages
|
|
1682
|
+
* (only a first-page history load maps it in, which happens on mount, project
|
|
1683
|
+
* switch or tab return). So between two worker passes every pass the client
|
|
1684
|
+
* knows about is settled, and the collapsed row renders "Indexed N passes"
|
|
1685
|
+
* with no spinner and no Stop, for a file that is still being read. A user who
|
|
1686
|
+
* believes that then asks questions against a half-indexed file — which is what
|
|
1687
|
+
* this exists to prevent.
|
|
1688
|
+
*
|
|
1689
|
+
* So when a background indexing pass settles, ask the bg queue what is still
|
|
1690
|
+
* unresolved on it and adopt anything unknown as an ordinary BgTaskEntry.
|
|
1691
|
+
* drainBgTaskQueue then treats it exactly like a pass this client dispatched:
|
|
1692
|
+
* same bubble, same `_indexFile` (so it joins the file's collapsed row), same
|
|
1693
|
+
* poll — and that poll settling runs this again, so the chain is followed to
|
|
1694
|
+
* its end. `status`-scoped so the reply carries the live items only, never a
|
|
1695
|
+
* page of finished ones with their bodies.
|
|
1696
|
+
*
|
|
1697
|
+
* Termination: the only trigger is a pass SETTLING, which happens once per
|
|
1698
|
+
* pass. An adopted item that is still running is not re-adopted (its id is
|
|
1699
|
+
* already polled), and when the queue holds nothing unknown the chain stops on
|
|
1700
|
+
* its own. Nothing here is periodic — a timer that re-reads history is the
|
|
1701
|
+
* shape that previously looped fetchHistoryPage after an already-DONE index.
|
|
1702
|
+
*/
|
|
1703
|
+
this._adoptingWorkerPasses = false;
|
|
1576
1704
|
this.host = host;
|
|
1577
1705
|
this.state = {
|
|
1578
1706
|
messages: [],
|
|
@@ -2518,8 +2646,21 @@ var ChatSession = class {
|
|
|
2518
2646
|
}
|
|
2519
2647
|
// --- background-task resolution + drain -------------------------------
|
|
2520
2648
|
handleHistoryItemResolution(itemId, response, platform) {
|
|
2649
|
+
var indexRef = this._indexRefOfItem(itemId);
|
|
2521
2650
|
this.applyHistoryItemResolution(itemId, response, platform);
|
|
2522
2651
|
this.promoteNextBgQueuedToRunning();
|
|
2652
|
+
if (indexRef) this._followWorkerIndexingChain(indexRef.name, indexRef.mime);
|
|
2653
|
+
}
|
|
2654
|
+
/** The file an already-rendered background pass is about, off its request
|
|
2655
|
+
* bubble. Null for an ordinary turn, which is most of them. */
|
|
2656
|
+
_indexRefOfItem(itemId) {
|
|
2657
|
+
if (!itemId) return null;
|
|
2658
|
+
for (var i = 0; i < this.state.messages.length; i++) {
|
|
2659
|
+
var m = this.state.messages[i];
|
|
2660
|
+
if (m._serverItemId !== itemId || m.role !== "user" || !m.isBackgroundTask) continue;
|
|
2661
|
+
return m._indexFile || null;
|
|
2662
|
+
}
|
|
2663
|
+
return null;
|
|
2523
2664
|
}
|
|
2524
2665
|
applyHistoryItemResolution(itemId, response, platform) {
|
|
2525
2666
|
this.historyItemPolls.delete(itemId);
|
|
@@ -2653,6 +2794,116 @@ var ChatSession = class {
|
|
|
2653
2794
|
self.cancelQueuedMessage(t.msg, idx === -1 ? t.idx : idx);
|
|
2654
2795
|
});
|
|
2655
2796
|
}
|
|
2797
|
+
/**
|
|
2798
|
+
* True when the WORKER, not this client, drives the rest of this file's chain.
|
|
2799
|
+
* The mirror image of the early returns in maybeResumeIndexing: whatever that
|
|
2800
|
+
* refuses to continue is exactly what nothing client-side is tracking.
|
|
2801
|
+
*/
|
|
2802
|
+
_isWorkerDrivenIndexing(filename, mime) {
|
|
2803
|
+
if (!isPagedReadFile(filename, mime)) return false;
|
|
2804
|
+
if (isImageVisionFile(filename, mime)) return true;
|
|
2805
|
+
return windowedIndexingEnabled() && isWindowedReadFile(filename, mime);
|
|
2806
|
+
}
|
|
2807
|
+
_adoptWorkerIndexingPasses(attempt) {
|
|
2808
|
+
var self = this;
|
|
2809
|
+
if (this._adoptingWorkerPasses) return;
|
|
2810
|
+
var id = this.host.getIdentity();
|
|
2811
|
+
var platform = id.platform;
|
|
2812
|
+
if (!id.serviceId || platform !== "claude" && platform !== "openai") return;
|
|
2813
|
+
if (this.isPollingPaused() || !this.host.isViewMounted()) return;
|
|
2814
|
+
var svcId = id.serviceId, owner = id.owner;
|
|
2815
|
+
var queue = (id.userId || id.serviceId) + BG_INDEXING_QUEUE_SUFFIX;
|
|
2816
|
+
var ask = function(status) {
|
|
2817
|
+
return Promise.resolve(getChatHistory(
|
|
2818
|
+
{ service: svcId, owner, platform, queue, status },
|
|
2819
|
+
{ limit: WORKER_PASS_ADOPT_LIMIT }
|
|
2820
|
+
)).catch(function() {
|
|
2821
|
+
return null;
|
|
2822
|
+
});
|
|
2823
|
+
};
|
|
2824
|
+
this._adoptingWorkerPasses = true;
|
|
2825
|
+
Promise.all([ask("running"), ask("pending")]).then(function(results) {
|
|
2826
|
+
self._adoptingWorkerPasses = false;
|
|
2827
|
+
var now = self.host.getIdentity();
|
|
2828
|
+
if (now.serviceId !== svcId || now.platform !== platform) return;
|
|
2829
|
+
if (!self.host.isViewMounted()) return;
|
|
2830
|
+
var adoptedIds = [];
|
|
2831
|
+
for (var ri = 0; ri < results.length; ri++) {
|
|
2832
|
+
var list = results[ri] && Array.isArray(results[ri].list) ? results[ri].list : [];
|
|
2833
|
+
for (var i = 0; i < list.length; i++) {
|
|
2834
|
+
if (self._adoptWorkerIndexingItem(list[i], svcId, platform)) adoptedIds.push(list[i].id);
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
if (adoptedIds.length) {
|
|
2838
|
+
self.drainBgTaskQueue();
|
|
2839
|
+
if (self._isTrackingAny(adoptedIds)) return;
|
|
2840
|
+
}
|
|
2841
|
+
if (attempt + 1 >= WORKER_PASS_ADOPT_ATTEMPTS.length) return;
|
|
2842
|
+
setTimeout(function() {
|
|
2843
|
+
var later = self.host.getIdentity();
|
|
2844
|
+
if (later.serviceId !== svcId || later.platform !== platform) return;
|
|
2845
|
+
if (self.isPollingPaused() || !self.host.isViewMounted()) return;
|
|
2846
|
+
self._adoptWorkerIndexingPasses(attempt + 1);
|
|
2847
|
+
}, WORKER_PASS_ADOPT_ATTEMPTS[attempt + 1]);
|
|
2848
|
+
}, function() {
|
|
2849
|
+
self._adoptingWorkerPasses = false;
|
|
2850
|
+
});
|
|
2851
|
+
}
|
|
2852
|
+
/** Any of these ids still queued or still polled, i.e. surviving work. */
|
|
2853
|
+
_isTrackingAny(ids) {
|
|
2854
|
+
for (var i = 0; i < ids.length; i++) {
|
|
2855
|
+
if (this.historyItemPolls.has(ids[i])) return true;
|
|
2856
|
+
for (var q = 0; q < this.bgTaskQueue.length; q++) {
|
|
2857
|
+
if (this.bgTaskQueue[q].id === ids[i]) return true;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
return false;
|
|
2861
|
+
}
|
|
2862
|
+
/** One live bg-queue item -> a BgTaskEntry, if it is an indexing pass this
|
|
2863
|
+
* client is not already tracking. Returns whether it was adopted. */
|
|
2864
|
+
_adoptWorkerIndexingItem(item, svcId, platform) {
|
|
2865
|
+
if (!item || typeof item.id !== "string" || !item.id) return false;
|
|
2866
|
+
if (item.status !== "pending" && item.status !== "running") return false;
|
|
2867
|
+
if (typeof item.poll !== "function") return false;
|
|
2868
|
+
if (this.historyItemPolls.has(item.id)) return false;
|
|
2869
|
+
for (var q = 0; q < this.bgTaskQueue.length; q++) {
|
|
2870
|
+
if (this.bgTaskQueue[q].id === item.id) return false;
|
|
2871
|
+
}
|
|
2872
|
+
for (var m = 0; m < this.state.messages.length; m++) {
|
|
2873
|
+
var msg = this.state.messages[m];
|
|
2874
|
+
if (msg._serverItemId !== item.id) continue;
|
|
2875
|
+
if (!(msg.isPending || msg.isPendingInProcess || msg.isPendingQueued)) return false;
|
|
2876
|
+
}
|
|
2877
|
+
var body = item.request_body;
|
|
2878
|
+
if (!body || typeof body !== "object") return false;
|
|
2879
|
+
if (platform === "claude" ? !Array.isArray(body.messages) : !Array.isArray(body.input)) return false;
|
|
2880
|
+
var userText = extractLastUserTextFromRequest(body);
|
|
2881
|
+
if (!isIndexingRequestText(userText)) return false;
|
|
2882
|
+
var ref = parseIndexingRequestText(userText);
|
|
2883
|
+
if (!ref || !ref.name) return false;
|
|
2884
|
+
if (!this._isWorkerDrivenIndexing(ref.name, ref.mime)) return false;
|
|
2885
|
+
this.bgTaskQueue.push({
|
|
2886
|
+
serviceId: svcId,
|
|
2887
|
+
platform,
|
|
2888
|
+
id: item.id,
|
|
2889
|
+
filename: ref.name,
|
|
2890
|
+
storagePath: ref.path,
|
|
2891
|
+
mime: ref.mime,
|
|
2892
|
+
size: ref.size,
|
|
2893
|
+
status: item.status === "running" ? "running" : "pending",
|
|
2894
|
+
poll: item.poll,
|
|
2895
|
+
// Drives the "(continuing)" label and marks this as a continuation for
|
|
2896
|
+
// _applyIndexCancellations, which must not read a CONTINUE pass as the
|
|
2897
|
+
// fresh first pass that lifts a stop.
|
|
2898
|
+
resumePass: ref.continued ? 1 : 0
|
|
2899
|
+
});
|
|
2900
|
+
return true;
|
|
2901
|
+
}
|
|
2902
|
+
/** Follow the chain on from a background indexing pass that just settled. */
|
|
2903
|
+
_followWorkerIndexingChain(filename, mime) {
|
|
2904
|
+
if (!this._isWorkerDrivenIndexing(filename, mime)) return;
|
|
2905
|
+
this._adoptWorkerIndexingPasses(0);
|
|
2906
|
+
}
|
|
2656
2907
|
/** Best-effort server-side cancel of a bg-queue item that has no bubble (so
|
|
2657
2908
|
* cancelQueuedMessage, which drives one, has nothing to act on). */
|
|
2658
2909
|
_cancelServerItem(serverId) {
|
|
@@ -2863,8 +3114,7 @@ var ChatSession = class {
|
|
|
2863
3114
|
var chatList = history && Array.isArray(history.list) ? history.list : [];
|
|
2864
3115
|
chatList.forEach(function(item) {
|
|
2865
3116
|
if (isBgIndexingQueue(item.queue_name)) {
|
|
2866
|
-
|
|
2867
|
-
if (typeof userText === "string" && (userText.indexOf("A new file has just been uploaded") === 0 || userText.indexOf("CONTINUE indexing") === 0)) item._isBgTask = true;
|
|
3117
|
+
if (isIndexingRequestText(extractLastUserTextFromRequest(item.request_body))) item._isBgTask = true;
|
|
2868
3118
|
else item._isOnBgQueue = true;
|
|
2869
3119
|
}
|
|
2870
3120
|
});
|
|
@@ -3432,6 +3682,7 @@ function buildChatDisplayList(messages, opts) {
|
|
|
3432
3682
|
}
|
|
3433
3683
|
|
|
3434
3684
|
exports.BG_INDEXING_QUEUE_SUFFIX = BG_INDEXING_QUEUE_SUFFIX;
|
|
3685
|
+
exports.CLAUDE_INPUT_CAP_RATIO = CLAUDE_INPUT_CAP_RATIO;
|
|
3435
3686
|
exports.CLAUDE_PER_REQUEST_INPUT_CAP = CLAUDE_PER_REQUEST_INPUT_CAP;
|
|
3436
3687
|
exports.CONTEXT_WINDOW_BY_MODEL = CONTEXT_WINDOW_BY_MODEL;
|
|
3437
3688
|
exports.CONTEXT_WINDOW_DEFAULT = CONTEXT_WINDOW_DEFAULT;
|
|
@@ -3441,6 +3692,7 @@ exports.DEFAULT_OPENAI_MODEL = DEFAULT_OPENAI_MODEL;
|
|
|
3441
3692
|
exports.EXPIRED_ATTACHMENT_URL_HOST = EXPIRED_ATTACHMENT_URL_HOST;
|
|
3442
3693
|
exports.EXPIRED_ATTACHMENT_URL_ORIGIN = EXPIRED_ATTACHMENT_URL_ORIGIN;
|
|
3443
3694
|
exports.EXPIRED_LINK_REFRESH_EXPIRES_SECONDS = EXPIRED_LINK_REFRESH_EXPIRES_SECONDS;
|
|
3695
|
+
exports.HISTORY_BUDGET_RATIO = HISTORY_BUDGET_RATIO;
|
|
3444
3696
|
exports.HISTORY_FILL_SLACK_PX = HISTORY_FILL_SLACK_PX;
|
|
3445
3697
|
exports.HISTORY_TOKEN_BUDGET = HISTORY_TOKEN_BUDGET;
|
|
3446
3698
|
exports.LINK_LABEL_MAX_DISPLAY_CHARS = LINK_LABEL_MAX_DISPLAY_CHARS;
|
|
@@ -3454,6 +3706,7 @@ exports.OUTPUT_TOKEN_RESERVE = OUTPUT_TOKEN_RESERVE;
|
|
|
3454
3706
|
exports.POLL_INTERVAL = POLL_INTERVAL;
|
|
3455
3707
|
exports.RENDER_FROM_TOKEN = RENDER_FROM_TOKEN;
|
|
3456
3708
|
exports.TOOL_AND_RESPONSE_BUFFER = TOOL_AND_RESPONSE_BUFFER;
|
|
3709
|
+
exports.buildAiAgentValue = buildAiAgentValue;
|
|
3457
3710
|
exports.buildBoundedChatMessages = buildBoundedChatMessages;
|
|
3458
3711
|
exports.buildChatDisplayList = buildChatDisplayList;
|
|
3459
3712
|
exports.buildChatSystemPrompt = buildChatSystemPrompt;
|
|
@@ -3490,11 +3743,13 @@ exports.getChatHistory = getChatHistory;
|
|
|
3490
3743
|
exports.getContextWindow = getContextWindow;
|
|
3491
3744
|
exports.getErrorMessage = getErrorMessage;
|
|
3492
3745
|
exports.getExpiredAttachmentVisiblePath = getExpiredAttachmentVisiblePath;
|
|
3746
|
+
exports.getProjectContextWindow = getProjectContextWindow;
|
|
3493
3747
|
exports.groupAttachmentFailures = groupAttachmentFailures;
|
|
3494
3748
|
exports.isAuthExpiredError = isAuthExpiredError;
|
|
3495
3749
|
exports.isBgIndexingQueue = isBgIndexingQueue;
|
|
3496
3750
|
exports.isErrorResponseBody = isErrorResponseBody;
|
|
3497
3751
|
exports.isHttpUrlLike = isHttpUrlLike;
|
|
3752
|
+
exports.isIndexingRequestText = isIndexingRequestText;
|
|
3498
3753
|
exports.isNonRetryableRequestError = isNonRetryableRequestError;
|
|
3499
3754
|
exports.isOfficeFile = isOfficeFile;
|
|
3500
3755
|
exports.isServerExtractable = isServerExtractable;
|
|
@@ -3507,14 +3762,18 @@ exports.normalizeAttachmentPathCandidate = normalizeAttachmentPathCandidate;
|
|
|
3507
3762
|
exports.normalizeTextContent = normalizeTextContent;
|
|
3508
3763
|
exports.normalizeTrailingInlineToken = normalizeTrailingInlineToken;
|
|
3509
3764
|
exports.notifyAgentSaveAttachment = notifyAgentSaveAttachment;
|
|
3765
|
+
exports.parseAiAgentValue = parseAiAgentValue;
|
|
3510
3766
|
exports.parseAttachmentContent = parseAttachmentContent;
|
|
3511
3767
|
exports.parseIndexingLabel = parseIndexingLabel;
|
|
3768
|
+
exports.parseIndexingRequestText = parseIndexingRequestText;
|
|
3512
3769
|
exports.readExpiredAttachmentHref = readExpiredAttachmentHref;
|
|
3513
3770
|
exports.registerAttachmentParser = registerAttachmentParser;
|
|
3771
|
+
exports.registerModelContextWindows = registerModelContextWindows;
|
|
3514
3772
|
exports.repairUrlEntities = repairUrlEntities;
|
|
3515
3773
|
exports.repairUrlWhitespace = repairUrlWhitespace;
|
|
3516
3774
|
exports.safeDecodeURIComponent = safeDecodeURIComponent;
|
|
3517
3775
|
exports.sanitizeAttachmentLinksForHistory = sanitizeAttachmentLinksForHistory;
|
|
3776
|
+
exports.setProjectContextWindow = setProjectContextWindow;
|
|
3518
3777
|
exports.stripFileBlocksFromHistory = stripFileBlocksFromHistory;
|
|
3519
3778
|
exports.transformContentWithImages = transformContentWithImages;
|
|
3520
3779
|
exports.transformContentWithOpenAIImages = transformContentWithOpenAIImages;
|