zames_pro 2.73.1 → 2.73.2

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,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.73.2] - 2026-10-11
11
+
12
+ ### Changed
13
+
14
+ - docs(readme): document Qwen everywhere and refresh the diagram
15
+
10
16
  ## [2.73.1] - 2026-10-11
11
17
 
12
18
  ### Fixed
package/README.md CHANGED
@@ -63,27 +63,31 @@ zames does not call the model API. It launches a headless Chromium with a
63
63
  persistent profile, signs in to a chat web app like a human, types the task
64
64
  into the chat box, and reads the answer back.
65
65
 
66
- Two chat backends are available, switched with `/provider <deepseek|qwen>`
67
- (restart required): **DeepSeek** (`chat.deepseek.com`, the default) and
68
- **Qwen** (`chat.qwen.ai`). Each keeps its own persistent profile, so switching
69
- never signs the other one out.
66
+ Two chat backends are available, switched with `/provider <deepseek|qwen>`:
67
+ **DeepSeek** (`chat.deepseek.com`, the default) and **Qwen** (`chat.qwen.ai`).
68
+ The switch is **live** — zames closes the current backend and opens the other
69
+ one in place, no restart needed. Each keeps its own persistent profile
70
+ (`~/.zames/profile` and `~/.zames/qwen-profile`), so switching never signs the
71
+ other one out.
70
72
 
71
73
  <p align="center">
72
74
  <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/how-it-works.png" alt="how zames works" width="860">
73
75
  </p>
74
76
 
75
77
  In text: you type a task → zames sends the system prompt plus the task into
76
- the DeepSeek web chat → the model answers → zames parses the tool call, runs
77
- the tool locally, feeds the result back, and prints the final answer for you.
78
+ the active chat web app (DeepSeek or Qwen) → the model answers → zames parses
79
+ the tool call, runs the tool locally, feeds the result back, and prints the
80
+ final answer for you.
78
81
 
79
82
  Key pieces:
80
83
 
81
84
  - **The answer is read from the raw network stream** (SSE), not the rendered
82
85
  DOM, so tool-call JSON with template strings and escapes survives intact.
83
- - **A persistent profile** (`~/.zames/profile`) keeps you signed in; the
84
- headless User-Agent is patched so DeepSeek's CDN does not 403 the login.
85
- - **A send throttle** (15 s by default) keeps the web chat's rate limit happy
86
- during long tool-heavy runs.
86
+ - **A persistent per-provider profile** (`~/.zames/profile` for DeepSeek,
87
+ `~/.zames/qwen-profile` for Qwen) keeps you signed in; the headless
88
+ User-Agent is patched so the site's CDN does not 403 the login.
89
+ - **A send throttle** (15 s on DeepSeek, ~1 s on Qwen, which tolerates rapid
90
+ sends) keeps the web chat's rate limit happy during long tool-heavy runs.
87
91
  - **The agent is sandboxed** to the directory it was started in — no tool can
88
92
  read or write above it.
89
93
 
@@ -174,7 +178,7 @@ zames can drive either **DeepSeek** (`chat.deepseek.com`, the default) or
174
178
  **Qwen** (`chat.qwen.ai`):
175
179
 
