bunnyquery 1.8.1 → 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 CHANGED
@@ -433,6 +433,19 @@ Index the REMAINING windows - one record per row/item, looking at any page image
433
433
  }
434
434
 
435
435
  // src/engine/errors.ts
436
+ var STATUS_MESSAGE = {
437
+ "408": "The AI provider timed out before it started.",
438
+ "409": "The AI provider rejected the request as conflicting.",
439
+ "413": "The request was too large for the AI provider.",
440
+ "429": "The AI provider is rate limiting requests right now.",
441
+ "500": "The AI provider hit an internal error.",
442
+ "502": "The AI provider is temporarily unreachable.",
443
+ "503": "The AI provider is temporarily unavailable.",
444
+ "504": "The AI provider timed out."
445
+ };
446
+ function isTransientStatus(status) {
447
+ return status === 408 || status === 425 || status === 429 || status >= 500;
448
+ }
436
449
  function getErrorMessage(input) {
437
450
  if (!input) return "Something went wrong.";
438
451
  if (typeof input === "string") return input;
@@ -440,6 +453,11 @@ Index the REMAINING windows - one record per row/item, looking at any page image
440
453
  if (input.body && input.body.error && input.body.error.message) return input.body.error.message;
441
454
  if (input.body && typeof input.body.message === "string") return input.body.message;
442
455
  if (input.message) return input.message;
456
+ var status = typeof input.status_code === "number" ? input.status_code : typeof input.status === "number" ? input.status : 0;
457
+ if (status) {
458
+ var text = STATUS_MESSAGE[String(status)] || (status >= 500 ? "The AI provider returned a server error." : "The AI provider rejected the request.");
459
+ return text + " (error " + status + ")" + (isTransientStatus(status) ? " This is usually temporary, please try again." : "");
460
+ }
443
461
  return "Something went wrong.";
444
462
  }
445
463
  function isErrorResponseBody(response) {
@@ -852,6 +870,163 @@ Index the REMAINING windows - one record per row/item, looking at any page image
852
870
  };
853
871
  }
854
872
 
