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 +6 -0
- package/README.md +55 -41
- package/package.json +3 -1
- package/scripts/render-how-it-works.mts +129 -0
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
|
-
|
|
68
|
-
**
|
|
69
|
-
|
|
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
|
|
77
|
-
the tool locally, feeds the result back, and prints the
|
|
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`
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
|
|
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)
|
|
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
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
|
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 (
|
|
347
|
-
/provider status shows the active provider/model/login; /provider
|
|
348
|
-
re-runs the sign-in check. /model [id] lists or picks a Qwen model at
|
|
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
|
-
|
|
587
|
-
|
|
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
|
-
- **Постоянный
|
|
605
|
-
|
|
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
|
-
-
|
|
712
|
-
|
|
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 показывает активный провайдер/модель/вход;
|
|
877
|
-
повторно проверяет вход. /model [id] покажет или выберет
|
|
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.
|
|
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">→</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">⇄</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 — no API key. ' +
|
|
115
|
+
'Switch live with <b>/provider <deepseek|qwen></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
|
+
}
|