zames_pro 2.81.14 → 2.81.16
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 +12 -0
- package/dist/i18n/common.js +7 -4
- package/dist/web.js +36 -22
- package/package.json +1 -1
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.81.16] - 2026-10-21
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **i18n:** /cost describes the context counter neutrally
|
|
15
|
+
|
|
16
|
+
## [2.81.15] - 2026-10-21
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **web:** a search result without a snippet no longer borrows the next one
|
|
21
|
+
|
|
10
22
|
## [2.81.14] - 2026-10-21
|
|
11
23
|
|
|
12
24
|
### Fixed
|
package/dist/i18n/common.js
CHANGED
|
@@ -285,13 +285,16 @@ export const commonMessages = {
|
|
|
285
285
|
en: 'Session renamed: {v}',
|
|
286
286
|
},
|
|
287
287
|
'cost.title': { ru: 'Статистика сессии:', en: 'Session stats:' },
|
|
288
|
+
// /cost runs on EVERY provider, so the counter is described neutrally:
|
|
289
|
+
// DeepSeek reports accumulated_token_usage, Qwen input_tokens, GLM
|
|
290
|
+
// prompt_tokens - naming one backend made the other two look broken.
|
|
288
291
|
'cost.context_known': {
|
|
289
|
-
ru: ' контекст: ~{n} токенов (
|
|
290
|
-
en: ' context: ~{n} tokens (
|
|
292
|
+
ru: ' контекст: ~{n} токенов (счётчик провайдера)',
|
|
293
|
+
en: ' context: ~{n} tokens (the provider counter)',
|
|
291
294
|
},
|
|
292
295
|
'cost.context_unknown': {
|
|
293
|
-
ru: ' контекст: неизвестно (
|
|
294
|
-
en: ' context: unknown (
|
|
296
|
+
ru: ' контекст: неизвестно (провайдер сообщит после первого ответа в чате)',
|
|
297
|
+
en: ' context: unknown (the provider reports it after the first answer in a chat)',
|
|
295
298
|
},
|
|
296
299
|
'cost.tasks': { ru: ' задач: {n}', en: ' tasks: {n}' },
|
|
297
300
|
'cost.tool_calls': {
|
package/dist/web.js
CHANGED
|
@@ -645,33 +645,47 @@ export function createWebTools() {
|
|
|
645
645
|
// wraps links in a /l/?uddg=... redirect which must be unwrapped.
|
|
646
646
|
export function parseDuckDuckGoResults(body, limit) {
|
|
647
647
|
const results = [];
|
|
648
|
-
|
|
648
|
+
// Parse the page ROW BY ROW: each `result__a` title opens a result, and a
|
|
649
|
+
// `result__snippet` belongs to the result opened most recently. The old
|
|
650
|
+
// single regex made the snippet group OPTIONAL with an unbounded gap, so a
|
|
651
|
+
// result without a snippet picked up the FOLLOWING result's snippet (wrong
|
|
652
|
+
// text under a URL). A row scan ties every snippet to its own result.
|
|
653
|
+
const anchorRe = /<a[^>]*class="[^"]*result__(a|snippet)[^"]*"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
654
|
+
const hrefOf = (tag) => {
|
|
655
|
+
const m = tag.match(/href="([^"]*)"/i);
|
|
656
|
+
return m ? m[1] : '';
|
|
657
|
+
};
|
|
658
|
+
let cur = null;
|
|
649
659
|
let m;
|
|
650
|
-
while ((m =
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
try {
|
|
658
|
-
href = decodeURIComponent(uddgMatch[1]);
|
|
660
|
+
while ((m = anchorRe.exec(body))) {
|
|
661
|
+
const kind = m[1].toLowerCase();
|
|
662
|
+
if (kind === 'a') {
|
|
663
|
+
if (cur && cur.title && /^https?:\/\//i.test(cur.url)) {
|
|
664
|
+
results.push(cur);
|
|
665
|
+
if (results.length >= limit)
|
|
666
|
+
return results;
|
|
659
667
|
}
|
|
660
|
-
|
|
661
|
-
|
|
668
|
+
cur = { title: htmlToText(m[2] || '').trim(), url: '', snippet: '' };
|
|
669
|
+
// The href lives in the OPENING tag, which m[0] starts with.
|
|
670
|
+
let href = hrefOf(m[0].slice(0, m[0].indexOf('>') + 1));
|
|
671
|
+
const uddg = href.match(/[?&]uddg=([^&]+)/);
|
|
672
|
+
if (uddg) {
|
|
673
|
+
try {
|
|
674
|
+
href = decodeURIComponent(uddg[1]);
|
|
675
|
+
}
|
|
676
|
+
catch {
|
|
677
|
+
href = uddg[1];
|
|
678
|
+
}
|
|
662
679
|
}
|
|
663
|
-
|
|
664
|
-
const title = htmlToText(m[2] || '').trim();
|
|
665
|
-
const snippet = htmlToText(m[3] || '').trim();
|
|
666
|
-
// Only an absolute http(s) link is a real result. The page can carry a
|
|
667
|
-
// `javascript:`/`data:` href (malicious or broken markup) or a
|
|
668
|
-
// site-relative one; handing either to the model as a result URL is wrong
|
|
669
|
-
// (a `javascript:` URL looks fetchable, a relative one is not).
|
|
670
|
-
if (!title || !/^https?:\/\//i.test(href))
|
|
680
|
+
cur.url = href;
|
|
671
681
|
continue;
|
|
672
|
-
|
|
682
|
+
}
|
|
683
|
+
if (cur && !cur.snippet)
|
|
684
|
+
cur.snippet = htmlToText(m[2] || '').trim();
|
|
673
685
|
}
|
|
674
|
-
|
|
686
|
+
if (cur && cur.title && /^https?:\/\//i.test(cur.url))
|
|
687
|
+
results.push(cur);
|
|
688
|
+
return results.slice(0, limit);
|
|
675
689
|
}
|
|
676
690
|
function formatResult(status, url, text, limit) {
|
|
677
691
|
let out = text;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zames_pro",
|
|
3
|
-
"version": "2.81.
|
|
3
|
+
"version": "2.81.16",
|
|
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": {
|