176
180
  ```bash
177
- /provider qwen # switch to Qwen (persisted); restart zames to take effect
181
+ /provider qwen # switch to Qwen (persisted) — applied live, no restart
178
182
  /provider deepseek # switch back
179
183
  /provider status # show the active provider / model / login state
180
184
  /provider login # (re)run the sign-in check
@@ -184,15 +188,18 @@ zames can drive either **DeepSeek** (`chat.deepseek.com`, the default) or
184
188
 
185
189
  Notes:
186
190
 
187
- - The two backends use **separate persistent profiles**
188
- (`~/.zames/profile` for DeepSeek, `~/.zames/qwen-profile` for Qwen), so
189
- switching never signs the other one out. A provider switch takes effect on
190
- the next launch — the browser is created once at startup.
191
+ - The switch is **live**: zames closes the current backend and opens the other
192
+ one in place, so no restart is needed. The two backends use **separate
193
+ persistent profiles** (`~/.zames/profile` for DeepSeek, `~/.zames/qwen-profile`
194
+ for Qwen), so switching never signs the other one out.
195
+ - A chat id belongs to ONE backend, so the new provider opens a **fresh chat**.
196
+ If the previous chat had messages they are summarized and posted as a
197
+ handoff with the next task; an empty chat is switched silently.
191
198
  - Qwen works in **guest mode** without an account, but a guest is limited to a
192
199
  handful of messages per day; for long agent runs sign in (email / Google /
193
200
  GitHub — no phone required). zames auto-logins from the saved credentials or
194
201
  asks in the terminal, exactly like DeepSeek. `/model` changes the Qwen model
195
- at runtime (no restart).
202
+ at runtime.
196
203
  - File attachments on Qwen go through the mode menu's **Upload attachment**
197
204
  item; DeepSeek uses its own paperclip.
198
205
  - `/doctor` shows the active provider and the UI health of that provider's
@@ -343,9 +350,10 @@ Codex CLI:
343
350
  (zames-export-<stamp>.md by default).
344
351
  - /doctor — diagnose node, git, config, browser, clipboard, MCP and the
345
352
  active chat provider (it also reports that provider's UI health).
346
- - /provider <deepseek|qwen> — switch the chat backend (restart to apply);
347
- /provider status shows the active provider/model/login; /provider login
348
- re-runs the sign-in check. /model [id] lists or picks a Qwen model at runtime.
353
+ - /provider <deepseek|qwen> — switch the chat backend (applied live, no
354
+ restart); /provider status shows the active provider/model/login; /provider
355
+ login re-runs the sign-in check. /model [id] lists or picks a Qwen model at
356
+ runtime.
349
357
  - /add-dir <path> — validate an extra directory (the sandbox is fixed at
350
358
  startup; relaunch with --dir to write there).
351
359
  - /resume <n> (after /chats) and /resume-id <id> — open a chat and PRINT its
@@ -582,30 +590,33 @@ zames не вызывает API модели. Он запускает headless C
582
590
  профилем, входит в веб-чат как человек, печатает задачу в поле чата и читает
583
591
  ответ обратно.
584
592
 
585
- Доступны два бэкенда, переключаются командой `/provider <deepseek|qwen>`
586
- (нужен перезапуск): **DeepSeek** (`chat.deepseek.com`, по умолчанию) и
587
- **Qwen** (`chat.qwen.ai`). У каждого свой постоянный профиль, поэтому
588
- переключение не разлогинивает другой.
593
+ Доступны два бэкенда, переключаются командой `/provider <deepseek|qwen>`:
594
+ **DeepSeek** (`chat.deepseek.com`, по умолчанию) и **Qwen** (`chat.qwen.ai`).
595
+ Переключение **живое** — zames закрывает текущий бэкенд и открывает другой на
596
+ месте, без перезапуска. У каждого свой постоянный профиль
597
+ (`~/.zames/profile` и `~/.zames/qwen-profile`), поэтому переключение не
598
+ разлогинивает другой.
589
599
 
590
600
  <p align="center">
591
601
  <img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/how-it-works.png" alt="как работает zames" width="860">
592
602
  </p>
593
603
 
594
604
  Словами: вы вводите задачу → zames отправляет системный промпт и задачу в
595
- веб-чат DeepSeek → модель отвечает → zames разбирает вызов инструмента,
596
- выполняет его локально, возвращает результат обратно и печатает финальный
597
- ответ.
605
+ активный веб-чат (DeepSeek или Qwen) → модель отвечает → zames разбирает
606
+ вызов инструмента, выполняет его локально, возвращает результат обратно и
607
+ печатает финальный ответ.
598
608
 
599
609
  Ключевые детали:
600
610
 
601
611
  - **Ответ читается из сырого сетевого потока** (SSE), а не из отрендеренного
602
612
  DOM, поэтому JSON вызова инструмента с шаблонными строками и экранированием
603
613
  остаётся целым.
604
- - **Постоянный профиль** (`~/.zames/profile`) держит вас залогиненным;
605
- User-Agent headless-браузера подменяется, чтобы CDN DeepSeek не отдавал 403
606
- на вход.
607
- - **Троттлинг отправки** (15 с по умолчанию) щадит рейт-лимит веб-чата во
608
- время долгих прогонов с инструментами.
614
+ - **Постоянный профиль на каждого провайдера** (`~/.zames/profile` у DeepSeek,
615
+ `~/.zames/qwen-profile` у Qwen) держит вас залогиненным; User-Agent
616
+ headless-браузера подменяется, чтобы CDN сайта не отдавал 403 на вход.
617
+ - **Троттлинг отправки** (15 с у DeepSeek, ~1 с у Qwen, который спокойно
618
+ переносит частые отправки) щадит рейт-лимит веб-чата во время долгих
619
+ прогонов с инструментами.
609
620
  - **Агент запесочен** в директорию запуска — ни один инструмент не может
610
621
  читать или писать выше неё.
611
622
 
@@ -698,7 +709,7 @@ zames умеет работать с **DeepSeek** (`chat.deepseek.com`, по у
698
709
  **Qwen** (`chat.qwen.ai`):
699
710
 
700
711
  ```bash
701
- /provider qwen # переключиться на Qwen (сохраняется); нужен перезапуск
712
+ /provider qwen # переключиться на Qwen (сохраняется) — применяется сразу
702
713
  /provider deepseek # вернуться обратно
