zames_pro 2.82.92 → 2.82.94

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/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.82.94] - 2026-10-24
11
+
12
+ ### Fixed
13
+
14
+ - **web:** WebFetch cap does not split a surrogate pair
15
+
16
+ ## [2.82.93] - 2026-10-24
17
+
18
+ ### Fixed
19
+
20
+ - **web:** collapse a duplicated search result URL
21
+
10
22
  ## [2.82.92] - 2026-10-24
11
23
 
12
24
  ### Fixed
package/dist/web.js CHANGED
@@ -665,6 +665,9 @@ export function parseDuckDuckGoResults(body, limit) {
665
665
  return m ? (m[1] ?? m[2] ?? '') : '';
666
666
  };
667
667
  let cur = null;
668
+ // The page can repeat the SAME result (a sponsored row mirroring an organic
669
+ // one): two identical URLs made WebSearch print and cite it twice.
670
+ const seenUrls = new Set();
668
671
  let m;
669
672
  while ((m = anchorRe.exec(body))) {
670
673
  const classes = m[1] ?? m[2] ?? '';
@@ -675,9 +678,12 @@ export function parseDuckDuckGoResults(body, limit) {
675
678
  const text = m[3] || '';
676
679
  if (kind === 'a') {
677
680
  if (cur && cur.title && /^https?:\/\//i.test(cur.url)) {
678
- results.push(cur);
679
- if (results.length >= limit)
680
- return results;
681
+ if (!seenUrls.has(cur.url)) {
682
+ seenUrls.add(cur.url);
683
+ results.push(cur);
684
+ if (results.length >= limit)
685
+ return results;
686
+ }
681
687
  }
682
688
  cur = { title: htmlToText(text).trim(), url: '', snippet: '' };
683
689
  // The href lives in the OPENING tag, which m[0] starts with.
@@ -697,15 +703,33 @@ export function parseDuckDuckGoResults(body, limit) {
697
703
  if (cur && !cur.snippet)
698
704
  cur.snippet = htmlToText(text).trim();
699
705
  }
700
- if (cur && cur.title && /^https?:\/\//i.test(cur.url))
706
+ if (cur &&
707
+ cur.title &&
708
+ /^https?:\/\//i.test(cur.url) &&
709
+ !seenUrls.has(cur.url)) {
710
+ seenUrls.add(cur.url);
701
711
  results.push(cur);
712
+ }
702
713
  return results.slice(0, limit);
703
714
  }
715
+ /**
716
+ * Clip fetched page text WITHOUT splitting a surrogate pair. PURE;
717
+ * exported so the clip is unit-tested (formatResult itself is private).
718
+ */
719
+ export function capFetchedText(text, limit) {
720
+ if (text.length <= limit)
721
+ return text;
722
+ let cut = Math.max(0, limit);
723
+ const last = text.charCodeAt(cut - 1);
724
+ if (last >= 0xd800 && last <= 0xdbff)
725
+ cut--;
726
+ return text.slice(0, cut);
727
+ }
704
728
  function formatResult(status, url, text, limit) {
705
729
  let out = text;
706
730
  let truncated = false;
707
731
  if (out.length > limit) {
708
- out = out.slice(0, limit);
732
+ out = capFetchedText(out, limit);
709
733
  truncated = true;
710
734
  }
711
735
  return (`HTTP ${status} ${url}\n\n${out}` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.82.92",
3
+ "version": "2.82.94",
4
4
  "description": "Terminal coding agent that drives a real browser to chat with DeepSeek, Qwen and other web LLMs — no API key required. Reads and edits files, runs commands, commits to git, like Claude Code / Codex CLI.",
5
5
  "type": "module",
6
6
  "bin": {