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