tandem-mode 0.4.0 → 0.5.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/README.md +249 -233
- package/dist/agent/loop.js +12 -2
- package/dist/agent/loop.js.map +1 -1
- package/dist/cli.js +91 -6
- package/dist/cli.js.map +1 -1
- package/dist/config/schema.js +1 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/i18n/en.js +28 -19
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/sr.js +28 -19
- package/dist/i18n/sr.js.map +1 -1
- package/dist/repl/commands.js +1 -0
- package/dist/repl/commands.js.map +1 -1
- package/dist/ui/status.js +37 -0
- package/dist/ui/status.js.map +1 -0
- package/dist/ui/toolFormat.js +89 -0
- package/dist/ui/toolFormat.js.map +1 -0
- package/package.json +49 -49
package/README.md
CHANGED
|
@@ -1,233 +1,249 @@
|
|
|
1
|
-
# Tandem Mode
|
|
2
|
-
|
|
3
|
-
[](https://www.npmjs.com/package/tandem-mode)
|
|
4
|
-
[](./LICENSE)
|
|
5
|
-
[](./package.json)
|
|
6
|
-
[](https://github.com/zdrave08/Tandem-Mode/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
|
7
|
-
|
|
8
|
-
**English** | [Srpski](./README.sr.md)
|
|
9
|
-
|
|
10
|
-
A terminal coding agent built specifically for the DeepSeek API — not a generic
|
|
11
|
-
LLM harness with DeepSeek bolted on. Interactive REPL, planner/worker/reviewer
|
|
12
|
-
orchestration, cache-aware prompt architecture, and first-class support for
|
|
13
|
-
Windows, macOS, and Linux.
|
|
14
|
-
|
|
15
|
-
> **Independent open-source project. Not affiliated with or endorsed by
|
|
16
|
-
> DeepSeek.**
|
|
17
|
-
|
|
18
|
-
## Status
|
|
19
|
-
|
|
20
|
-
M0–M4 of the [development plan](./deepseek-cli-development-plan.md) are done.
|
|
21
|
-
Published on npm, usable today for real coding tasks against a local repo.
|
|
22
|
-
|
|
23
|
-
First benchmark run is in — see [full results](./docs/benchmark-results.md).
|
|
24
|
-
Headline: all three configurations (Pro-only, Flash-only, orchestration)
|
|
25
|
-
fixed 4/4 injected bugs correctly in a real WooCommerce plugin, with a clean
|
|
26
|
-
`php -l` and zero unnecessary file changes. But for this class of task
|
|
27
|
-
(single-file, well-scoped fixes), orchestration cost ~9.5× more and took
|
|
28
|
-
~19× longer than Pro-only for the same correctness — the opposite of what
|
|
29
|
-
you'd want orchestration for. Read as: orchestration's overhead needs a
|
|
30
|
-
bigger, more decomposable task to pay for itself, which this first run didn't
|
|
31
|
-
test. Reported as-is, not adjusted to fit expectations.
|
|
32
|
-
|
|
33
|
-
## Features
|
|
34
|
-
|
|
35
|
-
- **Agentic loop** — `deepseek-v4-pro`/`deepseek-v4-flash` with tool calling:
|
|
36
|
-
`read_file`, `list_dir`, `search`, `edit`, `git_diff`, `shell`, `view_image`,
|
|
37
|
-
`web_search`.
|
|
38
|
-
- **Two entry points** — interactive REPL for normal work, single-shot mode
|
|
39
|
-
(`tandem "task" --yes`) for scripting and CI.
|
|
40
|
-
- **Orchestration** (`/plan`) — a planner produces a JSON task list, workers
|
|
41
|
-
execute each task with a fresh minimal context, a reviewer checks the git
|
|
42
|
-
diff against the original task and either approves or requests corrections
|
|
43
|
-
(capped by `max_review_loops`).
|
|
44
|
-
- **Cache-aware prompts** — the worker's system prompt + repo map + plan stay
|
|
45
|
-
byte-identical across calls in one orchestration run, so DeepSeek's context
|
|
46
|
-
cache actually hits. Measured live: cache-hit tokens grew call over call
|
|
47
|
-
within a single `/plan` run.
|
|
48
|
-
- **Vision** — `view_image` lets the agent look at a screenshot you point it
|
|
49
|
-
to; `/paste` grabs an image straight from the clipboard (Windows, macOS,
|
|
50
|
-
and Linux via X11/`xclip` or Wayland/`wl-clipboard`).
|
|
51
|
-
- **Web search** — isolated calls to DeepSeek's Responses API when the agent
|
|
52
|
-
needs something outside the repo (an error message, a library's docs).
|
|
53
|
-
- **Session persistence** — every session is a JSONL file; `/resume` continues
|
|
54
|
-
the latest (or a named) one, `/fork` branches off without touching the
|
|
55
|
-
original.
|
|
56
|
-
- **Safety** — destructive actions (file edits, shell commands not on a small
|
|
57
|
-
read-only allowlist) always ask for confirmation; `y`/`n`/`a` where `a`
|
|
58
|
-
remembers the choice for that tool for the rest of the session. `--yes`
|
|
59
|
-
bypasses this for CI but always prints what it auto-approved.
|
|
60
|
-
- **Cost control** — usage is read only from the API's own `usage` field,
|
|
61
|
-
never estimated. A budget (`/budget`, `--budget`) hard-stops the loop before
|
|
62
|
-
the next API call if exceeded, without losing the session. `/usage` also
|
|
63
|
-
shows what the session would have cost off-peak, and the REPL warns you at
|
|
64
|
-
startup if you're currently in a peak-pricing window.
|
|
65
|
-
- **
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
|
118
|
-
|
|
119
|
-
| `--
|
|
120
|
-
| `--
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
|
125
|
-
|
|
126
|
-
|
|
|
127
|
-
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
|
132
|
-
|
|
133
|
-
| `/
|
|
134
|
-
| `/
|
|
135
|
-
| `/
|
|
136
|
-
| `/
|
|
137
|
-
| `/
|
|
138
|
-
| `/
|
|
139
|
-
| `/
|
|
140
|
-
| `/
|
|
141
|
-
| `/
|
|
142
|
-
| `/
|
|
143
|
-
| `/
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
- `src/
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
1
|
+
# Tandem Mode
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/tandem-mode)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](./package.json)
|
|
6
|
+
[](https://github.com/zdrave08/Tandem-Mode/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
|
7
|
+
|
|
8
|
+
**English** | [Srpski](./README.sr.md)
|
|
9
|
+
|
|
10
|
+
A terminal coding agent built specifically for the DeepSeek API — not a generic
|
|
11
|
+
LLM harness with DeepSeek bolted on. Interactive REPL, planner/worker/reviewer
|
|
12
|
+
orchestration, cache-aware prompt architecture, and first-class support for
|
|
13
|
+
Windows, macOS, and Linux.
|
|
14
|
+
|
|
15
|
+
> **Independent open-source project. Not affiliated with or endorsed by
|
|
16
|
+
> DeepSeek.**
|
|
17
|
+
|
|
18
|
+
## Status
|
|
19
|
+
|
|
20
|
+
M0–M4 of the [development plan](./deepseek-cli-development-plan.md) are done.
|
|
21
|
+
Published on npm, usable today for real coding tasks against a local repo.
|
|
22
|
+
|
|
23
|
+
First benchmark run is in — see [full results](./docs/benchmark-results.md).
|
|
24
|
+
Headline: all three configurations (Pro-only, Flash-only, orchestration)
|
|
25
|
+
fixed 4/4 injected bugs correctly in a real WooCommerce plugin, with a clean
|
|
26
|
+
`php -l` and zero unnecessary file changes. But for this class of task
|
|
27
|
+
(single-file, well-scoped fixes), orchestration cost ~9.5× more and took
|
|
28
|
+
~19× longer than Pro-only for the same correctness — the opposite of what
|
|
29
|
+
you'd want orchestration for. Read as: orchestration's overhead needs a
|
|
30
|
+
bigger, more decomposable task to pay for itself, which this first run didn't
|
|
31
|
+
test. Reported as-is, not adjusted to fit expectations.
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **Agentic loop** — `deepseek-v4-pro`/`deepseek-v4-flash` with tool calling:
|
|
36
|
+
`read_file`, `list_dir`, `search`, `edit`, `git_diff`, `shell`, `view_image`,
|
|
37
|
+
`web_search`.
|
|
38
|
+
- **Two entry points** — interactive REPL for normal work, single-shot mode
|
|
39
|
+
(`tandem "task" --yes`) for scripting and CI.
|
|
40
|
+
- **Orchestration** (`/plan`) — a planner produces a JSON task list, workers
|
|
41
|
+
execute each task with a fresh minimal context, a reviewer checks the git
|
|
42
|
+
diff against the original task and either approves or requests corrections
|
|
43
|
+
(capped by `max_review_loops`).
|
|
44
|
+
- **Cache-aware prompts** — the worker's system prompt + repo map + plan stay
|
|
45
|
+
byte-identical across calls in one orchestration run, so DeepSeek's context
|
|
46
|
+
cache actually hits. Measured live: cache-hit tokens grew call over call
|
|
47
|
+
within a single `/plan` run.
|
|
48
|
+
- **Vision** — `view_image` lets the agent look at a screenshot you point it
|
|
49
|
+
to; `/paste` grabs an image straight from the clipboard (Windows, macOS,
|
|
50
|
+
and Linux via X11/`xclip` or Wayland/`wl-clipboard`).
|
|
51
|
+
- **Web search** — isolated calls to DeepSeek's Responses API when the agent
|
|
52
|
+
needs something outside the repo (an error message, a library's docs).
|
|
53
|
+
- **Session persistence** — every session is a JSONL file; `/resume` continues
|
|
54
|
+
the latest (or a named) one, `/fork` branches off without touching the
|
|
55
|
+
original.
|
|
56
|
+
- **Safety** — destructive actions (file edits, shell commands not on a small
|
|
57
|
+
read-only allowlist) always ask for confirmation; `y`/`n`/`a` where `a`
|
|
58
|
+
remembers the choice for that tool for the rest of the session. `--yes`
|
|
59
|
+
bypasses this for CI but always prints what it auto-approved.
|
|
60
|
+
- **Cost control** — usage is read only from the API's own `usage` field,
|
|
61
|
+
never estimated. A budget (`/budget`, `--budget`) hard-stops the loop before
|
|
62
|
+
the next API call if exceeded, without losing the session. `/usage` also
|
|
63
|
+
shows what the session would have cost off-peak, and the REPL warns you at
|
|
64
|
+
startup if you're currently in a peak-pricing window.
|
|
65
|
+
- **Status line** — the last line of every turn shows model, mode (chat/plan),
|
|
66
|
+
cost (and budget), and the current call out of the iteration limit; it turns
|
|
67
|
+
yellow, then red, as you approach the budget or the limit.
|
|
68
|
+
- **Readable tool output** — `edit` shows a red/green diff, `read_file`, `search`
|
|
69
|
+
and `list_dir` collapse to a one-line summary (`120 lines read`, `no matches`).
|
|
70
|
+
- **ESC to interrupt** — cancels the in-flight call (and any running shell
|
|
71
|
+
command) cleanly, keeping whatever was generated so far.
|
|
72
|
+
- **Cross-platform** — the shell tool runs PowerShell natively on Windows and
|
|
73
|
+
`sh` on macOS/Linux, file edits preserve the original CRLF/LF line ending
|
|
74
|
+
style, paths are handled with `path.resolve` throughout.
|
|
75
|
+
|
|
76
|
+
## Quick start
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm install -g tandem-mode
|
|
80
|
+
tandem # interactive REPL
|
|
81
|
+
tandem "explain what this repo does" --yes # one-shot
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or from source (useful for contributing, or to track `main` instead of the
|
|
85
|
+
latest npm release):
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://github.com/zdrave08/Tandem-Mode.git
|
|
89
|
+
cd Tandem-Mode
|
|
90
|
+
pnpm install
|
|
91
|
+
pnpm dev # interactive REPL
|
|
92
|
+
pnpm dev "explain what this repo does" --yes # one-shot
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
On first run you'll be asked for a DeepSeek API key (get one at
|
|
96
|
+
[platform.deepseek.com](https://platform.deepseek.com)) and a default
|
|
97
|
+
model/reasoning effort. The key is stored in your OS's own secure credential
|
|
98
|
+
store — never in a config file or log:
|
|
99
|
+
|
|
100
|
+
- **Windows** — DPAPI-encrypted (tied to your OS user account) in
|
|
101
|
+
`%LOCALAPPDATA%\TandemMode\credentials.dat`.
|
|
102
|
+
- **macOS** — the login Keychain, via the built-in `security` CLI.
|
|
103
|
+
- **Linux** — the Secret Service (gnome-keyring, KWallet, or similar), via
|
|
104
|
+
`secret-tool` (install `libsecret-tools` if it's missing).
|
|
105
|
+
|
|
106
|
+
`DEEPSEEK_API_KEY` works everywhere and always takes priority, for CI use.
|
|
107
|
+
|
|
108
|
+
## Usage
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
tandem # interactive REPL
|
|
112
|
+
tandem "fix the off-by-one in foo.ts"
|
|
113
|
+
tandem --plan "add dark mode to the settings page"
|
|
114
|
+
tandem "task" --model deepseek-v4-flash --effort low --budget 0.50 --yes
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
| Flag | Effect |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `--resume` / `-r` | Continue the latest session in this directory |
|
|
120
|
+
| `--yes` / `-y` | Auto-approve destructive actions (prints what it approved) |
|
|
121
|
+
| `--plan` | Run planner/worker/reviewer orchestration instead of a single turn |
|
|
122
|
+
| `--model` | `deepseek-v4-pro` or `deepseek-v4-flash` |
|
|
123
|
+
| `--effort` | `low`, `high`, or `max` reasoning effort |
|
|
124
|
+
| `--budget` | Hard USD cap for the run |
|
|
125
|
+
| `--max-review-loops` | Cap on orchestration correction cycles (default 3) |
|
|
126
|
+
| `--max-iterations` | Model calls per chunk of a turn (default 25); at the limit the agent asks whether to continue |
|
|
127
|
+
| `--auto-continue` | Continue at the iteration limit without asking — only together with a budget (`--budget`) |
|
|
128
|
+
|
|
129
|
+
### REPL commands
|
|
130
|
+
|
|
131
|
+
| Command | Effect |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `/plan <task>` | Planner/worker/reviewer orchestration |
|
|
134
|
+
| `/model [name]` | Show or switch model |
|
|
135
|
+
| `/thinking [on\|off]` | Toggle thinking mode |
|
|
136
|
+
| `/effort [low\|high\|max]` | Show or set reasoning effort |
|
|
137
|
+
| `/status` | Current session/settings |
|
|
138
|
+
| `/diff [--staged] [path]` | Working-tree diff, no API call |
|
|
139
|
+
| `/usage` | Tokens, cost, off-peak projection |
|
|
140
|
+
| `/budget [amount]` | Show or set the session budget |
|
|
141
|
+
| `/new` | Start a fresh session |
|
|
142
|
+
| `/save-profile <name>` | Save model, effort, budget and review loops as a named profile |
|
|
143
|
+
| `/profile [name]` | Load a saved profile, or list them |
|
|
144
|
+
| `/compact` | Summarize the history into a new session to free up context; the old session stays on disk |
|
|
145
|
+
| `/fork` | New session, carrying over the current history |
|
|
146
|
+
| `/resume [id]` | Continue the latest (or a named) session |
|
|
147
|
+
| `/paste [message]` | Send a clipboard image to the agent |
|
|
148
|
+
| `/clear` | Clear the screen |
|
|
149
|
+
| `/help` | This list |
|
|
150
|
+
| `/exit` | Quit |
|
|
151
|
+
|
|
152
|
+
Press **ESC** at any time during a turn to interrupt it.
|
|
153
|
+
|
|
154
|
+
## Architecture
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
tandem (no args) ─┬─> interactive REPL ─┬─> single turn: agent loop (tools)
|
|
158
|
+
│ └─> /plan: planner → worker(s) → reviewer
|
|
159
|
+
tandem "task" ──┘ (single-shot, same agent loop, for scripts/CI)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- `src/deepseek/` — thin client for DeepSeek's OpenAI-compatible API
|
|
163
|
+
(streaming + non-streaming chat completions, vision, web search via
|
|
164
|
+
Responses API). See [`docs/api-notes.en.md`](./docs/api-notes.en.md)
|
|
165
|
+
(Serbian original: [`docs/api-notes.md`](./docs/api-notes.md)) for the
|
|
166
|
+
API behavior this is built against, verified live rather than assumed.
|
|
167
|
+
- `src/agent/` — the tool-calling loop, tool implementations, session
|
|
168
|
+
persistence, usage/cost tracking.
|
|
169
|
+
- `src/orchestrator/` — planner/worker/reviewer, repo-map generation, the
|
|
170
|
+
cache-aware stable-prefix construction.
|
|
171
|
+
- `src/repl/` — slash commands, runtime config, the first-run wizard.
|
|
172
|
+
- `src/cli.tsx` — Ink-based terminal UI and the REPL/single-shot entry points.
|
|
173
|
+
|
|
174
|
+
## Configuration
|
|
175
|
+
|
|
176
|
+
Layered: **session** (in-REPL commands) > **project** (`.tandem/config.json`
|
|
177
|
+
in the current directory) > **global** (`~/.tandem/config.json`).
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"defaultModel": "deepseek-v4-pro",
|
|
182
|
+
"defaultReasoningEffort": "high",
|
|
183
|
+
"budgetUsd": 5,
|
|
184
|
+
"maxReviewLoops": 3,
|
|
185
|
+
"maxIterations": 25,
|
|
186
|
+
"autoContinue": false,
|
|
187
|
+
"verifyCommand": "pnpm typecheck && pnpm test",
|
|
188
|
+
"notifyCommand": "curl -s -d \"Tandem: $TANDEM_OUTCOME\" https://ntfy.sh/my-topic",
|
|
189
|
+
"language": "en"
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
`maxIterations` is how many model calls one turn may make before Tandem stops and
|
|
194
|
+
asks "continue for N more calls? (y/n/a)"; `a` remembers the answer for the rest of
|
|
195
|
+
the session. With `autoContinue` (or `--auto-continue`) it continues on its own, but
|
|
196
|
+
only when a budget is set, because the budget is the hard stop before the next API
|
|
197
|
+
call. In non-interactive runs (`--yes`) without `--auto-continue` it stops instead of
|
|
198
|
+
waiting for an answer, and the session is saved so you can send "continue".
|
|
199
|
+
|
|
200
|
+
`verifyCommand` runs before each `/plan` review round and its result goes to
|
|
201
|
+
the reviewer. `language` is the UI language (`en` or `sr`, default `en`); the
|
|
202
|
+
`--lang` flag and the `TANDEM_LANG` environment variable override it, in that
|
|
203
|
+
order. The first-run wizard asks for it.
|
|
204
|
+
|
|
205
|
+
`notifyCommand` runs when a `/plan` run ends: reviewer approved, `max_review_loops`
|
|
206
|
+
reached, or an error (not when you interrupt it with ESC). The details come in as
|
|
207
|
+
environment variables, never spliced into the command text: `TANDEM_OUTCOME`
|
|
208
|
+
(`approved`, `max_review_loops` or `error`), `TANDEM_TASK`, `TANDEM_NOTES` (the
|
|
209
|
+
reviewer's notes, or the error message), `TANDEM_REVIEW_LOOPS` and `TANDEM_COST_USD`.
|
|
210
|
+
The command runs in your shell (PowerShell on Windows, `sh` elsewhere) with a 15 s
|
|
211
|
+
limit, and a failure only prints a warning. Any shell command works, so Slack,
|
|
212
|
+
ntfy, a desktop notification or a webhook are all just examples:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{ "notifyCommand": "curl -s -d \"Tandem: $TANDEM_OUTCOME\" https://ntfy.sh/my-topic" }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
On Windows (PowerShell) the variables are written `$env:TANDEM_OUTCOME`.
|
|
219
|
+
|
|
220
|
+
Like `verifyCommand`, `notifyCommand` runs without asking, so only put it in a
|
|
221
|
+
project's `.tandem/config.json` if you trust that project.
|
|
222
|
+
|
|
223
|
+
**Profiles:** `/save-profile <name>` stores the current model, reasoning effort,
|
|
224
|
+
budget and review loops in `~/.tandem/profiles/<name>.json`, and `/profile <name>`
|
|
225
|
+
loads them back into the running session (only the fields present in the file are
|
|
226
|
+
applied). `/profile` alone lists the saved ones. Names use `a-z`, `0-9`, `-` and `_`.
|
|
227
|
+
Profiles never include `verifyCommand` or the API key.
|
|
228
|
+
|
|
229
|
+
The API key is never stored in these files — it lives in the OS credential
|
|
230
|
+
store (or `DEEPSEEK_API_KEY` env var, which takes priority, for CI use).
|
|
231
|
+
|
|
232
|
+
## Development
|
|
233
|
+
|
|
234
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
pnpm install
|
|
238
|
+
pnpm typecheck
|
|
239
|
+
pnpm dev "some task"
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Disclaimer
|
|
243
|
+
|
|
244
|
+
This is an independent, community-run project. It is not affiliated with,
|
|
245
|
+
endorsed by, or sponsored by DeepSeek.
|
|
246
|
+
|
|
247
|
+
## License
|
|
248
|
+
|
|
249
|
+
[MIT](./LICENSE)
|
package/dist/agent/loop.js
CHANGED
|
@@ -17,7 +17,17 @@ const MAX_REASONING_CHARS = 200_000;
|
|
|
17
17
|
export async function* runAgentLoop(messages, opts) {
|
|
18
18
|
const ctx = { cwd: opts.cwd, env: opts.env, usage: opts.usage, ...(opts.signal ? { signal: opts.signal } : {}) };
|
|
19
19
|
const maxIterations = opts.maxIterations ?? 25;
|
|
20
|
-
|
|
20
|
+
// Granica se pomera za još jedan "komad" svaki put kad korisnik (ili autoContinue) dozvoli nastavak.
|
|
21
|
+
let limit = maxIterations;
|
|
22
|
+
for (let iteration = 0;; iteration++) {
|
|
23
|
+
if (iteration >= limit) {
|
|
24
|
+
const proceed = opts.onIterationLimit ? await opts.onIterationLimit({ iterations: iteration }) : false;
|
|
25
|
+
if (!proceed) {
|
|
26
|
+
yield { type: "max_iterations_reached" };
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
limit += maxIterations;
|
|
30
|
+
}
|
|
21
31
|
if (opts.signal?.aborted) {
|
|
22
32
|
yield { type: "interrupted" };
|
|
23
33
|
return;
|
|
@@ -29,6 +39,7 @@ export async function* runAgentLoop(messages, opts) {
|
|
|
29
39
|
return;
|
|
30
40
|
}
|
|
31
41
|
}
|
|
42
|
+
yield { type: "iteration", n: iteration + 1, max: limit };
|
|
32
43
|
let reasoning = "";
|
|
33
44
|
let content = "";
|
|
34
45
|
const toolCallBuf = new Map();
|
|
@@ -159,6 +170,5 @@ export async function* runAgentLoop(messages, opts) {
|
|
|
159
170
|
await appendSessionMessage(opts.session, toolMsg);
|
|
160
171
|
}
|
|
161
172
|
}
|
|
162
|
-
yield { type: "max_iterations_reached" };
|
|
163
173
|
}
|
|
164
174
|
//# sourceMappingURL=loop.js.map
|
package/dist/agent/loop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAqC,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAgB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
|