5770a574 added crates/tui/src/bin/deepseek.rs as a shim that calls
deepseek_tui_cli::run_cli() so `cargo install deepseek-tui` would also
install the canonical `deepseek` command. But the cli crate already
declares an identically-named bin target, so workspace builds emit two
artifacts to target/release/deepseek(.exe) -- cargo prints `output
filename collision` and on Windows the second linker hits LNK1104:
cannot open file deepseek.exe (the first hold has not released).
The cli crate stays the single source of `deepseek`. Workspace default
members still produce both binaries (deepseek from cli, deepseek-tui
from tui), no collision. Cargo install path: `cargo install
deepseek-tui-cli` for the canonical `deepseek` command, `cargo install
deepseek-tui` for the TUI binary; npm wrapper unaffected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a model-visible skills block to the system prompt (progressive
disclosure: lists name/description/path, never inlines SKILL.md bodies)
with a 12k-char prompt budget and a 512-char per-description cap.
EngineConfig gains skills_dir, threaded through the three construction
sites (TUI app, exec agent, runtime thread manager).
README skills section is rewritten to document the discovery order,
the SKILL.md frontmatter contract, and the install/update/uninstall/
trust commands. Adds Simplified Chinese README cross-link and full
README.zh-CN.md translation (DeepSeek went viral in CN -- discoverability
matters).
Tests cover happy path, empty/missing dir → None, oversize description
truncation with U+2026 marker, internal-whitespace collapse, and the
overflow-budget omission notice.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The wrapper re-downloaded the SHA-256 manifest from the GitHub release on every
invocation of `deepseek` / `deepseek-tui`, so any GitHub flake, captive portal,
proxy, or offline state broke every command — not just install.
Now ensureBinary returns immediately when the binary exists and its `.version`
marker matches. The manifest fetch is lazy and only runs when a download is
actually needed (first install or DEEPSEEK_TUI_FORCE_DOWNLOAD=1).
Bumps wrapper to 0.8.2; deepseekBinaryVersion stays on 0.8.1 (no new Rust
release required).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps the workspace/npm wrapper to 0.8.0 and fixes completed background shell jobs retaining live process handles, which could cause Too many open files, checkpoint save failures, shell spawn failures, and lag around send/close/Esc. Also includes Windows REPL bootstrap timeout hardening and Cargo/TUNA mirror install docs.
Includes:
- Post-turn freeze fix (reorder maybe_advance_cycle before TurnComplete)
- Enter/steering fix (QueueFollowUp when model is streaming)
- Esc fanout hardening (idempotent finalize methods)
- cargo fmt pass on new code
- CHANGELOG, README, and version bump across workspace + npm
- fix(#234): reorder cycle advancement before TurnComplete so the engine
loop doesn't block the terminal after the turn signal. User sees the
'↻ context refreshing...' status chip during briefing generation
instead of a frozen terminal with no feedback.
- fix(#250): Enter during streaming queues a follow-up (visible queued
text) instead of claiming to 'steer' a message that never reaches the
model. During tool-execution phases Enter correctly steers the active
turn via rx_steer, which is already drained before each API call.
- fix(#243): hardened Esc during sub-agent fanout — added idempotency
test proving finalize_active_cell_as_interrupted is safe when
TurnComplete arrives after Esc.
- close(#249): unicode search panic fix confirmed in v0.7.8, closing.
- feat: both fixes implemented by live sub-agents (agent_spawn) —
proving the sub-agent system works end-to-end.
* wip(v0.7.7): handoff baseline of partial sub-agent stabilization
Captures uncommitted work-in-progress on the v0.7.7 stabilization lane
so subsequent fixes have a stable starting point. Subsequent commits
finish the canonical SubAgentJob/SwarmJob model, fix sidebar/transcript/
footer agreement, copy/paste/cancel contract, checklist rendering, shell
summary preservation, monotonic spend, and version provenance.
Refs #235#236#237#238#239#240#241#242#243#244#245
* release: bump workspace version to 0.7.7 (#245)
Refs #245
* fix(v0.7.7): canonical swarm card binding, monotonic spend, checklist + shell summary
- Add `swarm_card_index: HashMap<swarm_id, history_index>` so overlapping
fanouts each project to their own FanoutCard. Eliminates the screenshot
contradiction where a stale background swarm's progress clobbered a
newer card (#236, #238).
- Suppress fanout-class tools (`agent_swarm`, `spawn_agents_on_csv`,
`rlm`, `agent_spawn`) from `active_tool_status_label` so the footer no
longer reports "tool agent_swarm · 1 active" while sidebar+card show
the actual worker counts (#236, #238).
- Add `App::displayed_session_cost` + `displayed_cost_high_water` so the
visible session+sub-agent total is monotonic across reconciliation
events (cache discounts, provisional → final). New tests: monotonicity
under negative reconciliation; duplicate dedup keeps display steady (#244).
- Preserve high-signal summary lines from the truncated tail of shell
output: `test result:`, `failures:`, `error[E…]`, `Finished`,
`Compiling`, panic markers. Stops the agent re-running cargo gates
just to see pass/fail under truncation (#242).
- Render `checklist_write` / `todo_*` results as a purpose-built
checklist card with completed/total + percent header, per-item status
markers, and a collapsing affordance for long lists. Plumbed through
the existing `GenericToolCell` so no new variant threading is needed (#241).
Refs #236#238#241#242#244
* fix(v0.7.7): Esc clears active tool entries optimistically (#243)
When Esc cancels the foreground turn we now finalize the active cell
immediately rather than waiting for the engine's TurnComplete echo to
drain. This stops the footer "tool ... · X active" chip from briefly
contradicting the cancelled state, and frees the composer for the next
message.
Background `block:false` swarms are intentionally NOT killed here — they
remain durable, tracked through `swarm_jobs` and `swarm_card_index` so
their FanoutCard updates as workers land. Subsequent `swarm_status` /
`swarm_result` / `swarm_cancel` tool calls see the canonical store.
New focused test verifies: after Esc, `active_cell` is None, the
background swarm record is preserved, and `is_loading` is cleared so
the composer can submit immediately.
Refs #243
* fix(v0.7.7): Windows .exe lookup + post-turn snapshot detach (#247, #234)
#247 — npm-distributed Windows package failed at runtime because the
Rust dispatcher's `delegate_to_tui` / `delegate_simple_tui` looked for a
sibling named exactly "deepseek-tui", while the actual file shipped by
`scripts/install.js` is `deepseek-tui.exe`. Replace both lookups with
`locate_sibling_tui_binary`, which:
- Honours `DEEPSEEK_TUI_BIN` for explicit overrides
- Tries `deepseek-tui{EXE_SUFFIX}` first (`.exe` on Windows, "" elsewhere)
- Falls back to suffix-less `deepseek-tui` on Windows so users who
applied the issue's manual workaround still launch successfully
- Emits a platform-correct error path in the bail message
Tests: `sibling_tui_candidate_picks_platform_correct_name`,
`sibling_tui_candidate_windows_falls_back_to_suffixless` (windows-only),
`locate_sibling_tui_binary_honours_env_override`.
#234 — Detach the post-turn workspace snapshot so `git add -A && git
commit` no longer pins the engine loop after `Event::TurnComplete`.
The snapshot still runs on `tokio::task::spawn_blocking`, but the
engine no longer awaits its `JoinHandle`, so the UI accepts input
(text, copy, paste, selection) without waiting for the bookkeeping to
finish. Cycle advance and pre-turn snapshot remain awaited — they are
correctness-sensitive and the cycle path already emits a status chip
("↻ context refreshing…") so the user has visible feedback.
Refs #234#247
* chore(v0.7.7): bump npm package version 0.7.6 → 0.7.7
Required by `scripts/release/check-versions.sh` ("Version drift" CI
gate); the workspace was bumped to 0.7.7 but `npm/deepseek-tui/package.json`
still reported 0.7.6, blocking PR #246 from going green.
Refs #245
- Bump workspace version to 0.7.6 (Cargo.toml + all crate internal dep pins)
- Bump npm wrapper version and deepseekBinaryVersion to 0.7.6
- Add v0.7.6 changelog entry: localization, paste burst, history search,
pending input preview, grouped /config editor, searchable help overlay,
Alt+↑ edit-last-queued, composer attachment management
- Update README with v0.7.6 features (localization, paste, history search)
- Archive v0.7.5 implementation plan to docs/archive/
- Update Cargo.lock
Issues #202, #203, #204, #205:
- Cycle/seam triggers use active request input size + response
headroom reserve, not lifetime cumulative API usage.
- V4 hard-cycle headroom calibrated around fixed TURN_MAX_OUTPUT_TOKENS
plus CONTEXT_HEADROOM_TOKENS safety buffer.
- /tokens, /cost, footer/header labels, and docs now separate
active context, turn telemetry, cumulative usage, cache hit/miss,
context percent, and cost.
- Foreground exec_shell timeout output tells the model the process
was killed and suggests task_shell_start or background exec_shell
plus poll/wait.
- Added regression tests for active-token basis, V4 headroom,
seam trigger basis, footer label behavior, and shell timeout
recovery metadata.
- Preserved #200/#201 policy: V4 default is append-only,
prefix-cache preserving; replacement compaction, Flash seams,
and capacity intervention remain opt-in.
#167: Fix all 7 clippy warnings — annotated SeamMetadata dead fields,
removed unused should_cycle calls, collapsed nested ifs, fixed
useless_format and nonminimal_bool.
#168: Wire TokenUsage mailbox drain to subagent_cost accumulator.
handle_subagent_mailbox now intercepts TokenUsage before routing to
cards, computes cost via calculate_turn_cost, and increments
app.subagent_cost in real time. Footer reflects live sub-agent spend.
Restored ArchivedContext variant to HistoryCell (corrupted by prior
apply_patch). Version bump to 0.7.2.
Refs: #166, #167, #168
Adds the core SeamManager struct (#159) that uses V4 Flash to produce
append-only <archived_context> XML blocks at 192K/384K/576K thresholds.
No messages are deleted — soft seams are navigational summaries that
preserve the V4 prefix cache.
- seam_manager.rs: Flash-driven soft seam production, recompaction,
and cycle briefing replacement
- config.rs: [context] table with L1/L2/L3/cycle thresholds,
verbatim window, seam model, and per-model overrides
- compaction.rs: pub exports for plan_compaction, KEEP_RECENT_MESSAGES,
and CompactionPlan fields so SeamManager can reuse pinning heuristics
- cycle_manager.rs: pub CYCLE_HANDOFF_TEMPLATE for Flash briefing use
- main.rs: mod seam_manager registration
All 1,570 tests pass. Engine wiring follows in a subsequent commit.
`run_interactive` now calls `session_manager::prune_workspace_snapshots_at_boot`
right after the system-skills installer, dropping any snapshot in the
side-git repo older than 7 days (default; configurable via the new
`[snapshots]` section in `config.example.toml`). The helper is
non-fatal: a missing `git` binary, read-only home, or absent snapshot
dir all log a single WARN (or DEBUG for the count of pruned commits)
and return, so the TUI keeps starting even when retention can't run.
Also document the snapshot subsystem in `config.example.toml` —
disk-footprint expectations, where the side repo lives, and how
`/restore` / `revert_turn` consume it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two user-facing entry points to the snapshot side-repo:
- `/restore [N]` (slash command) — `/restore` with no arg lists the
10 most recent snapshots so the user can see what's available.
`/restore N` restores the N-th most recent snapshot. Outside YOLO
or `/trust on`, the command refuses to mutate files and tells the
user how to opt in (no in-flow modal-confirm path inside slash
commands today; trust mode is the explicit gate).
- `revert_turn` (agent-callable tool) — `turn_offset` (default 1)
counts in `pre-turn:*` snapshots, so the model can say "undo my
last edit" without having to enumerate the history. Approval-gated
(`ApprovalRequirement::Required`) since it mutates the workspace,
and registered through `with_full_agent_surface` so children
inherit it just like every other agent-mode tool.
Tests for both surfaces use the process-wide env mutex
(`crate::test_support::lock_test_env`) plus an RAII `HOME` guard so
tempdir-based snapshot resolution stays inside the per-test sandbox
even when the runner threads multiple tests in parallel.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire `pre_turn_snapshot` and `post_turn_snapshot` helpers into
`core::turn`, then call them from `Engine::handle_send_message` —
pre-turn fires right after `turn_counter` is incremented, post-turn
fires right after `Event::TurnComplete` is emitted.
Both hooks are dispatched via `tokio::task::spawn_blocking` so the
agent loop never waits on the side-git commit, and helper failures are
swallowed at WARN log level so a busted disk or missing `git` binary
can never derail a turn (per the snapshot module's documented
non-fatal contract).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduce `crate::snapshot` — a per-workspace side-git repo that lives
under `~/.deepseek/snapshots/<project_hash>/<worktree_hash>/.git` and
captures the workspace into commits via `git add -A` + `git commit
--allow-empty`. The user's own `.git` is never touched: every git
invocation passes both `--git-dir` (side repo) and `--work-tree`
(workspace) together, which is the load-bearing safety invariant.
Module layout:
- `paths.rs` — resolves the side-repo dir; strips `.worktrees/<name>`
so worktrees of the same checkout share a project_hash but get
distinct worktree_hashes.
- `repo.rs` — `SnapshotRepo::open_or_init / snapshot / restore / list /
prune_older_than`. Shells out to system `git` (avoids `git2` LGPL
surface). Honors workspace `.gitignore` automatically.
- `prune.rs` — boot-time helper used by session_manager (next commit).
Default retention is 7 days.
Tests (real `git` invocations on tempdirs, env-mutating tests serialised
through the existing `crate::test_support::lock_test_env` mutex) cover:
snapshot creates a commit in the side repo only, restore reverts files,
list respects limit, prune drops aged commits, gitignore is honored,
and re-init is idempotent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- README: add a "Publishing your own skill" section explaining the
`github:owner/repo` install path, the multi-skill `skills/<name>/`
layout, and how to submit to the curated registry.
- config.example.toml: document `[skills] registry_url` /
`max_install_size_bytes` next to the existing `[network]` section so
users see the network-gate dependency in context.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Slash-command surface for the community-skill installer:
- `/skill install <github:owner/repo|https://...|<registry-name>>` parses
the spec via `InstallSource::parse`, calls `install_with_registry`, and
surfaces `NeedsApproval`/`NetworkDenied` with actionable messages
pointing at `[network]` config (we deliberately don't dispatch a modal
from the sync slash-command path; the underlying installer returns the
outcome so a future approval wiring can reuse it).
- `/skill update <name>` re-fetches and prints "no upstream change" when
the checksum matches.
- `/skill uninstall <name>` and `/skill trust <name>` both refuse to
touch system skills (no `.installed-from` marker).
- `/skills --remote` (or `/skills remote`) fetches the curated registry
through the same network gate and prints `name — description (source)`.
Internals:
- Sub-command dispatch happens in `run_skill` before activation lookup,
so a user can't accidentally activate a skill literally named
`install`. Async install/update/uninstall plumbed through
`tokio::task::block_in_place` + `Handle::current().block_on`, matching
the existing pattern in `commands/cycle.rs`.
- `installer_settings` loads `Config` on demand — `App` doesn't carry a
`Config` reference, and the cost of a single TOML parse is negligible
next to the network round-trip the install will make.
Config:
- New `[skills]` section in both `crates/tui/src/config.rs::Config` and
the workspace `crates/config/src/lib.rs::ConfigToml` with
`registry_url` (default: bundled raw GitHub index) and
`max_install_size_bytes` (default: 5 MiB).
- `merge_config` propagates the new field, default impls cover the
unset case.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>