703
714
  /provider status # активный провайдер / модель / статус входа
704
715
  /provider login # повторно пройти проверку входа
@@ -708,15 +719,17 @@ zames умеет работать с **DeepSeek** (`chat.deepseek.com`, по у
708
719
 
709
720
  Замечания:
710
721
 
711
- - У бэкендов **разные постоянные профили** (`~/.zames/profile` у DeepSeek,
712
- `~/.zames/qwen-profile` у Qwen), поэтому переключение не разлогинивает
713
- другой. Смена провайдера применяется при следующем запуске — браузер
714
- создаётся один раз на старте.
722
+ - Переключение **живое**: zames закрывает текущий бэкенд и открывает другой на
723
+ месте, перезапуск не нужен. У бэкендов **разные постоянные профили**
724
+ (`~/.zames/profile` у DeepSeek, `~/.zames/qwen-profile` у Qwen), поэтому
725
+ переключение не разлогинивает другой.
726
+ - id чата принадлежит ОДНОМУ бэкенду, поэтому новый провайдер открывает
727
+ **свежий чат**. Если в прошлом чате были сообщения, они сжимаются и
728
+ подставляются как handoff в следующую задачу; пустой чат переключается молча.
715
729
  - Qwen работает в **гостевом режиме** без аккаунта, но гостю доступно всего
716
730
  несколько сообщений в день; для долгих прогонов войдите (email / Google /
717
731
  GitHub — телефон не нужен). zames сам логинится по сохранённым кредам или
718
- спросит в терминале, как и с DeepSeek. `/model` меняет модель Qwen на лету
719
- (без перезапуска).
732
+ спросит в терминале, как и с DeepSeek. `/model` меняет модель Qwen на лету.
720
733
  - Вложения в Qwen идут через пункт **Upload attachment** в меню режима; в
721
734
  DeepSeek — своя скрепка.
722
735
  - `/doctor` показывает активный провайдер и состояние UI его страницы.
@@ -872,9 +885,10 @@ zames --task "..." --output-format jsonl \
872
885
  (по умолчанию zames-export-<stamp>.md).
873
886
  - /doctor — диагностика node, git, конфига, браузера, буфера обмена, MCP и
874
887
  активного провайдера чата (плюс состояние UI его страницы).
875
- - /provider <deepseek|qwen> — сменить бэкенд чата (нужен перезапуск);
876
- /provider status показывает активный провайдер/модель/вход; /provider login
877
- повторно проверяет вход. /model [id] покажет или выберет модель Qwen на лету.
888
+ - /provider <deepseek|qwen> — сменить бэкенд чата (применяется сразу, без
889
+ перезапуска); /provider status показывает активный провайдер/модель/вход;
890
+ /provider login повторно проверяет вход. /model [id] покажет или выберет
891
+ модель Qwen на лету.
878
892
  - /add-dir <path> — проверить дополнительную директорию (песочница
879
893
  фиксируется при старте; для записи туда перезапустите с --dir).
880
894
  - /resume <n> (после /chats) и /resume-id <id> — открыть чат и НАПЕЧАТАТЬ его
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.73.1",
3
+ "version": "2.73.2",
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": {
@@ -35,6 +35,8 @@
35
35
  "self-smoke": "tsx scripts/self-smoke.mts",
36
36
  "qwen-smoke": "tsx scripts/qwen-smoke.mts",
37
37
  "render-demo": "tsx scripts/render-demo.mts",
38
+ "render-how": "tsx scripts/render-how-it-works.mts",
39
+ "render-how": "tsx scripts/render-how-it-works.mts",
38
40
  "build:readme": "tsx scripts/build-readme.mts",
39
41
  "postinstall": "node scripts/postinstall.mjs",
40
42
  "prepare": "husky"
@@ -0,0 +1,129 @@
1
+ // Render docs/how-it-works.png — the architecture diagram used in README.md.
2
+ //
3
+ // Why a generator: the README must show BOTH chat backends (DeepSeek and
4
+ // Qwen), not just DeepSeek. A hand-drawn PNG drifts; this renders a fixed
5
+ // HTML page with headless Chromium so the diagram is reproducible and easy to
6
+ // update when a provider is added.
7
+ //
8
+ // Run: npm run render-how (tsx scripts/render-how-it-works.mts)
9
+ //
10
+ // Isolation: chromium.launch() uses a THROWAWAY in-memory context, never
11
+ // ~/.zames/profile (see AGENTS.md — never touch the live agent's browser).
12
+
13
+ import { chromium } from 'playwright'
14
+ import path from 'node:path'
15
+ import { fileURLToPath } from 'node:url'
16
+
17
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
18
+ const out = path.join(root, 'docs', 'how-it-works.png')
19
+
20
+ const C = {
21
+ bg: '#23272e',
22
+ panel: '#2b303a',
23
+ border: '#3b4250',
24
+ text: '#cfc9b0',
25
+ dim: '#8a9bb5',
26
+ user: '#b4b8d0',
27
+ accent: '#7fc4f0',
28
+ ds: '#6f8ed0',
29
+ qwen: '#6fd0b0',
30
+ tool: '#c6a97e',
31
+ }
32
+
33
+ const W = 1300
34
+ const H = 360
35
+
36
+ const box = (
37
+ title: string,
38
+ sub: string,
39
+ color: string,
40
+ ): string =>
41
+ '<div class="box" style="border-color:' +
42
+ color +
43
+ '">' +
44
+ '<div class="box-t" style="color:' +
45
+ color +
46
+ '">' +
47
+ title +
48
+ '</div>' +
49
+ '<div class="box-s">' +
50
+ sub +
51
+ '</div></div>'
52
+
53
+ const html =
54
+ '<!doctype html><html><head><meta charset="utf-8"><style>' +
55
+ '@font-face{font-family:ZM;src:local("DejaVu Sans Mono")}' +
56
+ 'html,body{margin:0;padding:0;background:' +
57
+ C.bg +
58
+ '}' +
59
+ 'body{font-family:"DejaVu Sans Mono",monospace;color:' +
60
+ C.text +
61
+ ';-webkit-font-smoothing:antialiased}' +
62
+ '.wrap{box-sizing:border-box;width:' +
63
+ W +
64
+ 'px;height:' +
65
+ H +
66
+ 'px;padding:26px 30px}' +
67
+ '.row{display:flex;align-items:center;justify-content:space-between;gap:8px}' +
68
+ '.box{box-sizing:border-box;border:2px solid;border-radius:10px;padding:14px 16px;' +
69
+ 'background:' +
70
+ C.panel +
71
+ ';min-width:150px;text-align:center}' +
72
+ '.box-t{font-size:18px;font-weight:700;margin-bottom:6px}' +
73
+ '.box-s{font-size:12px;color:' +
74
+ C.dim +
75
+ ';line-height:1.5}' +
76
+ '.arrow{font-size:26px;color:' +
77
+ C.dim +
78
+ '}' +
79
+ '.flow-label{font-size:12px;color:' +
80
+ C.dim +
81
+ ';text-align:center;margin-top:4px}' +
82
+ '.providers{display:flex;flex-direction:column;gap:10px}' +
83
+ '.col{display:flex;flex-direction:column;align-items:center;gap:4px}' +
84
+ '.legend{margin-top:20px;font-size:12px;color:' +
85
+ C.dim +
86
+ ';text-align:center}' +
87
+ '.legend b{color:' +
88
+ C.text +
89
+ '}' +
90
+ '</style></head><body><div class="wrap">' +
91
+ '<div class="row">' +
92
+ // left: the operator
93
+ '<div class="col">' +
94
+ box('Operator', 'terminal task<br/>+ tool approval', C.user) +
95
+ '<div class="flow-label">types a task</div>' +
96
+ '</div>' +
97
+ '<div class="arrow">&#8594;</div>' +
98
+ // middle: zames
99
+ '<div class="col">' +
100
+ box(
101
+ 'zames',
102
+ 'sandboxed tools<br/>parses tool-calls<br/>runs them locally',
103
+ C.accent,
104
+ ) +
105
+ '<div class="flow-label">system prompt + task</div>' +
106
+ '</div>' +
107
+ '<div class="arrow">&#8644;</div>' +
108
+ // right: the two backends
109
+ '<div class="providers">' +
110
+ box('DeepSeek', 'chat.deepseek.com<br/>~/.zames/profile', C.ds) +
111
+ box('Qwen', 'chat.qwen.ai<br/>~/.zames/qwen-profile', C.qwen) +
112
+ '</div>' +
113
+ '</div>' +
114
+ '<div class="legend">zames drives a <b>real browser</b> over a persistent per-provider profile &mdash; no API key. ' +
115
+ 'Switch live with <b>/provider &lt;deepseek|qwen&gt;</b> (each chat id belongs to one backend).</div>' +
116
+ '</div></body></html>'
117
+
118
+ const browser = await chromium.launch({ headless: true })
119
+ try {
120
+ const page = await browser.newPage({
121
+ viewport: { width: W, height: H },
122
+ deviceScaleFactor: 2,
123
+ })
124
+ await page.setContent(html, { waitUntil: 'load' })
125
+ await page.screenshot({ path: out })
126
+ console.log('wrote', path.relative(root, out))
127
+ } finally {
128
+ await browser.close()
129
+ }