zames_pro 2.66.0 → 2.67.0
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 +189 -106
- package/README.md +484 -0
- package/README.ru.md +469 -0
- package/dist/attachments.js +0 -17
- package/dist/context.js +0 -3
- package/dist/extraTools.js +10 -11
- package/dist/fsutil.js +38 -1
- package/dist/gitTools.js +83 -26
- package/dist/index.js +18 -18
- package/dist/input.js +134 -30
- package/dist/mcp.js +49 -10
- package/dist/permissions.js +40 -1
- package/dist/run-task.js +6 -0
- package/dist/sandbox.js +49 -0
- package/dist/scheduler.js +8 -1
- package/dist/self-review.js +37 -17
- package/dist/shell.js +74 -32
- package/dist/tools.js +40 -20
- package/dist/transcript.js +15 -2
- package/dist/web.js +73 -33
- package/package.json +2 -1
- package/scripts/build-readme.mts +129 -0
- package/scripts/coverage-gate.mjs +4 -0
- package/scripts/release.mts +12 -1
package/README.ru.md
CHANGED
|
@@ -500,3 +500,472 @@ first-party API-клиент.
|
|
|
500
500
|
## Лицензия
|
|
501
501
|
|
|
502
502
|
MIT
|
|
503
|
+
|
|
504
|
+
<details>
|
|
505
|
+
<summary>🇬🇧 Read in English</summary>
|
|
506
|
+
|
|
507
|
+
A terminal coding agent that works on top of [chat.deepseek.com](https://chat.deepseek.com/) through Playwright.
|
|
508
|
+
In spirit it is similar to Claude Code / Codex CLI: it starts in the current
|
|
509
|
+
directory, reads and edits files, runs commands, and commits to git.
|
|
510
|
+
|
|
511
|
+
> No API key required — it drives the DeepSeek web chat like a regular user
|
|
512
|
+
> through a real (headless) browser.
|
|
513
|
+
|
|
514
|
+
<p align="center">
|
|
515
|
+
<img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/demo.png" alt="zames session in the terminal" width="860">
|
|
516
|
+
</p>
|
|
517
|
+
|
|
518
|
+
## Quick start
|
|
519
|
+
|
|
520
|
+
```bash
|
|
521
|
+
npm install -g zames_pro # Chromium for Playwright is downloaded automatically
|
|
522
|
+
cd your-project # any folder the agent should work in
|
|
523
|
+
zames # sign in once, then describe your task
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
There is **no API key and no per-token bill**: zames signs in to **your own
|
|
527
|
+
[chat.deepseek.com](https://chat.deepseek.com/) account** in a real (headless)
|
|
528
|
+
Chromium and drives the web chat like a regular user. The first launch asks for
|
|
529
|
+
your DeepSeek login once (the session is stored in `~/.zames/profile`); after
|
|
530
|
+
that just run `zames` and type a task in plain language:
|
|
531
|
+
|
|
532
|
+
```text
|
|
533
|
+
❯ refactor the config loader and add a test for the new default
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
While the agent works you can keep typing — a message sent mid-task is queued
|
|
537
|
+
and runs right after it, in the same chat. `Esc` aborts the current generation,
|
|
538
|
+
`/help` lists commands, `/exit` quits.
|
|
539
|
+
|
|
540
|
+
## How it works
|
|
541
|
+
|
|
542
|
+
zames does not call the model API. It launches a headless Chromium with a
|
|
543
|
+
persistent profile, signs in to `chat.deepseek.com` like a human, types the task
|
|
544
|
+
into the chat box, and reads the answer back.
|
|
545
|
+
|
|
546
|
+
<p align="center">
|
|
547
|
+
<img src="https://raw.githubusercontent.com/Viqto0r/zames_pro/master/docs/how-it-works.png" alt="how zames works" width="860">
|
|
548
|
+
</p>
|
|
549
|
+
|
|
550
|
+
In text: you type a task → zames sends the system prompt plus the task into
|
|
551
|
+
the DeepSeek web chat → the model answers → zames parses the tool call, runs
|
|
552
|
+
the tool locally, feeds the result back, and prints the final answer for you.
|
|
553
|
+
|
|
554
|
+
Key pieces:
|
|
555
|
+
|
|
556
|
+
- **The answer is read from the raw network stream** (SSE), not the rendered
|
|
557
|
+
DOM, so tool-call JSON with template strings and escapes survives intact.
|
|
558
|
+
- **A persistent profile** (`~/.zames/profile`) keeps you signed in; the
|
|
559
|
+
headless User-Agent is patched so DeepSeek's CDN does not 403 the login.
|
|
560
|
+
- **A send throttle** (15 s by default) keeps the web chat's rate limit happy
|
|
561
|
+
during long tool-heavy runs.
|
|
562
|
+
- **The agent is sandboxed** to the directory it was started in — no tool can
|
|
563
|
+
read or write above it.
|
|
564
|
+
|
|
565
|
+
## Table of contents
|
|
566
|
+
|
|
567
|
+
- [Quick start](#quick-start) · [Features](#features) · [Why zames?](#why-zames) · [Requirements](#requirements)
|
|
568
|
+
- [How it works](#how-it-works) · [Installation](#installation) · [Signing in](#signing-in) · [Usage](#usage)
|
|
569
|
+
- [Tools](#tools) · [Slash commands](#slash-commands)
|
|
570
|
+
- [Project context, skills and memory](#project-context-skills-and-memory) · [MCP (external tools)](#mcp-external-tools) · [Configuration](#configuration)
|
|
571
|
+
- [FAQ](#faq) · [Links](#links) · [License](#license)
|
|
572
|
+
|
|
573
|
+
## Features
|
|
574
|
+
|
|
575
|
+
- **Tools like Claude Code / Codex** — `Read`, `Write`, `Edit`, `Bash`,
|
|
576
|
+
`Glob`, `Grep`, plus `MultiEdit`, `ApplyPatch`, `LS`, `TodoWrite`, git and web
|
|
577
|
+
tools. Every edit is backed by `/undo`.
|
|
578
|
+
- **Runs while you keep typing** — queue messages during a task; they run right
|
|
579
|
+
after it, in the same chat (like typing during generation on the web).
|
|
580
|
+
- **Plan mode** — `/plan` (or `--plan`) drops all mutating tools, so the agent
|
|
581
|
+
can investigate the code without touching the tree.
|
|
582
|
+
- **Project context** — reads `AGENTS.md`, `MEMORY.md`, skills (`SKILL.md`) and
|
|
583
|
+
custom commands from the repo and `~/.zames`, the same idea as Codex / Claude
|
|
584
|
+
Code.
|
|
585
|
+
- **MCP support** — plug in external tool servers (e.g. `@playwright/mcp`).
|
|
586
|
+
- **Scheduling** — `/loop`, `/cron` and `/jobs` repeat tasks on a timer.
|
|
587
|
+
- **Bilingual UI** — Russian / English (`/config lang`).
|
|
588
|
+
|
|
589
|
+
## Why zames?
|
|
590
|
+
|
|
591
|
+
- **No API key, no per-token bill** — it uses your own DeepSeek chat account,
|
|
592
|
+
not the paid API. Good for long, tool-heavy tasks.
|
|
593
|
+
- **Same workflow as Claude Code / Codex** — tools, `AGENTS.md`, skills, MCP
|
|
594
|
+
and slash commands, so it feels familiar from day one.
|
|
595
|
+
- **Runs unattended** — headless by default, resumable sessions, and `/loop`
|
|
596
|
+
plus `/cron` for scheduled work.
|
|
597
|
+
- **Local-first** — the browser profile, credentials and logs never leave your
|
|
598
|
+
machine, and the agent is sandboxed to the project directory.
|
|
599
|
+
|
|
600
|
+
## Requirements
|
|
601
|
+
|
|
602
|
+
- Node.js >= 20
|
|
603
|
+
- A DeepSeek account. On first launch zames asks for your DeepSeek
|
|
604
|
+
login/password in the terminal (and stores them in `~/.zames/config.json`
|
|
605
|
+
after a successful sign-in, so a later logout is handled automatically
|
|
606
|
+
without asking you again). You can also sign in manually in the browser
|
|
607
|
+
window when the browser is headed.
|
|
608
|
+
|
|
609
|
+
## Signing in
|
|
610
|
+
|
|
611
|
+
The browser runs **headless by default**. When DeepSeek requires a sign-in,
|
|
612
|
+
zames:
|
|
613
|
+
|
|
614
|
+
1. reuses the session stored in the persistent profile (`~/.zames/profile`)
|
|
615
|
+
if it is still valid;
|
|
616
|
+
2. otherwise signs in automatically with the saved credentials
|
|
617
|
+
(`browser.auth.username` / `browser.auth.password`);
|
|
618
|
+
3. otherwise asks you for the login/password in the terminal (in a TTY) and,
|
|
619
|
+
after a successful sign-in, remembers them for next time;
|
|
620
|
+
4. otherwise falls back to a manual sign-in hint.
|
|
621
|
+
|
|
622
|
+
To sign in by hand (for example, if DeepSeek shows a captcha), run with a
|
|
623
|
+
visible window:
|
|
624
|
+
|
|
625
|
+
```bash
|
|
626
|
+
zames --headed
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
The `--headless` flag (the default) and `headless: true` in the config keep
|
|
630
|
+
the browser without a window; `--headed` / `headless: false` show it.
|
|
631
|
+
|
|
632
|
+
Headless works out of the box: a headless Chrome normally advertises a
|
|
633
|
+
`HeadlessChrome/...` User-Agent that DeepSeek's CDN blocks with a 403, so
|
|
634
|
+
zames strips that marker before loading the page (keeping the real engine
|
|
635
|
+
version). You do not need `--headed` just to log in.
|
|
636
|
+
|
|
637
|
+
Credentials and toggles can also be edited from `/config`
|
|
638
|
+
(`browser.auth.username`, `browser.auth.password`, `browser.auth.saveSession`).
|
|
639
|
+
|
|
640
|
+
## Installation
|
|
641
|
+
|
|
642
|
+
```bash
|
|
643
|
+
npm install -g zames_pro
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
Chromium for Playwright is downloaded automatically on install. On Linux/WSL
|
|
647
|
+
the required system libraries are installed too when passwordless `sudo` is
|
|
648
|
+
available; otherwise run once by hand:
|
|
649
|
+
|
|
650
|
+
```bash
|
|
651
|
+
npx playwright install chromium
|
|
652
|
+
sudo npx playwright install-deps chromium
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
## Usage
|
|
656
|
+
|
|
657
|
+
Go to your project folder and run:
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
zames
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
The agent works inside the directory it was started in and cannot leave it (sandbox).
|
|
664
|
+
|
|
665
|
+
While the agent is working you can keep typing: press Enter to queue a message
|
|
666
|
+
(it is sent right after the current task, in the same chat), or Esc / Ctrl+C to
|
|
667
|
+
abort the current generation. This mirrors typing during generation on the
|
|
668
|
+
DeepSeek website.
|
|
669
|
+
|
|
670
|
+
### Input line
|
|
671
|
+
|
|
672
|
+
The prompt is a small line editor with persistent history:
|
|
673
|
+
|
|
674
|
+
- `↑` / `↓` — walk the message history (saved in `~/.zames/history.json`, so it
|
|
675
|
+
survives a restart); inside a multiline message the arrows move between lines.
|
|
676
|
+
- `Ctrl+R` — incremental reverse search over the history (bash-style): type to
|
|
677
|
+
filter, `Ctrl+R` for older matches, `Enter` to accept, `Esc` to cancel.
|
|
678
|
+
- `Ctrl+_` — undo the last edit in the input line (a fat-fingered `Ctrl+U` /
|
|
679
|
+
`Ctrl+K` is recoverable).
|
|
680
|
+
- `Ctrl+U` — clear the line, `Ctrl+K` — delete to end of line, `Ctrl+W` —
|
|
681
|
+
delete the word before the cursor, `Ctrl+←`/`Ctrl+→` — move by words.
|
|
682
|
+
- `\` + `Enter`, `Ctrl+J`, `Ctrl+Enter` or `Shift+Enter` — insert a newline.
|
|
683
|
+
- `/` + `Tab` — slash-command hints and completion.
|
|
684
|
+
- `!command` — run a shell command directly, bypassing the model (like
|
|
685
|
+
Claude Code's bash mode). The same sandbox guard as the `Bash` tool applies,
|
|
686
|
+
so a direct command cannot leave the project either.
|
|
687
|
+
|
|
688
|
+
Set `NO_COLOR=1` to disable colors (a calm default palette is used otherwise).
|
|
689
|
+
|
|
690
|
+
### Images and files
|
|
691
|
+
|
|
692
|
+
You can paste an image or a file into the input line (Ctrl+Shift+V / Shift+Insert
|
|
693
|
+
or the terminal's own paste). zames saves it under `<project>/tmp` and shows a
|
|
694
|
+
marker in the line - `[image#1]` for images, `[file#1]` for other files - then
|
|
695
|
+
uploads the real file to the chat together with your message. These are the
|
|
696
|
+
same formats the DeepSeek web chat accepts (PNG, JPEG, GIF, WEBP, BMP, SVG and
|
|
697
|
+
the usual document types).
|
|
698
|
+
|
|
699
|
+
Pasting an image works when the terminal sends it as a `data:` URL or as a
|
|
700
|
+
base64 blob with a recognizable image signature. You can also paste a path to a
|
|
701
|
+
local file (drag a file into the terminal or copy its path); if the file exists
|
|
702
|
+
it is attached, otherwise the text is inserted as usual.
|
|
703
|
+
|
|
704
|
+
Press Ctrl+V (or use an empty paste) and zames reads the image straight from
|
|
705
|
+
the clipboard: Linux via wl-paste (Wayland) or xclip/xsel (X11), macOS
|
|
706
|
+
via pngpaste, Windows via PowerShell. The needed Linux tools are installed
|
|
707
|
+
automatically on npm install (best-effort, through the detected package
|
|
708
|
+
manager). If no image is found, zames says so and reports which tool it tried,
|
|
709
|
+
instead of staying silent.
|
|
710
|
+
|
|
711
|
+
### Options
|
|
712
|
+
|
|
713
|
+
```
|
|
714
|
+
zames --task <task text>
|
|
715
|
+
zames --chat <id>
|
|
716
|
+
zames --new-chat
|
|
717
|
+
zames --resend-prompt
|
|
718
|
+
zames --dir <path>
|
|
719
|
+
zames --headless
|
|
720
|
+
zames --headed
|
|
721
|
+
zames --plan
|
|
722
|
+
zames --output-format jsonl
|
|
723
|
+
zames --debug
|
|
724
|
+
zames --version
|
|
725
|
+
zames --help
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
### Machine-readable output (scripts / CI)
|
|
729
|
+
|
|
730
|
+
For one-shot runs (`--task`) the agent can emit its event stream as JSON lines
|
|
731
|
+
on stdout, keeping all human text on stderr:
|
|
732
|
+
|
|
733
|
+
```bash
|
|
734
|
+
zames --task "summarize the diff" --output-format jsonl
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
Each line is one event (`tool_call`, `tool_result`, `assistant_final`, ...), so
|
|
738
|
+
it pipes straight into `jq`:
|
|
739
|
+
|
|
740
|
+
```bash
|
|
741
|
+
zames --task "..." --output-format jsonl \
|
|
742
|
+
| jq -r 'select(.type=="assistant_final") | .message'
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
## Tools
|
|
746
|
+
|
|
747
|
+
The agent has the same style of tools as Claude Code / Codex CLI:
|
|
748
|
+
|
|
749
|
+
- **File tools** — `Read`, `Write`, `Edit`, `Bash`, `Glob`, `Grep`. `Read`
|
|
750
|
+
returns raw content by default; pass `numbered=true` to get `cat -n`-style
|
|
751
|
+
line numbers (for reference only — do not paste them into `Edit`).
|
|
752
|
+
- **Extra tools** — `LS` (list a directory), `MultiEdit` (several edits to one
|
|
753
|
+
file applied atomically), `TodoWrite` (session task checklist), `ApplyPatch`
|
|
754
|
+
(multi-file patch in Codex's V4A format: `*** Begin Patch` … `*** End Patch`).
|
|
755
|
+
- **Git** — `GitStatus`, `GitDiff`, `GitLog`, `GitShow`, `GitBranchList`,
|
|
756
|
+
`GitAdd`, `GitCommit`, `GitPush`.
|
|
757
|
+
- **Web** — `WebFetch`, `WebSearch`.
|
|
758
|
+
- **Service** — `respond` (final answer to the operator, ends the task).
|
|
759
|
+
|
|
760
|
+
All file tools stay inside the working directory (sandbox). `Write`/`Edit` and
|
|
761
|
+
`MultiEdit`/`ApplyPatch` make a backup (undo) before touching a file.
|
|
762
|
+
|
|
763
|
+
## Slash commands
|
|
764
|
+
|
|
765
|
+
Type / in the prompt for hints (Tab completes). Besides the session and
|
|
766
|
+
config commands (/new, /chats, /resume, /cd, /status, /config,
|
|
767
|
+
/undo, /transcript, /mcp, /skills, /memory, /init, /reload,
|
|
768
|
+
/debug-dom, /help, /exit) there are a few that mirror Claude Code /
|
|
769
|
+
Codex CLI:
|
|
770
|
+
|
|
771
|
+
- /diff [--staged] — show the working-tree git diff (--staged for the index).
|
|
772
|
+
- /diffstat — a one-line change summary (`git diff --stat`).
|
|
773
|
+
- /context — show what is loaded into the prompt (AGENTS.md, MEMORY.md,
|
|
774
|
+
skills, custom commands) and the system-prompt size.
|
|
775
|
+
- /retry — resend the last task into the same chat (handy after a truncated
|
|
776
|
+
or empty answer).
|
|
777
|
+
- /rename <title> — set the current session title (shown in /sessions).
|
|
778
|
+
- /copy — copy the last assistant answer to the OS clipboard.
|
|
779
|
+
- /cost (alias /usage) — session stats: tasks, tool calls, duration, and the
|
|
780
|
+
context size in tokens (DeepSeek's `accumulated_token_usage`).
|
|
781
|
+
- /export [file] — write the session transcript to a Markdown file
|
|
782
|
+
(zames-export-<stamp>.md by default).
|
|
783
|
+
- /doctor — diagnose node, git, config, browser, clipboard and MCP.
|
|
784
|
+
- /add-dir <path> — validate an extra directory (the sandbox is fixed at
|
|
785
|
+
startup; relaunch with --dir to write there).
|
|
786
|
+
- /resume <n> (after /chats) and /resume-id <id> — open a chat and PRINT its
|
|
787
|
+
dialogue into the terminal, so the restored context is visible. Only the
|
|
788
|
+
last 20 messages are shown (`RESTORED_HISTORY_LIMIT`). /last reopens the last
|
|
789
|
+
chat of the current directory with no lookup step; /sessions shows the saved
|
|
790
|
+
sessions with their relative age.
|
|
791
|
+
- /help <command> — the full description of a single command (e.g. `/help diff`)
|
|
792
|
+
instead of the whole list.
|
|
793
|
+
- /review [focus] [--staged] — ask the agent to review uncommitted changes
|
|
794
|
+
and report findings (no code changes).
|
|
795
|
+
- /plan [on|off] — plan (read-only) mode. While it is on, the mutating tools
|
|
796
|
+
(Write/Edit/MultiEdit/ApplyPatch/Bash, GitAdd/GitCommit/GitPush) are removed
|
|
797
|
+
from the tool set, so the agent can investigate without touching the tree.
|
|
798
|
+
Start in it with `--plan`.
|
|
799
|
+
- /compact — ask DeepSeek to compress the current chat into a handover
|
|
800
|
+
summary, then open a NEW chat, resend the system prompt and post the summary
|
|
801
|
+
as the carried-over context. Use it when the context gets long.
|
|
802
|
+
- /goal [text|clear] — set a long-lived session goal. It is prepended to every
|
|
803
|
+
task message, so the model keeps the big picture across many turns. Stored in
|
|
804
|
+
`<project>/.zames-goal` (git-ignored) and restored on the next launch.
|
|
805
|
+
- /loop <interval> <task> — repeat a task periodically (e.g. `/loop 10m run the
|
|
806
|
+
tests`). /cron "<min> <hour> <dom> <month> <dow>" <task> — run on a schedule.
|
|
807
|
+
/jobs [rm <id>|clear] lists and stops them. A fired job is put into the same
|
|
808
|
+
message queue you type into, so it runs when the agent is free (never mid-
|
|
809
|
+
generation) and still respects the send throttle.
|
|
810
|
+
- /thinking [on|off] and /web [on|off] — toggle Deep thinking / Smart search.
|
|
811
|
+
These (and /queue, /jobs, /goal, `/config <sub>`) can be used WHILE the agent
|
|
812
|
+
is working — they do not touch the in-flight generation.
|
|
813
|
+
- /queue [clear] — list or clear the messages waiting to be sent after the
|
|
814
|
+
current task.
|
|
815
|
+
|
|
816
|
+
The token context is also shown live: the status line above the input has the
|
|
817
|
+
spinner/text on the left and the context on the right (e.g. `125k · 13%`,
|
|
818
|
+
percent of a 1M context). It is COLORED by fill level: green below 50%,
|
|
819
|
+
yellow 50-80%, red above 80%. It comes from DeepSeek's
|
|
820
|
+
`accumulated_token_usage` and is hidden until the first answer delivers it.
|
|
821
|
+
|
|
822
|
+
## Project context, skills and memory
|
|
823
|
+
|
|
824
|
+
Like Codex / Claude Code, zames reads project instructions and reusable
|
|
825
|
+
workflows from your repository and from `~/.zames`.
|
|
826
|
+
|
|
827
|
+
- **AGENTS.md** — project instructions. Put one in the repo root (or in any
|
|
828
|
+
parent folder of the working directory). Global instructions live in
|
|
829
|
+
`~/.zames/AGENTS.md` (and `~/.claude/CLAUDE.md`). Run `/init` and the agent
|
|
830
|
+
will explore the project and write an AGENTS.md based on the real build/test
|
|
831
|
+
commands and conventions (use `/init --force` to overwrite an existing file).
|
|
832
|
+
- **MEMORY.md** — durable notes that persist between sessions. The agent
|
|
833
|
+
appends useful facts here; you can edit it by hand, or add one from the
|
|
834
|
+
prompt with `/remember <text>`.
|
|
835
|
+
- **Skills** — a folder with a `SKILL.md` file (YAML frontmatter: `name`,
|
|
836
|
+
`description`, optional `allowed-tools`, `user-invokable`) plus any helper
|
|
837
|
+
files. Discovered under `.zames/skills/`, `.claude/skills/`,
|
|
838
|
+
`.agents/skills/`, `skills/`, and `~/.zames/skills/`. The agent reads the
|
|
839
|
+
body only when a task matches the description. List them with `/skills`;
|
|
840
|
+
invoke one with `/<skill-name>`.
|
|
841
|
+
- **Custom commands** — `.md` files under `.zames/commands/` (or
|
|
842
|
+
`.claude/commands/`). They support `$ARGUMENTS` / `{{args}}` placeholders and
|
|
843
|
+
are invoked with `/<command-name>`.
|
|
844
|
+
|
|
845
|
+
Skills and custom commands show up in the «/» completion list and in `/help`.
|
|
846
|
+
|
|
847
|
+
```
|
|
848
|
+
/skills list discovered skills
|
|
849
|
+
/memory show AGENTS.md / MEMORY.md in effect
|
|
850
|
+
/remember <text> append a durable note to MEMORY.md
|
|
851
|
+
/init [--force] analyze the project and create AGENTS.md
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
## MCP (external tools)
|
|
855
|
+
|
|
856
|
+
zames can use tools from [MCP](https://modelcontextprotocol.io) servers.
|
|
857
|
+
The flagship example is @playwright/mcp: it gives the agent a real browser
|
|
858
|
+
(navigate, click, snapshot, type, ...) on top of the one zames already uses
|
|
859
|
+
for the DeepSeek chat.
|
|
860
|
+
|
|
861
|
+
Drop a config file (same shape as Claude Code / Cursor):
|
|
862
|
+
|
|
863
|
+
- `~/.zames/mcp.json` - global
|
|
864
|
+
- `<project>/.zames/mcp.json` - project-scoped (later files win)
|
|
865
|
+
- `<project>/.mcp.json` - the common MCP name
|
|
866
|
+
|
|
867
|
+
```json
|
|
868
|
+
{
|
|
869
|
+
"mcpServers": {
|
|
870
|
+
"playwright": {
|
|
871
|
+
"command": "npx",
|
|
872
|
+
"args": ["-y", "@playwright/mcp@latest", "--headless", "--isolated"]
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
IMPORTANT: keep the MCP browser isolated. @playwright/mcp defaults to the
|
|
879
|
+
SAME profile directory as zames (~/.zames/profile). If it is launched
|
|
880
|
+
without --isolated (or without its own --user-data-dir), the MCP browser
|
|
881
|
+
and the agent browser fight over one profile and the DeepSeek chat shows
|
|
882
|
+
"Something went wrong when opening your profile". Always pass --isolated
|
|
883
|
+
as in the example above.
|
|
884
|
+
Servers can also be remote ("url": "https://...", "transport": "sse").
|
|
885
|
+
Their tools show up in the agent as `server__tool` (e.g.
|
|
886
|
+
`playwright__browser_navigate`) and are listed with `/mcp` and in `/status`.
|
|
887
|
+
A server that fails to connect is skipped with a warning and never breaks the
|
|
888
|
+
agent.
|
|
889
|
+
|
|
890
|
+
## Configuration
|
|
891
|
+
|
|
892
|
+
Global config: `~/.zames/config.json`
|
|
893
|
+
Local (per project): `.zamesrc.json`
|
|
894
|
+
|
|
895
|
+
You can view and change settings without leaving the agent — use the
|
|
896
|
+
`/config` command. Run it without arguments to open an interactive menu
|
|
897
|
+
(↑/↓ to move, Enter to change, `d` to reset, `q` to quit). Booleans and enums
|
|
898
|
+
toggle in place; numbers and strings open an input prompt.
|
|
899
|
+
|
|
900
|
+
```
|
|
901
|
+
/config interactive settings menu
|
|
902
|
+
/config list print all editable settings
|
|
903
|
+
/config get <path> show a setting
|
|
904
|
+
/config set <path> <value> change a setting
|
|
905
|
+
/config reset <path> reset a setting to its default
|
|
906
|
+
/config path show config file paths
|
|
907
|
+
/config lang <ru|en> switch interface and agent language
|
|
908
|
+
```
|
|
909
|
+
|
|
910
|
+
Examples:
|
|
911
|
+
|
|
912
|
+
```
|
|
913
|
+
/config set maxIterations 20
|
|
914
|
+
/config set browser.deepThinking true # DeepSeek Deep thinking (slow; reasoning is hidden)
|
|
915
|
+
/config set browser.webSearch false # DeepSeek Smart web search
|
|
916
|
+
/config lang en
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
Changes are written to the project `.zamesrc.json` and applied right away
|
|
920
|
+
(where possible without a restart).
|
|
921
|
+
|
|
922
|
+
### Language
|
|
923
|
+
|
|
924
|
+
`/config lang ru` or `/config lang en` switches both the interface language
|
|
925
|
+
(help, messages, spinner) and the language the agent answers you in. The
|
|
926
|
+
locale lives in `ui.locale` in the config file.
|
|
927
|
+
|
|
928
|
+
Agent data is stored in `~/.zames`: browser profile, logs, undo history, sessions.
|
|
929
|
+
|
|
930
|
+
## FAQ
|
|
931
|
+
|
|
932
|
+
**Is this an official DeepSeek product?**
|
|
933
|
+
No. zames drives the public chat.deepseek.com web UI through a real browser,
|
|
934
|
+
like a regular user. It is not affiliated with DeepSeek.
|
|
935
|
+
|
|
936
|
+
**Do I need an API key?**
|
|
937
|
+
No. You sign in with your own DeepSeek account once; the session is stored in
|
|
938
|
+
`~/.zames/profile` and reused.
|
|
939
|
+
|
|
940
|
+
**Which model does it use?**
|
|
941
|
+
Whichever the DeepSeek web chat uses (DeepSeek-V3, or the reasoning model with
|
|
942
|
+
"Deep thinking" on). zames never calls the API directly.
|
|
943
|
+
|
|
944
|
+
**Does it work headless / on a server?**
|
|
945
|
+
Yes — headless is the default, and `--output-format jsonl` makes it scriptable.
|
|
946
|
+
`--headed` is only needed for a manual sign-in or selector debugging.
|
|
947
|
+
|
|
948
|
+
**Is automating the web UI allowed?**
|
|
949
|
+
That depends on DeepSeek's terms; automating a website may violate them. Use at
|
|
950
|
+
your own risk and keep the send throttle (15s by default) so you do not hammer
|
|
951
|
+
the rate limit.
|
|
952
|
+
|
|
953
|
+
**How is it different from Claude Code / Codex?**
|
|
954
|
+
Same shape (tools, `AGENTS.md`, skills, MCP, slash commands) but it runs on your
|
|
955
|
+
DeepSeek account instead of an API, as a browser automation rather than a
|
|
956
|
+
first-party API client.
|
|
957
|
+
|
|
958
|
+
## Links
|
|
959
|
+
|
|
960
|
+
- **npm:** <https://www.npmjs.com/package/zames_pro>
|
|
961
|
+
- **GitHub:** <https://github.com/Viqto0r/zames_pro>
|
|
962
|
+
- **Changelog:** [`CHANGELOG.md`](CHANGELOG.md)
|
|
963
|
+
- **Contributing:** [`CONTRIBUTING.md`](CONTRIBUTING.md)
|
|
964
|
+
- **Security policy:** [`SECURITY.md`](SECURITY.md)
|
|
965
|
+
- **Code of conduct:** [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md)
|
|
966
|
+
|
|
967
|
+
## License
|
|
968
|
+
|
|
969
|
+
MIT
|
|
970
|
+
|
|
971
|
+
</details>
|
package/dist/attachments.js
CHANGED
|
@@ -399,23 +399,6 @@ export function writeClipboardText(text) {
|
|
|
399
399
|
}
|
|
400
400
|
return { ok: false, via: candidates.map((c) => c.bin).join('/') };
|
|
401
401
|
}
|
|
402
|
-
export async function findFileByName(workdir, name) {
|
|
403
|
-
const candidate = path.resolve(workdir, name);
|
|
404
|
-
if (await fs.stat(candidate).catch(() => null))
|
|
405
|
-
return candidate;
|
|
406
|
-
try {
|
|
407
|
-
const { glob } = await import('fs/promises');
|
|
408
|
-
for await (const f of glob('**/' + name, { cwd: workdir })) {
|
|
409
|
-
const abs = path.resolve(workdir, f);
|
|
410
|
-
const rel = path.relative(workdir, abs);
|
|
411
|
-
if (rel.startsWith('..') || path.isAbsolute(rel))
|
|
412
|
-
continue;
|
|
413
|
-
return abs;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
catch { }
|
|
417
|
-
return null;
|
|
418
|
-
}
|
|
419
402
|
// Read file paths from the Windows clipboard (copied files, CF_HDROP) and
|
|
420
403
|
// translate them to WSL paths. On WSL the user often copies a FILE, not an
|
|
421
404
|
// image. Returns [] on non-WSL / when nothing is there.
|
package/dist/context.js
CHANGED
package/dist/extraTools.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { safePath } from './sandbox.js';
|
|
3
4
|
// Extra tools that bring zames closer to Claude Code / Codex CLI:
|
|
4
5
|
// * LS - list a directory (Claude Code has LS; Codex has list_dir)
|
|
5
6
|
// * MultiEdit - several edits to ONE file applied atomically (Claude Code)
|
|
@@ -171,14 +172,7 @@ export function applyUpdateHunk(content, hunkLines) {
|
|
|
171
172
|
export function createExtraTools(workdir, { undo, todos } = {}) {
|
|
172
173
|
const todoStore = todos || defaultTodoStore;
|
|
173
174
|
const root = path.resolve(workdir);
|
|
174
|
-
const safe = (p) =>
|
|
175
|
-
const resolved = path.resolve(root, p);
|
|
176
|
-
const rel = path.relative(root, resolved);
|
|
177
|
-
if (rel.startsWith('..') || path.isAbsolute(rel)) {
|
|
178
|
-
throw new Error('Access outside the working directory is forbidden: ' + p);
|
|
179
|
-
}
|
|
180
|
-
return resolved;
|
|
181
|
-
};
|
|
175
|
+
const safe = (p) => safePath(root, p);
|
|
182
176
|
// Guard against missing/placeholder required args: a missing `path` becomes
|
|
183
177
|
// String(undefined) === "undefined" and would create a file literally named
|
|
184
178
|
// "undefined" in the working directory.
|
|
@@ -271,9 +265,14 @@ export function createExtraTools(workdir, { undo, todos } = {}) {
|
|
|
271
265
|
throw new Error(`edits[${i}]: string occurs ${occurrences} times. ` +
|
|
272
266
|
'Make old_string more specific or pass replace_all=true.');
|
|
273
267
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
268
|
+
if (e.replace_all) {
|
|
269
|
+
content = content.split(oldStr).join(newStr);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
// Functional replacer: a string replacer would interpret $-patterns
|
|
273
|
+
// ($&, $$, $1) inside newStr and corrupt the written text.
|
|
274
|
+
content = content.replace(oldStr, () => newStr);
|
|
275
|
+
}
|
|
277
276
|
}
|
|
278
277
|
if (undo)
|
|
279
278
|
await undo.backup(file);
|
package/dist/fsutil.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
2
3
|
// One atomic writer shared by config, sessions and undo. Writing to a temp
|
|
3
4
|
// file in the SAME directory and renaming over the target is atomic on POSIX
|
|
4
5
|
// and Windows (same volume), so a crash or Ctrl+C mid-write can never leave a
|
|
@@ -8,10 +9,46 @@ import fs from 'fs';
|
|
|
8
9
|
// Kept in its own module because the pattern used to be copy-pasted in at
|
|
9
10
|
// least three places; drift between the copies is exactly how one of them
|
|
10
11
|
// silently loses its atomicity.
|
|
12
|
+
//
|
|
13
|
+
// The file is created 0o600: ~/.zames/config.json holds the
|
|
14
|
+
// browser password in clear text alongside sessions/undo history, and the
|
|
15
|
+
// default umask (022) would make them readable by other users on a
|
|
16
|
+
// multi-user machine. We also chmod the target after rename because a
|
|
17
|
+
// pre-existing file keeps its old mode (rename does not change the inode).
|
|
11
18
|
export function writeFileAtomic(file, data) {
|
|
12
19
|
const tmp = file + '.tmp-' + process.pid;
|
|
13
|
-
|
|
20
|
+
// fsync the file BEFORE rename: without it a power loss can leave the
|
|
21
|
+
// renamed name pointing at an empty/partial inode (rename itself is atomic,
|
|
22
|
+
// but the data blocks may not have reached the disk yet).
|
|
23
|
+
const fd = fs.openSync(tmp, 'w', 0o600);
|
|
24
|
+
try {
|
|
25
|
+
fs.writeFileSync(fd, data);
|
|
26
|
+
fs.fsyncSync(fd);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
fs.closeSync(fd);
|
|
30
|
+
}
|
|
14
31
|
fs.renameSync(tmp, file);
|
|
32
|
+
// fsync the DIRECTORY so the rename entry itself is durable.
|
|
33
|
+
try {
|
|
34
|
+
const dirFd = fs.openSync(path.dirname(file), 'r');
|
|
35
|
+
try {
|
|
36
|
+
fs.fsyncSync(dirFd);
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
fs.closeSync(dirFd);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Some platforms/filesystems do not allow opening a directory; best-effort.
|
|
44
|
+
}
|
|
45
|
+
// Best-effort: on Windows chmod is largely a no-op and can throw.
|
|
46
|
+
try {
|
|
47
|
+
fs.chmodSync(file, 0o600);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// ignore
|
|
51
|
+
}
|
|
15
52
|
}
|
|
16
53
|
export function writeJsonAtomic(file, value) {
|
|
17
54
|
writeFileAtomic(file, JSON.stringify(value, null, 2) + String.fromCharCode(10));
|