873
+ // src/engine/download_encoding.ts
874
+ var BOM = "\uFEFF";
875
+ var BOM_EXTS = /* @__PURE__ */ new Set(["csv", "tsv", "tab", "txt", "text", "log"]);
876
+ var HTML_EXTS = /* @__PURE__ */ new Set(["html", "htm", "xhtml"]);
877
+ var XML_EXTS = /* @__PURE__ */ new Set(["xml", "svg", "rss", "atom", "xsl", "xslt", "plist", "kml"]);
878
+ var RTF_EXTS = /* @__PURE__ */ new Set(["rtf"]);
879
+ var EXT_CONTENT_TYPES = {
880
+ csv: "text/csv; charset=utf-8",
881
+ tsv: "text/tab-separated-values; charset=utf-8",
882
+ tab: "text/tab-separated-values; charset=utf-8",
883
+ txt: "text/plain; charset=utf-8",
884
+ text: "text/plain; charset=utf-8",
885
+ log: "text/plain; charset=utf-8",
886
+ md: "text/markdown; charset=utf-8",
887
+ markdown: "text/markdown; charset=utf-8",
888
+ json: "application/json; charset=utf-8",
889
+ jsonl: "application/x-ndjson; charset=utf-8",
890
+ ndjson: "application/x-ndjson; charset=utf-8",
891
+ geojson: "application/geo+json; charset=utf-8",
892
+ yaml: "text/yaml; charset=utf-8",
893
+ yml: "text/yaml; charset=utf-8",
894
+ toml: "text/plain; charset=utf-8",
895
+ ini: "text/plain; charset=utf-8",
896
+ sql: "text/plain; charset=utf-8",
897
+ html: "text/html; charset=utf-8",
898
+ htm: "text/html; charset=utf-8",
899
+ xhtml: "application/xhtml+xml; charset=utf-8",
900
+ xml: "application/xml; charset=utf-8",
901
+ svg: "image/svg+xml; charset=utf-8",
902
+ css: "text/css; charset=utf-8",
903
+ js: "text/javascript; charset=utf-8",
904
+ ts: "text/plain; charset=utf-8",
905
+ py: "text/x-python; charset=utf-8",
906
+ sh: "text/x-shellscript; charset=utf-8",
907
+ srt: "application/x-subrip; charset=utf-8",
908
+ vtt: "text/vtt; charset=utf-8",
909
+ ics: "text/calendar; charset=utf-8",
910
+ vcf: "text/vcard; charset=utf-8",
911
+ // RTF is 7-bit ASCII by specification, so it takes no charset parameter.
912
+ rtf: "application/rtf",
913
+ // Binary types the model can only ever REFERENCE, never author in a fence, but
914
+ // which keep the type sensible if one ever shows up.
915
+ pdf: "application/pdf",
916
+ png: "image/png",
917
+ jpg: "image/jpeg",
918
+ jpeg: "image/jpeg",
919
+ gif: "image/gif",
920
+ webp: "image/webp"
921
+ };
922
+ function normalizeExt(ext) {
923
+ return String(ext || "").trim().replace(/^\./, "").toLowerCase();
924
+ }
925
+ function extOf(filename) {
926
+ const name = String(filename || "");
927
+ const dot = name.lastIndexOf(".");
928
+ return dot > 0 ? normalizeExt(name.slice(dot + 1)) : "";
929
+ }
930
+ function encodingClassForExt(ext) {
931
+ const e = normalizeExt(ext);
932
+ if (BOM_EXTS.has(e)) return "bom";
933
+ if (HTML_EXTS.has(e)) return "html";
934
+ if (XML_EXTS.has(e)) return "xml";
935
+ if (RTF_EXTS.has(e)) return "rtf";
936
+ return "none";
937
+ }
938
+ function contentTypeForExt(ext, fallback = "text/plain; charset=utf-8") {
939
+ return EXT_CONTENT_TYPES[normalizeExt(ext)] || fallback;
940
+ }
941
+ function hasBom(text) {
942
+ return typeof text === "string" && text.charCodeAt(0) === 65279;
943
+ }
944
+ var HTML_HEAD_WINDOW = 4096;
945
+ var META_CHARSET_RE = /<meta[^>]+charset\s*=\s*["']?\s*([a-z0-9_-]+)/i;
946
+ var META_HTTP_EQUIV_RE = /<meta[^>]+http-equiv\s*=\s*["']?content-type["']?[^>]*>/i;
947
+ function ensureHtmlCharset(text) {
948
+ const src = String(text == null ? "" : text);
949
+ const head = src.slice(0, HTML_HEAD_WINDOW);
950
+ const declared = META_CHARSET_RE.exec(head);
951
+ if (declared) {
952
+ if (declared[1].toLowerCase().replace(/[^a-z0-9]/g, "") === "utf8") return src;
953
+ const start = declared.index + declared[0].length - declared[1].length;
954
+ return src.slice(0, start) + "utf-8" + src.slice(start + declared[1].length);
955
+ }
956
+ const httpEquiv = META_HTTP_EQUIV_RE.exec(head);
957
+ if (httpEquiv) {
958
+ return src.slice(0, httpEquiv.index) + '<meta charset="utf-8">' + src.slice(httpEquiv.index + httpEquiv[0].length);
959
+ }
960
+ const tag = '<meta charset="utf-8">';
961
+ const headOpen = /<head[^>]*>/i.exec(head);
962
+ if (headOpen) {
963
+ const at = headOpen.index + headOpen[0].length;
964
+ return src.slice(0, at) + "\n" + tag + src.slice(at);
965
+ }
966
+ const htmlOpen = /<html[^>]*>/i.exec(head);
967
+ if (htmlOpen) {
968
+ const at = htmlOpen.index + htmlOpen[0].length;
969
+ return src.slice(0, at) + "\n<head>" + tag + "</head>" + src.slice(at);
970
+ }
971
+ const doctype = /<!doctype[^>]*>/i.exec(head);
972
+ if (doctype) {
973
+ const at = doctype.index + doctype[0].length;
974
+ return src.slice(0, at) + "\n" + tag + src.slice(at);
975
+ }
976
+ return tag + "\n" + src;
977
+ }
978
+ var XML_DECL_RE = /^\s*<\?xml\s[^?]*\?>/i;
979
+ function ensureXmlEncoding(text) {
980
+ const src = String(text == null ? "" : text);
981
+ const decl = XML_DECL_RE.exec(src);
982
+ if (!decl) return src;
983
+ const found = /encoding\s*=\s*["']([^"']*)["']/i.exec(decl[0]);
984
+ if (!found) return src;
985
+ if (found[1].toLowerCase().replace(/[^a-z0-9]/g, "") === "utf8") return src;
986
+ const fixedDecl = decl[0].slice(0, found.index) + found[0].replace(found[1], "UTF-8") + decl[0].slice(found.index + found[0].length);
987
+ return fixedDecl + src.slice(decl[0].length);
988
+ }
989
+ var RTF_SIGNATURE_RE = /^[\s]*\{\\rtf/i;
990
+ function looksLikeRtf(text) {
991
+ return RTF_SIGNATURE_RE.test(String(text == null ? "" : text));
992
+ }
993
+ function escapeRtfNonAscii(text) {
994
+ const src = String(text == null ? "" : text);
995
+ let out = "";
996
+ let plainFrom = 0;
997
+ for (let i = 0; i < src.length; i++) {
998
+ const code = src.charCodeAt(i);
999
+ if (code < 128) continue;
1000
+ out += src.slice(plainFrom, i);
1001
+ out += `\\u${code > 32767 ? code - 65536 : code}?`;
1002
+ plainFrom = i + 1;
1003
+ }
1004
+ return plainFrom === 0 ? src : out + src.slice(plainFrom);
1005
+ }
1006
+ function applyEncodingDeclaration(text, ext) {
1007
+ const src = String(text == null ? "" : text);
1008
+ switch (encodingClassForExt(ext)) {
1009
+ case "bom":
1010
+ return hasBom(src) ? src : BOM + src;
1011
+ case "html":
1012
+ return ensureHtmlCharset(src);
1013
+ case "xml":
1014
+ return ensureXmlEncoding(src);
1015
+ case "rtf":
1016
+ return looksLikeRtf(src) ? escapeRtfNonAscii(src) : hasBom(src) ? src : BOM + src;
1017
+ default:
1018
+ return src;
1019
+ }
1020
+ }
1021
+ function prepareDownloadText(filename, body) {
1022
+ const ext = extOf(filename);
1023
+ return {
1024
+ ext,
1025
+ text: applyEncodingDeclaration(body, ext),
1026
+ contentType: contentTypeForExt(ext)
1027
+ };
1028
+ }
1029
+
855
1030
  // src/engine/time.ts
856
1031
  function wallClockNow() {
857
1032
  return Date.now();
@@ -1013,7 +1188,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
1013
1188
  return { ...m, content: blocks };
1014
1189
  });
1015
1190
  }
1016
- var POLL_INTERVAL = 1500;
1191
+ var POLL_INTERVAL = 3e3;
1017
1192
  async function callClaudeWithMcp({
1018
1193
  prompt,
1019
1194
  messages,
@@ -1937,7 +2112,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
1937
2112
  var chatQueue = useBgQueue ? userId + BG_INDEXING_QUEUE_SUFFIX : userId;
1938
2113
  if (offChat) {
1939
2114
  var offHistory = (this.aiChatHistoryCache[key] ? this.aiChatHistoryCache[key].messages : []).filter(function(m) {
1940
- return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask;
2115
+ return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
1941
2116
  });
1942
2117
  var offBounded = buildBoundedChatMessages({
1943
2118
  platform: aiPlatform,
@@ -1972,7 +2147,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
1972
2147
  }
1973
2148
  if (isQueuedSend) {
1974
2149
  var resolvedHistory = this.state.messages.filter(function(m) {
1975
- return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask;
2150
+ return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
1976
2151
  });
1977
2152
  var boundedQ = buildBoundedChatMessages({
1978
2153
  platform: aiPlatform,
@@ -2023,7 +2198,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
2023
2198
  this.state.sending = true;
2024
2199
  this.host.scrollToBottom(true);
2025
2200
  var historyForLlm = this.state.messages.filter(function(m) {
2026
- return !m.isCancelled && !m.isBackgroundTask;
2201
+ return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
2027
2202
  });
2028
2203
  if (llmComposed !== composed) {
2029
2204
  for (var li = historyForLlm.length - 1; li >= 0; li--) {
@@ -3632,7 +3807,7 @@ Index the REMAINING windows - one record per row/item, looking at any page image
3632
3807
  (function() {
3633
3808
  var MCP_PROD = "https://mcp.broadwayinc.computer";
3634
3809
  var MCP_DEV = "https://mcp-dev.broadwayinc.computer";
3635
- var BQ_VERSION = "1.8.1" ;
3810
+ var BQ_VERSION = "1.8.2" ;
3636
3811
  var ATTACHMENT_URL_EXPIRES_SECONDS = 600;
3637
3812
  var GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
3638
3813
  var GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
@@ -5518,13 +5693,9 @@ Index the REMAINING windows - one record per row/item, looking at any page image
5518
5693
  var key = filename + "\0" + body;
5519
5694
  var existing = fileBlobCache.get(key);
5520
5695
  if (existing) return existing;
5521
- var contentType = mimeGetType(filename) || "text/plain";
5522
- var ext = (String(filename || "").split(".").pop() || "").toLowerCase();
5523
- var isText = /^text\//i.test(contentType) || /application\/(json|xml|csv|yaml|x-yaml|javascript)/i.test(contentType);
5524
- var needsBom = ext === "csv" || ext === "tsv" || ext === "tab";
5525
- var type = isText ? contentType + "; charset=utf-8" : contentType;
5526
- var data = needsBom ? "\uFEFF" + body : body;
5527
- var href = URL.createObjectURL(new Blob([data], { type }));
5696
+ var prepared = prepareDownloadText(filename, body);
5697
+ var type = EXT_CONTENT_TYPES[extOf(filename)] || mimeGetType(filename) || "text/plain; charset=utf-8";
5698
+ var href = URL.createObjectURL(new Blob([prepared.text], { type }));
5528
5699
  fileBlobCache.set(key, href);
5529
5700
  return href;
5530
5701
  }
package/dist/engine.cjs CHANGED
@@ -439,6 +439,19 @@ Index the REMAINING windows - one record per row/item, looking at any page image
439
439
  }
440
440
 
441
441
  // src/engine/errors.ts
442
+ var STATUS_MESSAGE = {
443
+ "408": "The AI provider timed out before it started.",
444
+ "409": "The AI provider rejected the request as conflicting.",
445
+ "413": "The request was too large for the AI provider.",
446
+ "429": "The AI provider is rate limiting requests right now.",
447
+ "500": "The AI provider hit an internal error.",
448
+ "502": "The AI provider is temporarily unreachable.",
449
+ "503": "The AI provider is temporarily unavailable.",
450
+ "504": "The AI provider timed out."
451
+ };
452
+ function isTransientStatus(status) {
453
+ return status === 408 || status === 425 || status === 429 || status >= 500;
454
+ }
442
455
  function getErrorMessage(input) {
443
456
  if (!input) return "Something went wrong.";
444
457
  if (typeof input === "string") return input;
@@ -446,6 +459,11 @@ function getErrorMessage(input) {
446
459
  if (input.body && input.body.error && input.body.error.message) return input.body.error.message;
447
460
  if (input.body && typeof input.body.message === "string") return input.body.message;
448
461
  if (input.message) return input.message;
462
+ var status = typeof input.status_code === "number" ? input.status_code : typeof input.status === "number" ? input.status : 0;
463
+ if (status) {
464
+ var text = STATUS_MESSAGE[String(status)] || (status >= 500 ? "The AI provider returned a server error." : "The AI provider rejected the request.");
465
+ return text + " (error " + status + ")" + (isTransientStatus(status) ? " This is usually temporary, please try again." : "");
466
+ }
449
467
  return "Something went wrong.";
450
468
  }
451
469
  function isErrorResponseBody(response) {
@@ -869,6 +887,166 @@ function buildBoundedChatMessages(options) {
869
887
  };
870
888
  }
871
889
 
890
+ // src/engine/download_encoding.ts
891
+ var BOM = "\uFEFF";
892
+ var BOM_EXTS = /* @__PURE__ */ new Set(["csv", "tsv", "tab", "txt", "text", "log"]);
893
+ var HTML_EXTS = /* @__PURE__ */ new Set(["html", "htm", "xhtml"]);
894
+ var XML_EXTS = /* @__PURE__ */ new Set(["xml", "svg", "rss", "atom", "xsl", "xslt", "plist", "kml"]);
895
+ var RTF_EXTS = /* @__PURE__ */ new Set(["rtf"]);
896
+ var EXT_CONTENT_TYPES = {
897
+ csv: "text/csv; charset=utf-8",
898
+ tsv: "text/tab-separated-values; charset=utf-8",
899
+ tab: "text/tab-separated-values; charset=utf-8",
900
+ txt: "text/plain; charset=utf-8",
901
+ text: "text/plain; charset=utf-8",
902
+ log: "text/plain; charset=utf-8",
903
+ md: "text/markdown; charset=utf-8",
904
+ markdown: "text/markdown; charset=utf-8",
905
+ json: "application/json; charset=utf-8",
906
+ jsonl: "application/x-ndjson; charset=utf-8",
907
+ ndjson: "application/x-ndjson; charset=utf-8",
908
+ geojson: "application/geo+json; charset=utf-8",
909
+ yaml: "text/yaml; charset=utf-8",
910
+ yml: "text/yaml; charset=utf-8",
911
+ toml: "text/plain; charset=utf-8",
912
+ ini: "text/plain; charset=utf-8",
913
+ sql: "text/plain; charset=utf-8",
914
+ html: "text/html; charset=utf-8",
915
+ htm: "text/html; charset=utf-8",
916
+ xhtml: "application/xhtml+xml; charset=utf-8",
917
+ xml: "application/xml; charset=utf-8",
918
+ svg: "image/svg+xml; charset=utf-8",
919
+ css: "text/css; charset=utf-8",
920
+ js: "text/javascript; charset=utf-8",
921
+ ts: "text/plain; charset=utf-8",
922
+ py: "text/x-python; charset=utf-8",
923
+ sh: "text/x-shellscript; charset=utf-8",
924
+ srt: "application/x-subrip; charset=utf-8",
925
+ vtt: "text/vtt; charset=utf-8",
926
+ ics: "text/calendar; charset=utf-8",
927
+ vcf: "text/vcard; charset=utf-8",
928
+ // RTF is 7-bit ASCII by specification, so it takes no charset parameter.
929
+ rtf: "application/rtf",
930
+ // Binary types the model can only ever REFERENCE, never author in a fence, but
931
+ // which keep the type sensible if one ever shows up.
932
+ pdf: "application/pdf",
933
+ png: "image/png",
934
+ jpg: "image/jpeg",
935
+ jpeg: "image/jpeg",
936
+ gif: "image/gif",
937
+ webp: "image/webp"
938
+ };
939
+ function normalizeExt(ext) {
940
+ return String(ext || "").trim().replace(/^\./, "").toLowerCase();
941
+ }
942
+ function extOf(filename) {
943
+ const name = String(filename || "");
944
+ const dot = name.lastIndexOf(".");
945
+ return dot > 0 ? normalizeExt(name.slice(dot + 1)) : "";
946
+ }
947
+ function encodingClassForExt(ext) {
948
+ const e = normalizeExt(ext);
949
+ if (BOM_EXTS.has(e)) return "bom";
950
+ if (HTML_EXTS.has(e)) return "html";
951
+ if (XML_EXTS.has(e)) return "xml";
952
+ if (RTF_EXTS.has(e)) return "rtf";
953
+ return "none";
954
+ }
955
+ function needsBomForExt(ext) {
956
+ return encodingClassForExt(ext) === "bom";
957
+ }
958
+ function contentTypeForExt(ext, fallback = "text/plain; charset=utf-8") {
959
+ return EXT_CONTENT_TYPES[normalizeExt(ext)] || fallback;
960
+ }
961
+ function hasBom(text) {
962
+ return typeof text === "string" && text.charCodeAt(0) === 65279;
963
+ }
964
+ var HTML_HEAD_WINDOW = 4096;
965
+ var META_CHARSET_RE = /<meta[^>]+charset\s*=\s*["']?\s*([a-z0-9_-]+)/i;
966
+ var META_HTTP_EQUIV_RE = /<meta[^>]+http-equiv\s*=\s*["']?content-type["']?[^>]*>/i;
967
+ function ensureHtmlCharset(text) {
968
+ const src = String(text == null ? "" : text);
969
+ const head = src.slice(0, HTML_HEAD_WINDOW);
970
+ const declared = META_CHARSET_RE.exec(head);
971
+ if (declared) {
972
+ if (declared[1].toLowerCase().replace(/[^a-z0-9]/g, "") === "utf8") return src;
973
+ const start = declared.index + declared[0].length - declared[1].length;
974
+ return src.slice(0, start) + "utf-8" + src.slice(start + declared[1].length);
975
+ }
976
+ const httpEquiv = META_HTTP_EQUIV_RE.exec(head);
977
+ if (httpEquiv) {
978
+ return src.slice(0, httpEquiv.index) + '<meta charset="utf-8">' + src.slice(httpEquiv.index + httpEquiv[0].length);
979
+ }
980
+ const tag = '<meta charset="utf-8">';
981
+ const headOpen = /<head[^>]*>/i.exec(head);
982
+ if (headOpen) {
983
+ const at = headOpen.index + headOpen[0].length;
984
+ return src.slice(0, at) + "\n" + tag + src.slice(at);
985
+ }
986
+ const htmlOpen = /<html[^>]*>/i.exec(head);
987
+ if (htmlOpen) {
988
+ const at = htmlOpen.index + htmlOpen[0].length;
989
+ return src.slice(0, at) + "\n<head>" + tag + "</head>" + src.slice(at);
990
+ }
991
+ const doctype = /<!doctype[^>]*>/i.exec(head);
992
+ if (doctype) {
993
+ const at = doctype.index + doctype[0].length;
994
+ return src.slice(0, at) + "\n" + tag + src.slice(at);
995
+ }
996
+ return tag + "\n" + src;
997
+ }
998
+ var XML_DECL_RE = /^\s*<\?xml\s[^?]*\?>/i;
999
+ function ensureXmlEncoding(text) {
1000
+ const src = String(text == null ? "" : text);
1001
+ const decl = XML_DECL_RE.exec(src);
1002
+ if (!decl) return src;
1003
+ const found = /encoding\s*=\s*["']([^"']*)["']/i.exec(decl[0]);
1004
+ if (!found) return src;
1005
+ if (found[1].toLowerCase().replace(/[^a-z0-9]/g, "") === "utf8") return src;
1006
+ const fixedDecl = decl[0].slice(0, found.index) + found[0].replace(found[1], "UTF-8") + decl[0].slice(found.index + found[0].length);
1007
+ return fixedDecl + src.slice(decl[0].length);
1008
+ }
1009
+ var RTF_SIGNATURE_RE = /^[\s]*\{\\rtf/i;
1010
+ function looksLikeRtf(text) {
1011
+ return RTF_SIGNATURE_RE.test(String(text == null ? "" : text));
1012
+ }
1013
+ function escapeRtfNonAscii(text) {
1014
+ const src = String(text == null ? "" : text);
1015
+ let out = "";
1016
+ let plainFrom = 0;
1017
+ for (let i = 0; i < src.length; i++) {
1018
+ const code = src.charCodeAt(i);
1019
+ if (code < 128) continue;
1020
+ out += src.slice(plainFrom, i);
1021
+ out += `\\u${code > 32767 ? code - 65536 : code}?`;
1022
+ plainFrom = i + 1;
1023
+ }
1024
+ return plainFrom === 0 ? src : out + src.slice(plainFrom);
1025
+ }
1026
+ function applyEncodingDeclaration(text, ext) {
1027
+ const src = String(text == null ? "" : text);
1028
+ switch (encodingClassForExt(ext)) {
1029
+ case "bom":
1030
+ return hasBom(src) ? src : BOM + src;
1031
+ case "html":
1032
+ return ensureHtmlCharset(src);
1033
+ case "xml":
1034
+ return ensureXmlEncoding(src);
1035
+ case "rtf":
1036
+ return looksLikeRtf(src) ? escapeRtfNonAscii(src) : hasBom(src) ? src : BOM + src;
1037
+ default:
1038
+ return src;
1039
+ }
1040
+ }
1041
+ function prepareDownloadText(filename, body) {
1042
+ const ext = extOf(filename);
1043
+ return {
1044
+ ext,
1045
+ text: applyEncodingDeclaration(body, ext),
1046
+ contentType: contentTypeForExt(ext)
1047
+ };
1048
+ }
1049
+
872
1050
  // src/engine/time.ts
873
1051
  function wallClockNow() {
874
1052
  return Date.now();
@@ -1041,7 +1219,7 @@ function applyHistoryCacheBreakpoint(messages) {
1041
1219
  return { ...m, content: blocks };
1042
1220
  });
1043
1221
  }
1044
- var POLL_INTERVAL = 1500;
1222
+ var POLL_INTERVAL = 3e3;
1045
1223
  async function callClaudeWithMcp({
1046
1224
  prompt,
1047
1225
  messages,
@@ -1990,7 +2168,7 @@ var ChatSession = class {
1990
2168
  var chatQueue = useBgQueue ? userId + BG_INDEXING_QUEUE_SUFFIX : userId;
1991
2169
  if (offChat) {
1992
2170
  var offHistory = (this.aiChatHistoryCache[key] ? this.aiChatHistoryCache[key].messages : []).filter(function(m) {
1993
- return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask;
2171
+ return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
1994
2172
  });
1995
2173
  var offBounded = buildBoundedChatMessages({
1996
2174
  platform: aiPlatform,
@@ -2025,7 +2203,7 @@ var ChatSession = class {
2025
2203
  }
2026
2204
  if (isQueuedSend) {
2027
2205
  var resolvedHistory = this.state.messages.filter(function(m) {
2028
- return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask;
2206
+ return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
2029
2207
  });
2030
2208
  var boundedQ = buildBoundedChatMessages({
2031
2209
  platform: aiPlatform,
@@ -2076,7 +2254,7 @@ var ChatSession = class {
2076
2254
  this.state.sending = true;
2077
2255
  this.host.scrollToBottom(true);
2078
2256
  var historyForLlm = this.state.messages.filter(function(m) {
2079
- return !m.isCancelled && !m.isBackgroundTask;
2257
+ return !m.isPending && !m.isPendingQueued && !m.isPendingInProcess && !m.isPendingOlder && !m.isCancelled && !m.isBackgroundTask && !m.isError;
2080
2258
  });
2081
2259
  if (llmComposed !== composed) {
2082
2260
  for (var li = historyForLlm.length - 1; li >= 0; li--) {
@@ -3682,6 +3860,8 @@ function buildChatDisplayList(messages, opts) {
3682
3860
  }
3683
3861
 
3684
3862
  exports.BG_INDEXING_QUEUE_SUFFIX = BG_INDEXING_QUEUE_SUFFIX;
3863
+ exports.BOM = BOM;
3864
+ exports.BOM_EXTS = BOM_EXTS;
3685
3865
  exports.CLAUDE_INPUT_CAP_RATIO = CLAUDE_INPUT_CAP_RATIO;
3686
3866
  exports.CLAUDE_PER_REQUEST_INPUT_CAP = CLAUDE_PER_REQUEST_INPUT_CAP;
3687
3867
  exports.CONTEXT_WINDOW_BY_MODEL = CONTEXT_WINDOW_BY_MODEL;
@@ -3692,9 +3872,12 @@ exports.DEFAULT_OPENAI_MODEL = DEFAULT_OPENAI_MODEL;
3692
3872
  exports.EXPIRED_ATTACHMENT_URL_HOST = EXPIRED_ATTACHMENT_URL_HOST;
3693
3873
  exports.EXPIRED_ATTACHMENT_URL_ORIGIN = EXPIRED_ATTACHMENT_URL_ORIGIN;
3694
3874
  exports.EXPIRED_LINK_REFRESH_EXPIRES_SECONDS = EXPIRED_LINK_REFRESH_EXPIRES_SECONDS;
3875
+ exports.EXT_CONTENT_TYPES = EXT_CONTENT_TYPES;
3695
3876
  exports.HISTORY_BUDGET_RATIO = HISTORY_BUDGET_RATIO;
3696
3877
  exports.HISTORY_FILL_SLACK_PX = HISTORY_FILL_SLACK_PX;
3697
3878
  exports.HISTORY_TOKEN_BUDGET = HISTORY_TOKEN_BUDGET;
3879
+ exports.HTML_EXTS = HTML_EXTS;
3880
+ exports.HTML_HEAD_WINDOW = HTML_HEAD_WINDOW;
3698
3881
  exports.LINK_LABEL_MAX_DISPLAY_CHARS = LINK_LABEL_MAX_DISPLAY_CHARS;
3699
3882
  exports.LINK_REFRESH_WINDOW_MS = LINK_REFRESH_WINDOW_MS;
3700
3883
  exports.MAX_HISTORY_FILL_PAGES = MAX_HISTORY_FILL_PAGES;
@@ -3705,7 +3888,10 @@ exports.MIN_INPUT_TOKEN_BUDGET = MIN_INPUT_TOKEN_BUDGET;
3705
3888
  exports.OUTPUT_TOKEN_RESERVE = OUTPUT_TOKEN_RESERVE;
3706
3889
  exports.POLL_INTERVAL = POLL_INTERVAL;
3707
3890
  exports.RENDER_FROM_TOKEN = RENDER_FROM_TOKEN;
3891
+ exports.RTF_EXTS = RTF_EXTS;
3708
3892
  exports.TOOL_AND_RESPONSE_BUFFER = TOOL_AND_RESPONSE_BUFFER;
3893
+ exports.XML_EXTS = XML_EXTS;
3894
+ exports.applyEncodingDeclaration = applyEncodingDeclaration;
3709
3895
  exports.buildAiAgentValue = buildAiAgentValue;
3710
3896
  exports.buildBoundedChatMessages = buildBoundedChatMessages;
3711
3897
  exports.buildChatDisplayList = buildChatDisplayList;
@@ -3725,11 +3911,17 @@ exports.classifyInlineLink = classifyInlineLink;
3725
3911
  exports.clearAttachmentParsers = clearAttachmentParsers;
3726
3912
  exports.composeUserMessage = composeUserMessage;
3727
3913
  exports.configureChatEngine = configureChatEngine;
3914
+ exports.contentTypeForExt = contentTypeForExt;
3728
3915
  exports.createHistoryFiller = createHistoryFiller;
3729
3916
  exports.createInlineLinkRegex = createInlineLinkRegex;
3730
3917
  exports.encodePathSegments = encodePathSegments;
3918
+ exports.encodingClassForExt = encodingClassForExt;
3919
+ exports.ensureHtmlCharset = ensureHtmlCharset;
3920
+ exports.ensureXmlEncoding = ensureXmlEncoding;
3921
+ exports.escapeRtfNonAscii = escapeRtfNonAscii;
3731
3922
  exports.estimateMessageTokens = estimateMessageTokens;
3732
3923
  exports.estimateTextTokens = estimateTextTokens;
3924
+ exports.extOf = extOf;
3733
3925
  exports.extractClaudeText = extractClaudeText;
3734
3926
  exports.extractLastUserTextFromRequest = extractLastUserTextFromRequest;
3735
3927
  exports.extractOpenAIText = extractOpenAIText;
@@ -3745,6 +3937,7 @@ exports.getErrorMessage = getErrorMessage;
3745
3937
  exports.getExpiredAttachmentVisiblePath = getExpiredAttachmentVisiblePath;
3746
3938
  exports.getProjectContextWindow = getProjectContextWindow;
3747
3939
  exports.groupAttachmentFailures = groupAttachmentFailures;
3940
+ exports.hasBom = hasBom;
3748
3941
  exports.isAuthExpiredError = isAuthExpiredError;
3749
3942
  exports.isBgIndexingQueue = isBgIndexingQueue;
3750
3943
  exports.isErrorResponseBody = isErrorResponseBody;
@@ -3756,9 +3949,12 @@ exports.isServerExtractable = isServerExtractable;
3756
3949
  exports.isServiceDbAttachmentHref = isServiceDbAttachmentHref;
3757
3950
  exports.listClaudeModels = listClaudeModels;
3758
3951
  exports.listOpenAIModels = listOpenAIModels;
3952
+ exports.looksLikeRtf = looksLikeRtf;
3759
3953
  exports.makeExtractPlaceholder = makeExtractPlaceholder;
3760
3954
  exports.mapHistoryListToMessages = mapHistoryListToMessages;
3955
+ exports.needsBomForExt = needsBomForExt;
3761
3956
  exports.normalizeAttachmentPathCandidate = normalizeAttachmentPathCandidate;
3957
+ exports.normalizeExt = normalizeExt;
3762
3958
  exports.normalizeTextContent = normalizeTextContent;
3763
3959
  exports.normalizeTrailingInlineToken = normalizeTrailingInlineToken;
3764
3960
  exports.notifyAgentSaveAttachment = notifyAgentSaveAttachment;
@@ -3766,6 +3962,7 @@ exports.parseAiAgentValue = parseAiAgentValue;
3766
3962
  exports.parseAttachmentContent = parseAttachmentContent;
3767
3963
  exports.parseIndexingLabel = parseIndexingLabel;
3768
3964
  exports.parseIndexingRequestText = parseIndexingRequestText;
3965
+ exports.prepareDownloadText = prepareDownloadText;
3769
3966
  exports.readExpiredAttachmentHref = readExpiredAttachmentHref;
3770
3967
  exports.registerAttachmentParser = registerAttachmentParser;
3771
3968
  exports.registerModelContextWindows = registerModelContextWindows;