bunnyquery 1.8.0 → 1.8.2
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 +455 -43
- package/dist/engine.cjs +489 -33
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.mts +232 -3
- package/dist/engine.d.ts +232 -3
- package/dist/engine.mjs +462 -34
- 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/download_encoding.ts +281 -0
- package/src/engine/errors.ts +34 -0
- package/src/engine/history.ts +48 -18
- package/src/engine/index.ts +11 -0
- package/src/engine/requests.ts +15 -3
- package/src/engine/session.ts +227 -6
package/dist/engine.mjs
CHANGED
|
@@ -437,6 +437,19 @@ Index the REMAINING windows - one record per row/item, looking at any page image
|
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
// src/engine/errors.ts
|
|
440
|
+
var STATUS_MESSAGE = {
|
|
441
|
+
"408": "The AI provider timed out before it started.",
|
|
442
|
+
"409": "The AI provider rejected the request as conflicting.",
|
|
443
|
+
"413": "The request was too large for the AI provider.",
|
|
444
|
+
"429": "The AI provider is rate limiting requests right now.",
|
|
445
|
+
"500": "The AI provider hit an internal error.",
|
|
446
|
+
"502": "The AI provider is temporarily unreachable.",
|
|
447
|
+
"503": "The AI provider is temporarily unavailable.",
|
|
448
|
+
"504": "The AI provider timed out."
|
|
449
|
+
};
|
|
450
|
+
function isTransientStatus(status) {
|
|
451
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
452
|
+
}
|
|
440
453
|
function getErrorMessage(input) {
|
|
441
454
|
if (!input) return "Something went wrong.";
|
|
442
455
|
if (typeof input === "string") return input;
|
|
@@ -444,6 +457,11 @@ function getErrorMessage(input) {
|
|
|
444
457
|
if (input.body && input.body.error && input.body.error.message) return input.body.error.message;
|
|
445
458
|
if (input.body && typeof input.body.message === "string") return input.body.message;
|
|
446
459
|
if (input.message) return input.message;
|
|
460
|
+
var status = typeof input.status_code === "number" ? input.status_code : typeof input.status === "number" ? input.status : 0;
|
|
461
|
+
if (status) {
|
|
462
|
+
var text = STATUS_MESSAGE[String(status)] || (status >= 500 ? "The AI provider returned a server error." : "The AI provider rejected the request.");
|
|
463
|
+
return text + " (error " + status + ")" + (isTransientStatus(status) ? " This is usually temporary, please try again." : "");
|
|
464
|
+
}
|
|
447
465
|
return "Something went wrong.";
|
|
448
466
|
}
|
|
449
467
|
function isErrorResponseBody(response) {
|
|
@@ -755,25 +773,74 @@ function truncateLabelForDisplay(label) {
|
|
|
755
773
|
// src/engine/budget.ts
|
|
756
774
|
var CONTEXT_WINDOW_DEFAULT = { claude: 2e5, openai: 128e3 };
|
|
757
775
|
var CONTEXT_WINDOW_BY_MODEL = {
|
|
758
|
-
|
|
776
|
+
// exact ids
|
|
777
|
+
"claude-opus-5": 1e6,
|
|
778
|
+
"claude-opus-4-8": 1e6,
|
|
779
|
+
"claude-opus-4-7": 1e6,
|
|
780
|
+
"claude-sonnet-5": 1e6,
|
|
781
|
+
"claude-sonnet-4-6": 1e6,
|
|
759
782
|
"claude-sonnet-4": 2e5,
|
|
760
|
-
"
|
|
783
|
+
"claude-haiku-4-5": 2e5,
|
|
784
|
+
"gpt-5.4": 128e3,
|
|
785
|
+
"gpt-5.6-luna": 128e3,
|
|
786
|
+
// family keys
|
|
787
|
+
"claude-opus": 1e6,
|
|
788
|
+
"claude-sonnet": 1e6,
|
|
789
|
+
"claude-haiku": 2e5,
|
|
790
|
+
"gpt-5.6": 128e3,
|
|
791
|
+
"gpt-5": 128e3
|
|
761
792
|
};
|
|
793
|
+
var apiReportedContextWindows = {};
|
|
794
|
+
function registerModelContextWindows(models) {
|
|
795
|
+
if (!Array.isArray(models)) return;
|
|
796
|
+
for (var i = 0; i < models.length; i++) {
|
|
797
|
+
var m = models[i];
|
|
798
|
+
var id = (m && m.id ? String(m.id) : "").trim().toLowerCase();
|
|
799
|
+
var reported = m ? Number(m.max_input_tokens) : NaN;
|
|
800
|
+
if (id && Number.isFinite(reported) && reported > 0) {
|
|
801
|
+
apiReportedContextWindows[id] = Math.floor(reported);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
var projectContextWindows = {};
|
|
806
|
+
function setProjectContextWindow(serviceId, tokens) {
|
|
807
|
+
var key = (serviceId || "").trim();
|
|
808
|
+
if (!key) return;
|
|
809
|
+
var n = Number(tokens);
|
|
810
|
+
if (Number.isFinite(n) && n > 0) projectContextWindows[key] = Math.floor(n);
|
|
811
|
+
else delete projectContextWindows[key];
|
|
812
|
+
}
|
|
813
|
+
function getProjectContextWindow(serviceId) {
|
|
814
|
+
var key = (serviceId || "").trim();
|
|
815
|
+
return key && projectContextWindows[key] ? projectContextWindows[key] : null;
|
|
816
|
+
}
|
|
762
817
|
var OUTPUT_TOKEN_RESERVE = 22e3;
|
|
763
818
|
var TOOL_AND_RESPONSE_BUFFER = 4e3;
|
|
764
819
|
var MIN_INPUT_TOKEN_BUDGET = 8e3;
|
|
765
820
|
var CLAUDE_PER_REQUEST_INPUT_CAP = 28e3;
|
|
766
821
|
var MAX_HISTORY_MESSAGES = 20;
|
|
767
822
|
var HISTORY_TOKEN_BUDGET = 8e3;
|
|
823
|
+
var CLAUDE_INPUT_CAP_RATIO = 0.16;
|
|
824
|
+
var HISTORY_BUDGET_RATIO = 0.08;
|
|
768
825
|
function estimateTextTokens(text) {
|
|
769
826
|
return Math.ceil((text || "").length / 3);
|
|
770
827
|
}
|
|
771
828
|
function estimateMessageTokens(msg) {
|
|
772
829
|
return estimateTextTokens(msg.content) + estimateTextTokens(msg.role) + 6;
|
|
773
830
|
}
|
|
774
|
-
function getContextWindow(platform, model) {
|
|
831
|
+
function getContextWindow(platform, model, serviceId) {
|
|
832
|
+
var override = serviceId ? getProjectContextWindow(serviceId) : null;
|
|
833
|
+
if (override) return override;
|
|
775
834
|
var normalized = (model || "").trim().toLowerCase();
|
|
776
|
-
if (normalized
|
|
835
|
+
if (normalized) {
|
|
836
|
+
if (apiReportedContextWindows[normalized]) return apiReportedContextWindows[normalized];
|
|
837
|
+
if (CONTEXT_WINDOW_BY_MODEL[normalized]) return CONTEXT_WINDOW_BY_MODEL[normalized];
|
|
838
|
+
var parts = normalized.split("-");
|
|
839
|
+
for (var end = parts.length - 1; end > 0; end--) {
|
|
840
|
+
var family = parts.slice(0, end).join("-");
|
|
841
|
+
if (CONTEXT_WINDOW_BY_MODEL[family]) return CONTEXT_WINDOW_BY_MODEL[family];
|
|
842
|
+
}
|
|
843
|
+
}
|
|
777
844
|
return CONTEXT_WINDOW_DEFAULT[platform];
|
|
778
845
|
}
|
|
779
846
|
function stripFileBlocksFromHistory(content) {
|
|
@@ -781,15 +848,19 @@ function stripFileBlocksFromHistory(content) {
|
|
|
781
848
|
return content.replace(/```([^\n`]+?\.[^\s.`]+)\n[\s\S]*?```/g, "[file previously attached: $1]");
|
|
782
849
|
}
|
|
783
850
|
function buildBoundedChatMessages(options) {
|
|
784
|
-
var contextWindow = getContextWindow(options.platform, options.model);
|
|
851
|
+
var contextWindow = getContextWindow(options.platform, options.model, options.serviceId);
|
|
785
852
|
var contextBasedBudget = Math.max(
|
|
786
853
|
MIN_INPUT_TOKEN_BUDGET,
|
|
787
854
|
contextWindow - OUTPUT_TOKEN_RESERVE - TOOL_AND_RESPONSE_BUFFER
|
|
788
855
|
);
|
|
789
|
-
var
|
|
856
|
+
var scaled = !!(options.serviceId && getProjectContextWindow(options.serviceId));
|
|
857
|
+
var claudeInputCap = scaled ? Math.max(CLAUDE_PER_REQUEST_INPUT_CAP, Math.round(contextBasedBudget * CLAUDE_INPUT_CAP_RATIO)) : CLAUDE_PER_REQUEST_INPUT_CAP;
|
|
858
|
+
var availableInputBudget = options.platform === "claude" ? Math.min(contextBasedBudget, claudeInputCap) : contextBasedBudget;
|
|
790
859
|
var systemCost = estimateTextTokens(options.systemPrompt) + 12;
|
|
791
|
-
var
|
|
792
|
-
var
|
|
860
|
+
var historyAllowance = scaled ? Math.max(HISTORY_TOKEN_BUDGET, Math.round(contextBasedBudget * HISTORY_BUDGET_RATIO)) : HISTORY_TOKEN_BUDGET;
|
|
861
|
+
var budgetForHistory = Math.max(1e3, Math.min(historyAllowance, availableInputBudget - systemCost));
|
|
862
|
+
var maxHistoryMessages = scaled ? Math.max(MAX_HISTORY_MESSAGES, Math.round(MAX_HISTORY_MESSAGES * (budgetForHistory / HISTORY_TOKEN_BUDGET))) : MAX_HISTORY_MESSAGES;
|
|
863
|
+
var windowed = options.history.slice(-maxHistoryMessages);
|
|
793
864
|
var latestIndex = windowed.length - 1;
|
|
794
865
|
var trimmed = windowed.map(function(m, i2) {
|
|
795
866
|
if (i2 === latestIndex) return m;
|
|
@@ -814,6 +885,166 @@ function buildBoundedChatMessages(options) {
|
|
|
814
885
|
};
|
|
815
886
|
}
|
|
816
887
|
|
|
888
|
+
// src/engine/download_encoding.ts
|
|
889
|
+
var BOM = "\uFEFF";
|
|
890
|
+
var BOM_EXTS = /* @__PURE__ */ new Set(["csv", "tsv", "tab", "txt", "text", "log"]);
|
|
891
|
+
var HTML_EXTS = /* @__PURE__ */ new Set(["html", "htm", "xhtml"]);
|
|
892
|
+
var XML_EXTS = /* @__PURE__ */ new Set(["xml", "svg", "rss", "atom", "xsl", "xslt", "plist", "kml"]);
|
|
893
|
+
var RTF_EXTS = /* @__PURE__ */ new Set(["rtf"]);
|
|
894
|
+
var EXT_CONTENT_TYPES = {
|
|
895
|
+
csv: "text/csv; charset=utf-8",
|
|
896
|
+
tsv: "text/tab-separated-values; charset=utf-8",
|
|
897
|
+
tab: "text/tab-separated-values; charset=utf-8",
|
|
898
|
+
txt: "text/plain; charset=utf-8",
|
|
899
|
+
text: "text/plain; charset=utf-8",
|
|
900
|
+
log: "text/plain; charset=utf-8",
|
|
901
|
+
md: "text/markdown; charset=utf-8",
|
|
902
|
+
markdown: "text/markdown; charset=utf-8",
|
|
903
|
+
json: "application/json; charset=utf-8",
|
|
904
|
+
jsonl: "application/x-ndjson; charset=utf-8",
|
|
905
|
+
ndjson: "application/x-ndjson; charset=utf-8",
|
|
906
|
+
geojson: "application/geo+json; charset=utf-8",
|
|
907
|
+
yaml: "text/yaml; charset=utf-8",
|
|
908
|
+
yml: "text/yaml; charset=utf-8",
|
|
909
|
+
toml: "text/plain; charset=utf-8",
|
|
910
|
+
ini: "text/plain; charset=utf-8",
|
|
911
|
+
sql: "text/plain; charset=utf-8",
|
|
912
|
+
html: "text/html; charset=utf-8",
|
|
913
|
+
htm: "text/html; charset=utf-8",
|
|
914
|
+
xhtml: "application/xhtml+xml; charset=utf-8",
|
|
915
|
+
xml: "application/xml; charset=utf-8",
|
|
916
|
+
svg: "image/svg+xml; charset=utf-8",
|
|
917
|
+
css: "text/css; charset=utf-8",
|
|
918
|
+
js: "text/javascript; charset=utf-8",
|
|
919
|
+
ts: "text/plain; charset=utf-8",
|
|
920
|
+
py: "text/x-python; charset=utf-8",
|
|
921
|
+
sh: "text/x-shellscript; charset=utf-8",
|
|
922
|
+
srt: "application/x-subrip; charset=utf-8",
|
|
923
|
+
vtt: "text/vtt; charset=utf-8",
|
|
924
|
+
ics: "text/calendar; charset=utf-8",
|
|
925
|
+
vcf: "text/vcard; charset=utf-8",
|
|
926
|
+
// RTF is 7-bit ASCII by specification, so it takes no charset parameter.
|
|
927
|
+
rtf: "application/rtf",
|
|
928
|
+
// Binary types the model can only ever REFERENCE, never author in a fence, but
|
|
929
|
+
// which keep the type sensible if one ever shows up.
|
|
930
|
+
pdf: "application/pdf",
|
|
931
|
+
png: "image/png",
|
|
932
|
+
jpg: "image/jpeg",
|
|
933
|
+
jpeg: "image/jpeg",
|
|
934
|
+
gif: "image/gif",
|
|
935
|
+
webp: "image/webp"
|
|
936
|
+
};
|
|
937
|
+
function normalizeExt(ext) {
|
|
938
|
+
return String(ext || "").trim().replace(/^\./, "").toLowerCase();
|
|
939
|
+
}
|
|
940
|
+
function extOf(filename) {
|
|
941
|
+
const name = String(filename || "");
|
|
942
|
+
const dot = name.lastIndexOf(".");
|
|
943
|
+
return dot > 0 ? normalizeExt(name.slice(dot + 1)) : "";
|
|
944
|
+
}
|
|
945
|
+
function encodingClassForExt(ext) {
|
|
946
|
+
const e = normalizeExt(ext);
|
|
947
|
+
if (BOM_EXTS.has(e)) return "bom";
|
|
948
|
+
if (HTML_EXTS.has(e)) return "html";
|
|
949
|
+
if (XML_EXTS.has(e)) return "xml";
|
|
950
|
+
if (RTF_EXTS.has(e)) return "rtf";
|
|
951
|
+
return "none";
|
|
952
|
+
}
|
|
953
|
+
function needsBomForExt(ext) {
|
|
954
|
+
return encodingClassForExt(ext) === "bom";
|
|
955
|
+
}
|
|
956
|
+
function contentTypeForExt(ext, fallback = "text/plain; charset=utf-8") {
|
|
957
|
+
return EXT_CONTENT_TYPES[normalizeExt(ext)] || fallback;
|
|
958
|
+
}
|
|
959
|
+
function hasBom(text) {
|
|
960
|
+
return typeof text === "string" && text.charCodeAt(0) === 65279;
|
|
961
|
+
}
|
|
962
|
+
var HTML_HEAD_WINDOW = 4096;
|
|
963
|
+
var META_CHARSET_RE = /<meta[^>]+charset\s*=\s*["']?\s*([a-z0-9_-]+)/i;
|
|
964
|
+
var META_HTTP_EQUIV_RE = /<meta[^>]+http-equiv\s*=\s*["']?content-type["']?[^>]*>/i;
|
|
965
|
+
function ensureHtmlCharset(text) {
|
|
966
|
+
const src = String(text == null ? "" : text);
|
|
967
|
+
const head = src.slice(0, HTML_HEAD_WINDOW);
|
|
968
|
+
const declared = META_CHARSET_RE.exec(head);
|
|
969
|
+
if (declared) {
|
|
970
|
+
if (declared[1].toLowerCase().replace(/[^a-z0-9]/g, "") === "utf8") return src;
|
|
971
|
+
const start = declared.index + declared[0].length - declared[1].length;
|
|
972
|
+
return src.slice(0, start) + "utf-8" + src.slice(start + declared[1].length);
|
|
973
|
+
}
|
|
974
|
+
const httpEquiv = META_HTTP_EQUIV_RE.exec(head);
|
|
975
|
+
if (httpEquiv) {
|
|
976
|
+
return src.slice(0, httpEquiv.index) + '<meta charset="utf-8">' + src.slice(httpEquiv.index + httpEquiv[0].length);
|
|
977
|
+
}
|
|
978
|
+
const tag = '<meta charset="utf-8">';
|
|
979
|
+
const headOpen = /<head[^>]*>/i.exec(head);
|
|
980
|
+
if (headOpen) {
|
|
981
|
+
const at = headOpen.index + headOpen[0].length;
|
|
982
|
+
return src.slice(0, at) + "\n" + tag + src.slice(at);
|
|
983
|
+
}
|
|
984
|
+
const htmlOpen = /<html[^>]*>/i.exec(head);
|
|
985
|
+
if (htmlOpen) {
|
|
986
|
+
const at = htmlOpen.index + htmlOpen[0].length;
|
|
987
|
+
return src.slice(0, at) + "\n<head>" + tag + "</head>" + src.slice(at);
|
|
988
|
+
}
|
|
989
|
+
const doctype = /<!doctype[^>]*>/i.exec(head);
|
|
990
|
+
if (doctype) {
|
|
991
|
+
const at = doctype.index + doctype[0].length;
|
|
992
|
+
return src.slice(0, at) + "\n" + tag + src.slice(at);
|
|
993
|
+
}
|
|
994
|
+
return tag + "\n" + src;
|
|
995
|
+
}
|
|
996
|
+
var XML_DECL_RE = /^\s*<\?xml\s[^?]*\?>/i;
|
|
997
|
+
function ensureXmlEncoding(text) {
|
|
998
|
+
const src = String(text == null ? "" : text);
|
|
999
|
+
const decl = XML_DECL_RE.exec(src);
|
|
1000
|
+
if (!decl) return src;
|
|
1001
|
+
const found = /encoding\s*=\s*["']([^"']*)["']/i.exec(decl[0]);
|
|
1002
|
+
if (!found) return src;
|
|
1003
|
+
if (found[1].toLowerCase().replace(/[^a-z0-9]/g, "") === "utf8") return src;
|
|
1004
|
+
const fixedDecl = decl[0].slice(0, found.index) + found[0].replace(found[1], "UTF-8") + decl[0].slice(found.index + found[0].length);
|
|
1005
|
+
return fixedDecl + src.slice(decl[0].length);
|
|
1006
|
+
}
|
|
1007
|
+
var RTF_SIGNATURE_RE = /^[\s]*\{\\rtf/i;
|
|
1008
|
+
function looksLikeRtf(text) {
|
|
1009
|
+
return RTF_SIGNATURE_RE.test(String(text == null ? "" : text));
|
|
1010
|
+
}
|
|
1011
|
+
function escapeRtfNonAscii(text) {
|
|
1012
|
+
const src = String(text == null ? "" : text);
|
|
1013
|
+
let out = "";
|
|
1014
|
+
let plainFrom = 0;
|
|
1015
|
+
for (let i = 0; i < src.length; i++) {
|
|
1016
|
+
const code = src.charCodeAt(i);
|
|
1017
|
+
if (code < 128) continue;
|
|
1018
|
+
out += src.slice(plainFrom, i);
|
|
1019
|
+
out += `\\u${code > 32767 ? code - 65536 : code}?`;
|
|
1020
|
+
plainFrom = i + 1;
|
|
1021
|
+
}
|
|
1022
|
+
return plainFrom === 0 ? src : out + src.slice(plainFrom);
|
|
1023
|
+
}
|
|
1024
|
+
function applyEncodingDeclaration(text, ext) {
|
|
1025
|
+
const src = String(text == null ? "" : text);
|
|
1026
|
+
switch (encodingClassForExt(ext)) {
|
|
1027
|
+
case "bom":
|
|
1028
|
+
return hasBom(src) ? src : BOM + src;
|
|
1029
|
+
case "html":
|
|
1030
|
+
return ensureHtmlCharset(src);
|
|
1031
|
+
case "xml":
|
|
1032
|
+
return ensureXmlEncoding(src);
|
|
1033
|
+
case "rtf":
|
|
1034
|
+
return looksLikeRtf(src) ? escapeRtfNonAscii(src) : hasBom(src) ? src : BOM + src;
|
|
1035
|
+
default:
|
|
1036
|
+
return src;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
function prepareDownloadText(filename, body) {
|
|
1040
|
+
const ext = extOf(filename);
|
|
1041
|
+
return {
|
|
1042
|
+
ext,
|
|
1043
|
+
text: applyEncodingDeclaration(body, ext),
|
|
1044
|
+
contentType: contentTypeForExt(ext)
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1047
|
+
|
|
817
1048
|
// src/engine/time.ts
|
|
818
1049
|
function wallClockNow() {
|
|
819
1050
|
return Date.now();
|
|
@@ -834,6 +1065,40 @@ function formatChatTimestamp(ms) {
|
|
|
834
1065
|
}
|
|
835
1066
|
}
|
|
836
1067
|
|
|
1068
|
+
// src/engine/ai_agent.ts
|
|
1069
|
+
function normalizePlatform(raw) {
|
|
1070
|
+
var p = (raw || "").trim().toLowerCase();
|
|
1071
|
+
return p === "claude" || p === "openai" ? p : null;
|
|
1072
|
+
}
|
|
1073
|
+
function parseAiAgentValue(value) {
|
|
1074
|
+
var raw = (value || "").trim();
|
|
1075
|
+
if (!raw || raw.toLowerCase() === "none") {
|
|
1076
|
+
return { platform: null, model: "", contextWindow: null, hasPlatform: false };
|
|
1077
|
+
}
|
|
1078
|
+
var firstHash = raw.indexOf("#");
|
|
1079
|
+
if (firstHash === -1) {
|
|
1080
|
+
var only = normalizePlatform(raw);
|
|
1081
|
+
return { platform: only, model: "", contextWindow: null, hasPlatform: !!only };
|
|
1082
|
+
}
|
|
1083
|
+
var platform = normalizePlatform(raw.slice(0, firstHash));
|
|
1084
|
+
var rest = raw.slice(firstHash + 1);
|
|
1085
|
+
var secondHash = rest.indexOf("#");
|
|
1086
|
+
var model = (secondHash === -1 ? rest : rest.slice(0, secondHash)).trim();
|
|
1087
|
+
var windowRaw = secondHash === -1 ? "" : rest.slice(secondHash + 1).trim();
|
|
1088
|
+
var parsedWindow = windowRaw ? Number(windowRaw) : NaN;
|
|
1089
|
+
var contextWindow = Number.isFinite(parsedWindow) && parsedWindow > 0 ? Math.floor(parsedWindow) : null;
|
|
1090
|
+
return { platform, model, contextWindow, hasPlatform: !!platform };
|
|
1091
|
+
}
|
|
1092
|
+
function buildAiAgentValue(platform, model, contextWindow) {
|
|
1093
|
+
var p = (platform || "").trim().toLowerCase();
|
|
1094
|
+
if (!p || p === "none") return "none";
|
|
1095
|
+
var m = (model || "").trim();
|
|
1096
|
+
if (!m) return p;
|
|
1097
|
+
var n = Number(contextWindow);
|
|
1098
|
+
if (!Number.isFinite(n) || n <= 0) return p + "#" + m;
|
|
1099
|
+
return p + "#" + m + "#" + Math.floor(n);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
837
1102
|
// src/engine/requests.ts
|
|
838
1103
|
var ANTHROPIC_MESSAGES_API_URL = "https://api.anthropic.com/v1/messages";
|
|
839
1104
|
var ANTHROPIC_MODELS_API_URL = "https://api.anthropic.com/v1/models";
|
|
@@ -952,7 +1217,7 @@ function applyHistoryCacheBreakpoint(messages) {
|
|
|
952
1217
|
return { ...m, content: blocks };
|
|
953
1218
|
});
|
|
954
1219
|
}
|
|
955
|
-
var POLL_INTERVAL =
|
|
1220
|
+
var POLL_INTERVAL = 3e3;
|
|
956
1221
|
async function callClaudeWithMcp({
|
|
957
1222
|
prompt,
|
|
958
1223
|
messages,
|
|
@@ -1342,7 +1607,8 @@ async function getChatHistory(params, fetchOptions) {
|
|
|
1342
1607
|
method: "POST"
|
|
1343
1608
|
},
|
|
1344
1609
|
{ service: params.service, owner: params.owner },
|
|
1345
|
-
params.queue ? { queue: params.queue } : {}
|
|
1610
|
+
params.queue ? { queue: params.queue } : {},
|
|
1611
|
+
params.status ? { status: params.status } : {}
|
|
1346
1612
|
);
|
|
1347
1613
|
return chatEngineConfig().clientSecretRequestHistory(
|
|
1348
1614
|
p,
|
|
@@ -1379,6 +1645,25 @@ function extractLastUserTextFromRequest(requestBody) {
|
|
|
1379
1645
|
}
|
|
1380
1646
|
return "";
|
|
1381
1647
|
}
|
|
1648
|
+
function isIndexingRequestText(userText) {
|
|
1649
|
+
if (typeof userText !== "string") return false;
|
|
1650
|
+
return userText.indexOf("A new file has just been uploaded") === 0 || userText.indexOf("CONTINUE indexing") === 0;
|
|
1651
|
+
}
|
|
1652
|
+
function parseIndexingRequestText(userText) {
|
|
1653
|
+
if (typeof userText !== "string" || !userText) return null;
|
|
1654
|
+
var nameMatch = userText.match(/^- name: (.+)$/m);
|
|
1655
|
+
if (!nameMatch) return null;
|
|
1656
|
+
var mimeMatch = userText.match(/^- mime type: (.+)$/m);
|
|
1657
|
+
var sizeMatch = userText.match(/^- size \(bytes\): (\d+)$/m);
|
|
1658
|
+
var pathMatch = userText.match(/^- storage path: (.+)$/m);
|
|
1659
|
+
return {
|
|
1660
|
+
name: nameMatch[1].trim(),
|
|
1661
|
+
path: pathMatch ? pathMatch[1].trim() : void 0,
|
|
1662
|
+
mime: mimeMatch ? mimeMatch[1].trim() : void 0,
|
|
1663
|
+
size: sizeMatch ? Number(sizeMatch[1]) : void 0,
|
|
1664
|
+
continued: userText.indexOf("CONTINUE indexing") === 0
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1382
1667
|
function mapHistoryListToMessages(list, platform, opts) {
|
|
1383
1668
|
var mapped = [], runningItemIds = [];
|
|
1384
1669
|
var extractAssistantText = platform === "openai" ? extractOpenAIText : extractClaudeText;
|
|
@@ -1403,27 +1688,17 @@ function mapHistoryListToMessages(list, platform, opts) {
|
|
|
1403
1688
|
var displayContent;
|
|
1404
1689
|
var indexFile = void 0;
|
|
1405
1690
|
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;
|
|
1691
|
+
var ref = parseIndexingRequestText(userText);
|
|
1692
|
+
if (ref) {
|
|
1412
1693
|
displayContent = opts.formatIndexingLabel(
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1694
|
+
ref.name,
|
|
1695
|
+
ref.mime || "",
|
|
1696
|
+
typeof ref.size === "number" ? ref.size : null,
|
|
1697
|
+
ref.path,
|
|
1417
1698
|
false,
|
|
1418
|
-
|
|
1699
|
+
ref.continued
|
|
1419
1700
|
);
|
|
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
|
-
};
|
|
1701
|
+
indexFile = ref;
|
|
1427
1702
|
} else {
|
|
1428
1703
|
displayContent = userText;
|
|
1429
1704
|
}
|
|
@@ -1552,6 +1827,8 @@ function createHistoryFiller(base) {
|
|
|
1552
1827
|
}
|
|
1553
1828
|
|
|
1554
1829
|
// src/engine/session.ts
|
|
1830
|
+
var WORKER_PASS_ADOPT_LIMIT = 20;
|
|
1831
|
+
var WORKER_PASS_ADOPT_ATTEMPTS = [0, 2e3, 6e3];
|
|
1555
1832
|
var _g = typeof globalThis !== "undefined" ? globalThis : {};
|
|
1556
1833
|
function nowMs() {
|
|
1557
1834
|
return _g.performance && typeof _g.performance.now === "function" ? _g.performance.now() : Date.now();
|
|
@@ -1571,6 +1848,35 @@ function isPollStopped(res) {
|
|
|
1571
1848
|
var ChatSession = class {
|
|
1572
1849
|
constructor(host) {
|
|
1573
1850
|
this.typewriterQueue = Promise.resolve();
|
|
1851
|
+
/**
|
|
1852
|
+
* Pick up indexing passes the WORKER minted, which no client ever dispatched.
|
|
1853
|
+
*
|
|
1854
|
+
* For a PDF (and for text/grid when windowed indexing is on) the worker writes
|
|
1855
|
+
* pass N+1's row itself, inside pass N's invocation, right after saving pass
|
|
1856
|
+
* N's result. That row reaches this client through nothing at all: it is not in
|
|
1857
|
+
* bgTaskQueue (the client never asked for it) and it is not in state.messages
|
|
1858
|
+
* (only a first-page history load maps it in, which happens on mount, project
|
|
1859
|
+
* switch or tab return). So between two worker passes every pass the client
|
|
1860
|
+
* knows about is settled, and the collapsed row renders "Indexed N passes"
|
|
1861
|
+
* with no spinner and no Stop, for a file that is still being read. A user who
|
|
1862
|
+
* believes that then asks questions against a half-indexed file — which is what
|
|
1863
|
+
* this exists to prevent.
|
|
1864
|
+
*
|
|
1865
|
+
* So when a background indexing pass settles, ask the bg queue what is still
|
|
1866
|
+
* unresolved on it and adopt anything unknown as an ordinary BgTaskEntry.
|
|
1867
|
+
* drainBgTaskQueue then treats it exactly like a pass this client dispatched:
|
|
1868
|
+
* same bubble, same `_indexFile` (so it joins the file's collapsed row), same
|
|
1869
|
+
* poll — and that poll settling runs this again, so the chain is followed to
|
|
1870
|
+
* its end. `status`-scoped so the reply carries the live items only, never a
|
|
1871
|
+
* page of finished ones with their bodies.
|
|
1872
|
+
*
|
|
1873
|
+
* Termination: the only trigger is a pass SETTLING, which happens once per
|
|
1874
|
+
* pass. An adopted item that is still running is not re-adopted (its id is
|
|
1875
|
+
* already polled), and when the queue holds nothing unknown the chain stops on
|
|
1876
|
+
* its own. Nothing here is periodic — a timer that re-reads history is the
|
|
1877
|
+
* shape that previously looped fetchHistoryPage after an already-DONE index.
|
|
1878
|
+
*/
|
|
1879
|
+
this._adoptingWorkerPasses = false;
|
|
1574
1880
|
this.host = host;
|
|
1575
1881
|
this.state = {
|
|
1576
1882
|
messages: [],
|
|
@@ -1860,7 +2166,7 @@ var ChatSession = class {
|
|
|
1860
2166
|
var chatQueue = useBgQueue ? userId + BG_INDEXING_QUEUE_SUFFIX : userId;
|
|
1861
2167
|
if (offChat) {
|
|
1862
2168
|
var offHistory = (this.aiChatHistoryCache[key] ? this.aiChatHistoryCache[key].messages : []).filter(function(m) {
|
|
1863
|
-
return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask;
|
|
2169
|
+
return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
|
|
1864
2170
|
});
|
|
1865
2171
|
var offBounded = buildBoundedChatMessages({
|
|
1866
2172
|
platform: aiPlatform,
|
|
@@ -1895,7 +2201,7 @@ var ChatSession = class {
|
|
|
1895
2201
|
}
|
|
1896
2202
|
if (isQueuedSend) {
|
|
1897
2203
|
var resolvedHistory = this.state.messages.filter(function(m) {
|
|
1898
|
-
return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask;
|
|
2204
|
+
return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
|
|
1899
2205
|
});
|
|
1900
2206
|
var boundedQ = buildBoundedChatMessages({
|
|
1901
2207
|
platform: aiPlatform,
|
|
@@ -1946,7 +2252,7 @@ var ChatSession = class {
|
|
|
1946
2252
|
this.state.sending = true;
|
|
1947
2253
|
this.host.scrollToBottom(true);
|
|
1948
2254
|
var historyForLlm = this.state.messages.filter(function(m) {
|
|
1949
|
-
return !m.isCancelled && !m.isBackgroundTask;
|
|
2255
|
+
return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
|
|
1950
2256
|
});
|
|
1951
2257
|
if (llmComposed !== composed) {
|
|
1952
2258
|
for (var li = historyForLlm.length - 1; li >= 0; li--) {
|
|
@@ -2516,8 +2822,21 @@ var ChatSession = class {
|
|
|
2516
2822
|
}
|
|
2517
2823
|
// --- background-task resolution + drain -------------------------------
|
|
2518
2824
|
handleHistoryItemResolution(itemId, response, platform) {
|
|
2825
|
+
var indexRef = this._indexRefOfItem(itemId);
|
|
2519
2826
|
this.applyHistoryItemResolution(itemId, response, platform);
|
|
2520
2827
|
this.promoteNextBgQueuedToRunning();
|
|
2828
|
+
if (indexRef) this._followWorkerIndexingChain(indexRef.name, indexRef.mime);
|
|
2829
|
+
}
|
|
2830
|
+
/** The file an already-rendered background pass is about, off its request
|
|
2831
|
+
* bubble. Null for an ordinary turn, which is most of them. */
|
|
2832
|
+
_indexRefOfItem(itemId) {
|
|
2833
|
+
if (!itemId) return null;
|
|
2834
|
+
for (var i = 0; i < this.state.messages.length; i++) {
|
|
2835
|
+
var m = this.state.messages[i];
|
|
2836
|
+
if (m._serverItemId !== itemId || m.role !== "user" || !m.isBackgroundTask) continue;
|
|
2837
|
+
return m._indexFile || null;
|
|
2838
|
+
}
|
|
2839
|
+
return null;
|
|
2521
2840
|
}
|
|
2522
2841
|
applyHistoryItemResolution(itemId, response, platform) {
|
|
2523
2842
|
this.historyItemPolls.delete(itemId);
|
|
@@ -2651,6 +2970,116 @@ var ChatSession = class {
|
|
|
2651
2970
|
self.cancelQueuedMessage(t.msg, idx === -1 ? t.idx : idx);
|
|
2652
2971
|
});
|
|
2653
2972
|
}
|
|
2973
|
+
/**
|
|
2974
|
+
* True when the WORKER, not this client, drives the rest of this file's chain.
|
|
2975
|
+
* The mirror image of the early returns in maybeResumeIndexing: whatever that
|
|
2976
|
+
* refuses to continue is exactly what nothing client-side is tracking.
|
|
2977
|
+
*/
|
|
2978
|
+
_isWorkerDrivenIndexing(filename, mime) {
|
|
2979
|
+
if (!isPagedReadFile(filename, mime)) return false;
|
|
2980
|
+
if (isImageVisionFile(filename, mime)) return true;
|
|
2981
|
+
return windowedIndexingEnabled() && isWindowedReadFile(filename, mime);
|
|
2982
|
+
}
|
|
2983
|
+
_adoptWorkerIndexingPasses(attempt) {
|
|
2984
|
+
var self = this;
|
|
2985
|
+
if (this._adoptingWorkerPasses) return;
|
|
2986
|
+
var id = this.host.getIdentity();
|
|
2987
|
+
var platform = id.platform;
|
|
2988
|
+
if (!id.serviceId || platform !== "claude" && platform !== "openai") return;
|
|
2989
|
+
if (this.isPollingPaused() || !this.host.isViewMounted()) return;
|
|
2990
|
+
var svcId = id.serviceId, owner = id.owner;
|
|
2991
|
+
var queue = (id.userId || id.serviceId) + BG_INDEXING_QUEUE_SUFFIX;
|
|
2992
|
+
var ask = function(status) {
|
|
2993
|
+
return Promise.resolve(getChatHistory(
|
|
2994
|
+
{ service: svcId, owner, platform, queue, status },
|
|
2995
|
+
{ limit: WORKER_PASS_ADOPT_LIMIT }
|
|
2996
|
+
)).catch(function() {
|
|
2997
|
+
return null;
|
|
2998
|
+
});
|
|
2999
|
+
};
|
|
3000
|
+
this._adoptingWorkerPasses = true;
|
|
3001
|
+
Promise.all([ask("running"), ask("pending")]).then(function(results) {
|
|
3002
|
+
self._adoptingWorkerPasses = false;
|
|
3003
|
+
var now = self.host.getIdentity();
|
|
3004
|
+
if (now.serviceId !== svcId || now.platform !== platform) return;
|
|
3005
|
+
if (!self.host.isViewMounted()) return;
|
|
3006
|
+
var adoptedIds = [];
|
|
3007
|
+
for (var ri = 0; ri < results.length; ri++) {
|
|
3008
|
+
var list = results[ri] && Array.isArray(results[ri].list) ? results[ri].list : [];
|
|
3009
|
+
for (var i = 0; i < list.length; i++) {
|
|
3010
|
+
if (self._adoptWorkerIndexingItem(list[i], svcId, platform)) adoptedIds.push(list[i].id);
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
if (adoptedIds.length) {
|
|
3014
|
+
self.drainBgTaskQueue();
|
|
3015
|
+
if (self._isTrackingAny(adoptedIds)) return;
|
|
3016
|
+
}
|
|
3017
|
+
if (attempt + 1 >= WORKER_PASS_ADOPT_ATTEMPTS.length) return;
|
|
3018
|
+
setTimeout(function() {
|
|
3019
|
+
var later = self.host.getIdentity();
|
|
3020
|
+
if (later.serviceId !== svcId || later.platform !== platform) return;
|
|
3021
|
+
if (self.isPollingPaused() || !self.host.isViewMounted()) return;
|
|
3022
|
+
self._adoptWorkerIndexingPasses(attempt + 1);
|
|
3023
|
+
}, WORKER_PASS_ADOPT_ATTEMPTS[attempt + 1]);
|
|
3024
|
+
}, function() {
|
|
3025
|
+
self._adoptingWorkerPasses = false;
|
|
3026
|
+
});
|
|
3027
|
+
}
|
|
3028
|
+
/** Any of these ids still queued or still polled, i.e. surviving work. */
|
|
3029
|
+
_isTrackingAny(ids) {
|
|
3030
|
+
for (var i = 0; i < ids.length; i++) {
|
|
3031
|
+
if (this.historyItemPolls.has(ids[i])) return true;
|
|
3032
|
+
for (var q = 0; q < this.bgTaskQueue.length; q++) {
|
|
3033
|
+
if (this.bgTaskQueue[q].id === ids[i]) return true;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
return false;
|
|
3037
|
+
}
|
|
3038
|
+
/** One live bg-queue item -> a BgTaskEntry, if it is an indexing pass this
|
|
3039
|
+
* client is not already tracking. Returns whether it was adopted. */
|
|
3040
|
+
_adoptWorkerIndexingItem(item, svcId, platform) {
|
|
3041
|
+
if (!item || typeof item.id !== "string" || !item.id) return false;
|
|
3042
|
+
if (item.status !== "pending" && item.status !== "running") return false;
|
|
3043
|
+
if (typeof item.poll !== "function") return false;
|
|
3044
|
+
if (this.historyItemPolls.has(item.id)) return false;
|
|
3045
|
+
for (var q = 0; q < this.bgTaskQueue.length; q++) {
|
|
3046
|
+
if (this.bgTaskQueue[q].id === item.id) return false;
|
|
3047
|
+
}
|
|
3048
|
+
for (var m = 0; m < this.state.messages.length; m++) {
|
|
3049
|
+
var msg = this.state.messages[m];
|
|
3050
|
+
if (msg._serverItemId !== item.id) continue;
|
|
3051
|
+
if (!(msg.isPending || msg.isPendingInProcess || msg.isPendingQueued)) return false;
|
|
3052
|
+
}
|
|
3053
|
+
var body = item.request_body;
|
|
3054
|
+
if (!body || typeof body !== "object") return false;
|
|
3055
|
+
if (platform === "claude" ? !Array.isArray(body.messages) : !Array.isArray(body.input)) return false;
|
|
3056
|
+
var userText = extractLastUserTextFromRequest(body);
|
|
3057
|
+
if (!isIndexingRequestText(userText)) return false;
|
|
3058
|
+
var ref = parseIndexingRequestText(userText);
|
|
3059
|
+
if (!ref || !ref.name) return false;
|
|
3060
|
+
if (!this._isWorkerDrivenIndexing(ref.name, ref.mime)) return false;
|
|
3061
|
+
this.bgTaskQueue.push({
|
|
3062
|
+
serviceId: svcId,
|
|
3063
|
+
platform,
|
|
3064
|
+
id: item.id,
|
|
3065
|
+
filename: ref.name,
|
|
3066
|
+
storagePath: ref.path,
|
|
3067
|
+
mime: ref.mime,
|
|
3068
|
+
size: ref.size,
|
|
3069
|
+
status: item.status === "running" ? "running" : "pending",
|
|
3070
|
+
poll: item.poll,
|
|
3071
|
+
// Drives the "(continuing)" label and marks this as a continuation for
|
|
3072
|
+
// _applyIndexCancellations, which must not read a CONTINUE pass as the
|
|
3073
|
+
// fresh first pass that lifts a stop.
|
|
3074
|
+
resumePass: ref.continued ? 1 : 0
|
|
3075
|
+
});
|
|
3076
|
+
return true;
|
|
3077
|
+
}
|
|
3078
|
+
/** Follow the chain on from a background indexing pass that just settled. */
|
|
3079
|
+
_followWorkerIndexingChain(filename, mime) {
|
|
3080
|
+
if (!this._isWorkerDrivenIndexing(filename, mime)) return;
|
|
3081
|
+
this._adoptWorkerIndexingPasses(0);
|
|
3082
|
+
}
|
|
2654
3083
|
/** Best-effort server-side cancel of a bg-queue item that has no bubble (so
|
|
2655
3084
|
* cancelQueuedMessage, which drives one, has nothing to act on). */
|
|
2656
3085
|
_cancelServerItem(serverId) {
|
|
@@ -2861,8 +3290,7 @@ var ChatSession = class {
|
|
|
2861
3290
|
var chatList = history && Array.isArray(history.list) ? history.list : [];
|
|
2862
3291
|
chatList.forEach(function(item) {
|
|
2863
3292
|
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;
|
|
3293
|
+
if (isIndexingRequestText(extractLastUserTextFromRequest(item.request_body))) item._isBgTask = true;
|
|
2866
3294
|
else item._isOnBgQueue = true;
|
|
2867
3295
|
}
|
|
2868
3296
|
});
|
|
@@ -3429,6 +3857,6 @@ function buildChatDisplayList(messages, opts) {
|
|
|
3429
3857
|
return out;
|
|
3430
3858
|
}
|
|
3431
3859
|
|
|
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 };
|
|
3860
|
+
export { BG_INDEXING_QUEUE_SUFFIX, BOM, BOM_EXTS, 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, EXT_CONTENT_TYPES, HISTORY_BUDGET_RATIO, HISTORY_FILL_SLACK_PX, HISTORY_TOKEN_BUDGET, HTML_EXTS, HTML_HEAD_WINDOW, 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, RTF_EXTS, TOOL_AND_RESPONSE_BUFFER, XML_EXTS, applyEncodingDeclaration, buildAiAgentValue, buildBoundedChatMessages, buildChatDisplayList, buildChatSystemPrompt, buildDisplayExpiredAttachmentHref, buildIndexingContinueMessage, buildIndexingRenderContinueTemplate, buildIndexingRenderMessage, buildIndexingSystemPrompt, buildIndexingUserMessage, buildIndexingWindowMessage, callClaudeWithMcp, callClaudeWithPublicMcp, callOpenAIWithPublicMcp, chatEngineConfig, classifyInlineLink, clearAttachmentParsers, composeUserMessage, configureChatEngine, contentTypeForExt, createHistoryFiller, createInlineLinkRegex, encodePathSegments, encodingClassForExt, ensureHtmlCharset, ensureXmlEncoding, escapeRtfNonAscii, estimateMessageTokens, estimateTextTokens, extOf, extractClaudeText, extractLastUserTextFromRequest, extractOpenAIText, extractRemotePathFromAttachmentHref, fillHistoryViewport, filterListByClearHorizon, findAttachmentParser, formatChatTimestamp, getAttachmentParsers, getChatHistory, getContextWindow, getErrorMessage, getExpiredAttachmentVisiblePath, getProjectContextWindow, groupAttachmentFailures, hasBom, isAuthExpiredError, isBgIndexingQueue, isErrorResponseBody, isHttpUrlLike, isIndexingRequestText, isNonRetryableRequestError, isOfficeFile, isServerExtractable, isServiceDbAttachmentHref, listClaudeModels, listOpenAIModels, looksLikeRtf, makeExtractPlaceholder, mapHistoryListToMessages, needsBomForExt, normalizeAttachmentPathCandidate, normalizeExt, normalizeTextContent, normalizeTrailingInlineToken, notifyAgentSaveAttachment, parseAiAgentValue, parseAttachmentContent, parseIndexingLabel, parseIndexingRequestText, prepareDownloadText, readExpiredAttachmentHref, registerAttachmentParser, registerModelContextWindows, repairUrlEntities, repairUrlWhitespace, safeDecodeURIComponent, sanitizeAttachmentLinksForHistory, setProjectContextWindow, stripFileBlocksFromHistory, transformContentWithImages, transformContentWithOpenAIImages, truncateLabelForDisplay, wallClockNow };
|
|
3433
3861
|
//# sourceMappingURL=engine.mjs.map
|
|
3434
3862
|
//# sourceMappingURL=engine.mjs.map
|