zames_pro 2.82.9 → 2.82.13

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,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.82.13] - 2026-10-22
11
+
12
+ ### Fixed
13
+
14
+ - **qwen:** parse a bare-array history reply on resume
15
+
16
+ ## [2.82.12] - 2026-10-22
17
+
18
+ ### Fixed
19
+
20
+ - **qwen:** find an answer nested in a JSON envelope
21
+
22
+ ## [2.82.11] - 2026-10-22
23
+
24
+ ### Fixed
25
+
26
+ - **commands:** advertise /limits in the slash-command hints
27
+
28
+ ## [2.82.10] - 2026-10-22
29
+
30
+ ### Fixed
31
+
32
+ - **glm:** unwrap the chat:completion envelope in a non-streamed JSON reply
33
+
10
34
  ## [2.82.9] - 2026-10-22
11
35
 
12
36
  ### Fixed
package/dist/commands.js CHANGED
@@ -1117,6 +1117,7 @@ export const SLASH_COMMANDS = [
1117
1117
  { name: '/diff', key: 'help.cmd.diff' },
1118
1118
  { name: '/diffstat', key: 'help.cmd.diffstat' },
1119
1119
  { name: '/cost', key: 'help.cmd.cost' },
1120
+ { name: '/limits', key: 'help.cmd.limits' },
1120
1121
  { name: '/export', key: 'help.cmd.export' },
1121
1122
  { name: '/doctor', key: 'help.cmd.doctor' },
1122
1123
  { name: '/add-dir', key: 'help.cmd.add_dir' },
@@ -130,6 +130,14 @@ function pickAnswer(node) {
130
130
  }
131
131
  if (typeof obj.delta_content === 'string')
132
132
  return obj.delta_content;
133
+ // A non-streamed reply carries the SAME `chat:completion` envelope as the
134
+ // SSE stream: the answer lives in `data.delta_content`, so the envelope must
135
+ // be unwrapped or the whole reply reads as empty.
136
+ if (obj.data && typeof obj.data === 'object') {
137
+ const inner = pickAnswer(obj.data);
138
+ if (inner)
139
+ return inner;
140
+ }
133
141
  if (Array.isArray(obj.choices)) {
134
142
  let out = '';
135
143
  for (const ch of obj.choices) {
@@ -151,7 +151,12 @@ export function parseQwenChatList(json) {
151
151
  */
152
152
  export function parseQwenHistory(json) {
153
153
  const root = json;
154
- const data = root && typeof root === 'object' ? root.data : null;
154
+ // A BARE array (no `data` wrapper) and a top-level `messages` are the same
155
+ // simple shapes the chat-LIST endpoint returns: reading only `root.data`
156
+ // made /resume print nothing for a payload that DID carry the dialogue.
157
+ const data = Array.isArray(json) || root === null || typeof root !== 'object'
158
+ ? json
159
+ : (root.data ?? (root.messages ? { messages: root.messages } : null));
155
160
  // The REAL shape (verified live) is a MAP, not an array:
156
161
  // data.chat.history.messages = { <id>: { role, content, timestamp, ... } }
157
162
  // An array is accepted too (older shape).
@@ -122,6 +122,16 @@ function pickAnswer(node) {
122
122
  if (typeof v === 'string' && v)
123
123
  return v;
124
124
  }
125
+ // A wrapper envelope (`{data:{…}}`, `{response:{…}}`) keeps the answer one
126
+ // level deeper; without this the whole reply reads as empty.
127
+ for (const key of ['data', 'response', 'result']) {
128
+ const v = obj[key];
129
+ if (v && typeof v === 'object') {
130
+ const inner = pickAnswer(v);
131
+ if (inner)
132
+ return inner;
133
+ }
134
+ }
125
135
  return '';
126
136
  }
127
137
  // A universal attempt: first SSE, then regular JSON.
@@ -227,7 +237,20 @@ export function isRateLimitText(body) {
227
237
  }
228
238
  // True when the body carries actual answer text in an SSE/JSON chunk.
229
239
  function hasAnswerContent(body) {
230
- for (const obj of parseDataLines(body)) {
240
+ const b = String(body || '');
241
+ // A NON-streamed body is a single JSON object with no `data:` lines; the
242
+ // answer may sit in a wrapper (`{data:{content}}`). Without this check the
243
+ // answer was invisible here and a rate-limit/busy phrase elsewhere in the
244
+ // SAME body (the model may quote the notice) made ask() back off.
245
+ if (!b.split(NL).some((l) => l.trim().startsWith('data:'))) {
246
+ try {
247
+ const parsed = JSON.parse(b);
248
+ if (pickAnswer(parsed).trim())
249
+ return true;
250
+ }
251
+ catch { }
252
+ }
253
+ for (const obj of parseDataLines(b)) {
231
254
  const choices = obj.choices;
232
255
  if (!Array.isArray(choices))
233
256
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.82.9",
3
+ "version": "2.82.13",
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": {