zames_pro 2.82.18 → 2.82.21
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 +22 -0
- package/dist/glm-chats.js +20 -17
- package/dist/qwen-chats.js +21 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.82.21] - 2026-10-22
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **glm:** unwrap nested pagination wrappers in the chat list
|
|
15
|
+
|
|
16
|
+
## [2.82.20] - 2026-10-22
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- **qwen:** unwrap a paginated chat-list wrapper
|
|
21
|
+
|
|
22
|
+
## [2.82.19] - 2026-10-22
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **glm:** unwrap a nested chats wrapper in the chat list
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- **glm:** drop guessed role fields from the history parser
|
|
31
|
+
|
|
10
32
|
## [2.82.18] - 2026-10-22
|
|
11
33
|
|
|
12
34
|
### Fixed
|
package/dist/glm-chats.js
CHANGED
|
@@ -85,12 +85,20 @@ export function scrapeGlmChatMessages(opts) {
|
|
|
85
85
|
* anything unrecognizable (never throws).
|
|
86
86
|
*/
|
|
87
87
|
export function parseGlmChatList(json) {
|
|
88
|
+
// Unwrap up to THREE levels of list wrappers: a paginated reply nests them
|
|
89
|
+
// (`{data:{list:{page,data:[…]}}}`, `{chats:{page,data:[…]}}`). Leaving an
|
|
90
|
+
// inner wrapper in place made its KEY (`'data'`/`'list'`) look like a chat id
|
|
91
|
+
// with an empty title, so /chats showed one fake chat and hid the real ones.
|
|
92
|
+
// A bare id-keyed MAP of chats has none of these keys and is kept as-is.
|
|
88
93
|
let arr = json;
|
|
89
|
-
|
|
94
|
+
for (let depth = 0; depth < 3; depth++) {
|
|
95
|
+
if (!arr || typeof arr !== 'object' || Array.isArray(arr))
|
|
96
|
+
break;
|
|
90
97
|
const o = arr;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
98
|
+
const next = o.data ?? o.chats ?? o.list ?? o.items;
|
|
99
|
+
if (next === undefined)
|
|
100
|
+
break;
|
|
101
|
+
arr = next;
|
|
94
102
|
}
|
|
95
103
|
const keyed = Array.isArray(arr)
|
|
96
104
|
? null
|
|
@@ -154,30 +162,25 @@ export function parseGlmHistory(json) {
|
|
|
154
162
|
.sort((a, b) => (Number(a.timestamp) || 0) - (Number(b.timestamp) || 0));
|
|
155
163
|
const out = [];
|
|
156
164
|
for (const m of sorted) {
|
|
157
|
-
// The role
|
|
158
|
-
//
|
|
159
|
-
//
|
|
165
|
+
// The role comes from `role` (confirmed by the live fixture). Only the
|
|
166
|
+
// values the API actually uses are matched: a numeric flag or a `from`
|
|
167
|
+
// field was never observed on z.ai and guessing at it would silently
|
|
168
|
+
// re-attribute turns.
|
|
160
169
|
const roleStr = String(m.role ?? '').toLowerCase();
|
|
161
|
-
const fromStr = String(m.from ?? '').toLowerCase();
|
|
162
170
|
// A SYSTEM/TOOL turn is neither the operator nor the model's answer: z.ai's
|
|
163
171
|
// own system prompt and the sandbox output of its agent runtime used to be
|
|
164
172
|
// restored as model REPLIES (the Qwen parser drops those roles too).
|
|
165
|
-
if (/^(system|tool)$/.test(roleStr)
|
|
173
|
+
if (/^(system|tool)$/.test(roleStr))
|
|
166
174
|
continue;
|
|
167
|
-
|
|
168
|
-
// A numeric flag uses 1 = user, 2 = assistant (the same convention as
|
|
169
|
-
// Qwen's history); anything else is matched by name.
|
|
170
|
-
const isUser = roleStr === 'user' ||
|
|
171
|
-
roleStr === 'human' ||
|
|
172
|
-
roleStr === '1' ||
|
|
173
|
-
fromStr === 'user' ||
|
|
174
|
-
fromStr === 'human';
|
|
175
|
+
const isUser = roleStr === 'user' || roleStr === 'human';
|
|
175
176
|
const role = isUser ? 'user' : 'assistant';
|
|
176
177
|
let text = '';
|
|
177
178
|
if (typeof m.content === 'string')
|
|
178
179
|
text = m.content;
|
|
179
180
|
else if (typeof m.text === 'string')
|
|
180
181
|
text = m.text;
|
|
182
|
+
// `fragments` is the DeepSeek-style payload (kept as a safety net for a
|
|
183
|
+
// build that reuses it): REQUEST is the user turn, RESPONSE the answer.
|
|
181
184
|
else if (Array.isArray(m.fragments)) {
|
|
182
185
|
const want = role === 'assistant' ? 'RESPONSE' : 'REQUEST';
|
|
183
186
|
for (const fr of m.fragments) {
|
package/dist/qwen-chats.js
CHANGED
|
@@ -91,6 +91,26 @@ export function scrapeQwenChatMessages(opts) {
|
|
|
91
91
|
* { data: [ {id,title} ] }, { data: { chats: [...] } }, { data: { list: [...] } }.
|
|
92
92
|
* Returns [] for anything unrecognizable (never throws).
|
|
93
93
|
*/
|
|
94
|
+
/**
|
|
95
|
+
* Unwrap the list out of its wrappers: `{chats:[…]}`, `{list:{page,data:[…]}}`.
|
|
96
|
+
* A paginated reply nests the wrapper INSIDE the wrapper, and treating that
|
|
97
|
+
* inner object as an id-keyed map made its own key (`'data'`, `'list'`) look
|
|
98
|
+
* like a chat id. A plain id-keyed map (no known wrapper key) is returned
|
|
99
|
+
* as-is, because that is a legitimate shape too.
|
|
100
|
+
*/
|
|
101
|
+
function unwrapChatList(data) {
|
|
102
|
+
let cur = data;
|
|
103
|
+
for (let depth = 0; depth < 3; depth++) {
|
|
104
|
+
if (!cur || typeof cur !== 'object' || Array.isArray(cur))
|
|
105
|
+
return cur;
|
|
106
|
+
const o = cur;
|
|
107
|
+
const inner = o.chats ?? o.list ?? o.items ?? o.data;
|
|
108
|
+
if (inner === undefined)
|
|
109
|
+
return cur;
|
|
110
|
+
cur = inner;
|
|
111
|
+
}
|
|
112
|
+
return cur;
|
|
113
|
+
}
|
|
94
114
|
export function parseQwenChatList(json) {
|
|
95
115
|
const root = json;
|
|
96
116
|
// A BARE array (no `data` wrapper) is the simplest shape the endpoint can
|
|
@@ -105,10 +125,7 @@ export function parseQwenChatList(json) {
|
|
|
105
125
|
? // A bare map keyed by chat id (the same convention as the history
|
|
106
126
|
// shape) has no `chats`/`list`/`items` wrapper: without this fallback
|
|
107
127
|
// a legitimate list was rejected and /chats printed "(none)".
|
|
108
|
-
(data
|
|
109
|
-
data.list ??
|
|
110
|
-
data.items ??
|
|
111
|
-
data)
|
|
128
|
+
unwrapChatList(data)
|
|
112
129
|
: null;
|
|
113
130
|
const keyed = Array.isArray(arr)
|
|
114
131
|
? null
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zames_pro",
|
|
3
|
-
"version": "2.82.
|
|
3
|
+
"version": "2.82.21",
|
|
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": {
|