bunnyquery 1.4.6 → 1.5.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.css CHANGED
@@ -162,6 +162,87 @@
162
162
  to { transform: rotate(360deg); }
163
163
  }
164
164
 
165
+ /* jumping ASCII bunny — full-area "loading/fetching" indicator (page/gate loads,
166
+ initial history fetch, settings panel). Ported from www.bunnyquery.com
167
+ bunnyLoader.vue. Two <pre> frames toggle + hop across the track and flip. */
168
+ .bq-bunny-loader {
169
+ display: flex;
170
+ flex-direction: column;
171
+ align-items: center;
172
+ justify-content: center;
173
+ gap: 0.75rem;
174
+ }
175
+ .bq-bunny-loader--overlay {
176
+ position: absolute;
177
+ inset: 0;
178
+ pointer-events: none;
179
+ z-index: 4;
180
+ }
181
+ .bq-bunny-stage {
182
+ display: inline-block;
183
+ position: relative;
184
+ text-align: left;
185
+ }
186
+ .bq-bunny-track {
187
+ position: relative;
188
+ height: 3.6rem;
189
+ width: 100%;
190
+ animation: bq-bunny-move 9s steps(12) infinite;
191
+ }
192
+ .bq-bunny-dir {
193
+ display: inline-block;
194
+ position: absolute;
195
+ bottom: 0;
196
+ left: 0;
197
+ animation: bq-bunny-flip 9s steps(1) infinite;
198
+ }
199
+ .bq-frame {
200
+ margin: 0;
201
+ /* Pin a Latin monospace font. Without it the <pre> falls back to the UA
202
+ `monospace` keyword, which on Korean/Japanese systems can resolve to a
203
+ CJK font that renders U+005C (backslash) as ₩ / ¥ — wrecking the art. */
204
+ font-family: var(--bq-mono);
205
+ font-size: 1rem;
206
+ line-height: 1.2;
207
+ white-space: pre;
208
+ color: var(--bq-ink);
209
+ }
210
+ .bq-frame-a {
211
+ animation: bq-bunny-toggle-a 1s steps(1) infinite;
212
+ }
213
+ .bq-frame-b {
214
+ animation: bq-bunny-toggle-b 1s steps(1) infinite;
215
+ opacity: 0;
216
+ }
217
+ .bq-bunny-loader__label {
218
+ color: var(--bq-ink);
219
+ font-family: var(--bq-mono);
220
+ font-size: 0.83rem;
221
+ }
222
+ @keyframes bq-bunny-move {
223
+ 0% { transform: translateX(-11ch); }
224
+ 25% { transform: translateX(4ch); }
225
+ 37.5% { transform: translateX(4ch); }
226
+ 50% { transform: translateX(4ch); }
227
+ 75% { transform: translateX(-11ch); }
228
+ 87.5% { transform: translateX(-11ch); }
229
+ 100% { transform: translateX(-11ch); }
230
+ }
231
+ @keyframes bq-bunny-flip {
232
+ 0% { transform: scaleX(1); }
233
+ 50% { transform: scaleX(-1); }
234
+ }
235
+ @keyframes bq-bunny-toggle-a {
236
+ 0% { opacity: 1; }
237
+ 25% { opacity: 0; }
238
+ 100% { opacity: 1; }
239
+ }
240
+ @keyframes bq-bunny-toggle-b {
241
+ 0% { opacity: 0; }
242
+ 25% { opacity: 1; }
243
+ 100% { opacity: 0; }
244
+ }
245
+
165
246
  /* ============================================================================
166
247
  * AUTH VIEWS (login / signup / forgot / verify / settings)
167
248
  * ==========================================================================*/
package/bunnyquery.js CHANGED
@@ -473,7 +473,7 @@ ${options.inlineContentPlaceholder}
473
473
  }
474
474
  function stripFileBlocksFromHistory(content) {
475
475
  if (!content) return content;
476
- return content.replace(/```([\w.-]+\.[a-zA-Z0-9]+)\n[\s\S]*?```/g, "[file previously attached: $1]");
476
+ return content.replace(/```([^\n`]+?\.[^\s.`]+)\n[\s\S]*?```/g, "[file previously attached: $1]");
477
477
  }
478
478
  function buildBoundedChatMessages(options) {
479
479
  var contextWindow = getContextWindow(options.platform, options.model);
@@ -1530,7 +1530,7 @@ ${options.inlineContentPlaceholder}
1530
1530
  var MIN_STEP = 1;
1531
1531
  var MAX_FRAME_MS = 1e3;
1532
1532
  var regions = [], m;
1533
- var fenceRegex = /```[\w.-]+\.[a-zA-Z0-9]+\n[\s\S]*?```/g;
1533
+ var fenceRegex = /```[^\n`]+?\.[^\s.`]+\n[\s\S]*?```/g;
1534
1534
  while ((m = fenceRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
1535
1535
  var linkRegex = createInlineLinkRegex();
1536
1536
  while ((m = linkRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
@@ -2015,6 +2015,7 @@ ${options.inlineContentPlaceholder}
2015
2015
  members.forEach(function(member, idx) {
2016
2016
  chain = chain.then(function() {
2017
2017
  var hadExists = false;
2018
+ var skipped = false;
2018
2019
  var onProg = function(p) {
2019
2020
  if (p && p.total) {
2020
2021
  att.progress = Math.floor((idx + p.loaded / p.total) / total * 100);
@@ -2039,11 +2040,17 @@ ${options.inlineContentPlaceholder}
2039
2040
  if (!isExists) throw err;
2040
2041
  return self.host.promptOverwrite(member.file.name).then(function(choice) {
2041
2042
  if (choice === "overwrite") return doMemberUpload(false);
2043
+ if (choice === "skip") {
2044
+ skipped = true;
2045
+ return;
2046
+ }
2042
2047
  hadExists = true;
2043
2048
  });
2044
2049
  }).then(function() {
2050
+ if (skipped) return;
2045
2051
  return self.host.getTemporaryUrl(member.storagePath);
2046
2052
  }).then(function(url) {
2053
+ if (skipped) return;
2047
2054
  urls.push({ name: member.relPath, url, storagePath: member.storagePath });
2048
2055
  if (att.kind !== "folder") {
2049
2056
  att.uploadedUrl = url;
@@ -2176,7 +2183,7 @@ ${options.inlineContentPlaceholder}
2176
2183
  (function() {
2177
2184
  var MCP_PROD = "https://mcp.broadwayinc.computer";
2178
2185
  var MCP_DEV = "https://mcp-dev.broadwayinc.computer";
2179
- var BQ_VERSION = "1.4.6" ;
2186
+ var BQ_VERSION = "1.5.1" ;
2180
2187
  var ATTACHMENT_URL_EXPIRES_SECONDS = 600;
2181
2188
  var GOOGLE_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
2182
2189
  var GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
@@ -2431,13 +2438,40 @@ ${options.inlineContentPlaceholder}
2431
2438
  })
2432
2439
  );
2433
2440
  }
2441
+ var BUNNY_FRAME_A = ' (\\(\\\n ( - -)\n c(")(")';
2442
+ var BUNNY_FRAME_B = ' /)/)\n ( . .)\nc(")(")';
2443
+ function bunnyLoader(label, overlay) {
2444
+ return h(
2445
+ "div",
2446
+ {
2447
+ class: "bq-bunny-loader" + (""),
2448
+ "aria-hidden": "true",
2449
+ translate: "no"
2450
+ },
2451
+ h(
2452
+ "div",
2453
+ { class: "bq-bunny-stage" },
2454
+ h(
2455
+ "div",
2456
+ { class: "bq-bunny-track" },
2457
+ h(
2458
+ "div",
2459
+ { class: "bq-bunny-dir" },
2460
+ h("pre", { class: "bq-frame bq-frame-a", translate: "no", text: BUNNY_FRAME_A }),
2461
+ h("pre", { class: "bq-frame bq-frame-b", translate: "no", text: BUNNY_FRAME_B })
2462
+ )
2463
+ )
2464
+ ),
2465
+ label ? h("div", { class: "bq-bunny-loader__label", text: label }) : null
2466
+ );
2467
+ }
2434
2468
  function showLoading(label) {
2435
2469
  render("loading", function() {
2436
2470
  return pageRoot(
2437
2471
  h(
2438
2472
  "div",
2439
2473
  { class: "bq-disabled-inner", style: { marginTop: "3rem" } },
2440
- h("span", { class: "bq-loader", text: "Loading" })
2474
+ bunnyLoader("Loading...")
2441
2475
  )
2442
2476
  );
2443
2477
  });
@@ -3323,7 +3357,7 @@ ${options.inlineContentPlaceholder}
3323
3357
  CS.messagesBox.appendChild(h(
3324
3358
  "div",
3325
3359
  { class: "bq-chat-settings" },
3326
- h("div", { class: "bq-chat-settings-loading" }, h("span", { class: "bq-loader", text: "Loading" }))
3360
+ h("div", { class: "bq-chat-settings-loading" }, bunnyLoader("Loading..."))
3327
3361
  ));
3328
3362
  Promise.all([getProfile(), getNewsletterStatus()]).then(function(res) {
3329
3363
  if (res[0]) S.user = res[0];
@@ -3991,13 +4025,18 @@ ${options.inlineContentPlaceholder}
3991
4025
  var existing = fileBlobCache.get(key);
3992
4026
  if (existing) return existing;
3993
4027
  var contentType = mimeGetType(filename) || "text/plain";
3994
- var href = URL.createObjectURL(new Blob([body], { type: contentType }));
4028
+ var ext = (String(filename || "").split(".").pop() || "").toLowerCase();
4029
+ var isText = /^text\//i.test(contentType) || /application\/(json|xml|csv|yaml|x-yaml|javascript)/i.test(contentType);
4030
+ var needsBom = ext === "csv" || ext === "tsv" || ext === "tab";
4031
+ var type = isText ? contentType + "; charset=utf-8" : contentType;
4032
+ var data = needsBom ? "\uFEFF" + body : body;
4033
+ var href = URL.createObjectURL(new Blob([data], { type }));
3995
4034
  fileBlobCache.set(key, href);
3996
4035
  return href;
3997
4036
  }
3998
4037
  function fileToAnchorHtml(filename, href) {
3999
4038
  var text = "\u2197 " + filename;
4000
- return '<a class="bq-file-download" href="' + escapeHtml(href) + '" target="_blank" rel="noopener noreferrer">' + escapeHtml(text) + "</a>";
4039
+ return '<a class="bq-file-download" href="' + escapeHtml(href) + '" download="' + escapeHtml(filename) + '" target="_blank" rel="noopener noreferrer">' + escapeHtml(text) + "</a>";
4001
4040
  }
4002
4041
  function linkToAnchorHtml(link) {
4003
4042
  var refreshing = !!refreshingLinkMap[link.expiredHref || link.href];
@@ -4068,13 +4107,13 @@ ${options.inlineContentPlaceholder}
4068
4107
  return PH(idx);
4069
4108
  };
4070
4109
  var working = String(content == null ? "" : content).replace(
4071
- /```([\w.-]+\.[a-zA-Z0-9]+)\n([\s\S]*?)```/g,
4110
+ /```([^\n`]+?\.[^\s.`]+)\n([\s\S]*?)```/g,
4072
4111
  function(_full, filename, body) {
4073
4112
  return pushPlaceholder(fileToAnchorHtml(filename, getOrCreateFileHref(filename, body)));
4074
4113
  }
4075
4114
  );
4076
4115
  if (CS.typing) {
4077
- var openFence = working.match(/```([\w.-]+\.[a-zA-Z0-9]+)\n?/);
4116
+ var openFence = working.match(/```([^\n`]+?\.[^\s.`]+)\n?/);
4078
4117
  if (openFence && typeof openFence.index === "number") {
4079
4118
  working = working.slice(0, openFence.index) + "\n[generating " + openFence[1] + "\u2026]";
4080
4119
  }
@@ -4843,9 +4882,16 @@ ${options.inlineContentPlaceholder}
4843
4882
  return h("div", { class: cls.join(" "), dataset: { msgIndex: String(idx) } }, bubble);
4844
4883
  }
4845
4884
  function historyLoadingEl(initial) {
4885
+ if (initial) {
4886
+ return h(
4887
+ "div",
4888
+ { class: "bq-history-loading is-initial" },
4889
+ bunnyLoader("Fetching history...")
4890
+ );
4891
+ }
4846
4892
  return h(
4847
4893
  "div",
4848
- { class: "bq-history-loading" + (initial ? " is-initial" : "") },
4894
+ { class: "bq-history-loading" },
4849
4895
  h("span", { text: "Fetching history" }),
4850
4896
  h("span", { class: "bq-loader" })
4851
4897
  );
@@ -5073,12 +5119,15 @@ ${options.inlineContentPlaceholder}
5073
5119
  h(
5074
5120
  "p",
5075
5121
  { class: "bq-modal-desc" },
5076
- "A file named \u201C" + filename + "\u201D already exists. Keep the existing file and just reindex it, or overwrite it completely?"
5122
+ "A file named \u201C" + filename + "\u201D already exists. Skip it, keep the existing file and just reindex it, or overwrite it completely?"
5077
5123
  ),
5078
5124
  applyLabel,
5079
5125
  h(
5080
5126
  "div",
5081
5127
  { class: "bq-modal-btns" },
5128
+ h("button", { class: "btn btn--outline", type: "button", onclick: function() {
5129
+ chooseOverwrite("skip");
5130
+ } }, "Skip"),
5082
5131
  h("button", { class: "btn btn--outline", type: "button", onclick: function() {
5083
5132
  chooseOverwrite("reindex");
5084
5133
  } }, "Reindex only"),
package/dist/engine.cjs CHANGED
@@ -480,7 +480,7 @@ function getContextWindow(platform, model) {
480
480
  }
481
481
  function stripFileBlocksFromHistory(content) {
482
482
  if (!content) return content;
483
- return content.replace(/```([\w.-]+\.[a-zA-Z0-9]+)\n[\s\S]*?```/g, "[file previously attached: $1]");
483
+ return content.replace(/```([^\n`]+?\.[^\s.`]+)\n[\s\S]*?```/g, "[file previously attached: $1]");
484
484
  }
485
485
  function buildBoundedChatMessages(options) {
486
486
  var contextWindow = getContextWindow(options.platform, options.model);
@@ -1564,7 +1564,7 @@ var ChatSession = class {
1564
1564
  var MIN_STEP = 1;
1565
1565
  var MAX_FRAME_MS = 1e3;
1566
1566
  var regions = [], m;
1567
- var fenceRegex = /```[\w.-]+\.[a-zA-Z0-9]+\n[\s\S]*?```/g;
1567
+ var fenceRegex = /```[^\n`]+?\.[^\s.`]+\n[\s\S]*?```/g;
1568
1568
  while ((m = fenceRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
1569
1569
  var linkRegex = createInlineLinkRegex();
1570
1570
  while ((m = linkRegex.exec(fullText)) !== null) regions.push({ start: m.index, end: m.index + m[0].length });
@@ -2049,6 +2049,7 @@ var ChatSession = class {
2049
2049
  members.forEach(function(member, idx) {
2050
2050
  chain = chain.then(function() {
2051
2051
  var hadExists = false;
2052
+ var skipped = false;
2052
2053
  var onProg = function(p) {
2053
2054
  if (p && p.total) {
2054
2055
  att.progress = Math.floor((idx + p.loaded / p.total) / total * 100);
@@ -2073,11 +2074,17 @@ var ChatSession = class {
2073
2074
  if (!isExists) throw err;
2074
2075
  return self.host.promptOverwrite(member.file.name).then(function(choice) {
2075
2076
  if (choice === "overwrite") return doMemberUpload(false);
2077
+ if (choice === "skip") {
2078
+ skipped = true;
2079
+ return;
2080
+ }
2076
2081
  hadExists = true;
2077
2082
  });
2078
2083
  }).then(function() {
2084
+ if (skipped) return;
2079
2085
  return self.host.getTemporaryUrl(member.storagePath);
2080
2086
  }).then(function(url) {
2087
+ if (skipped) return;
2081
2088
  urls.push({ name: member.relPath, url, storagePath: member.storagePath });
2082
2089
  if (att.kind !== "folder") {
2083
2090
  att.uploadedUrl = url;