Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
0428f08
fix(tests): cover approval decision branches
tuohai666 May 9, 2026
fd5a0aa
fix(tests): cover hook event dispatch paths
tuohai666 May 9, 2026
39fd537
docs(tui): clarify Windows mouse capture behavior
Oliver-ZPLiu May 8, 2026
682e915
fix: retry quota errors returned as HTTP 400
dst1213 May 8, 2026
250953a
feat(tools/agent_spawn): teach parent that subagent results are self-…
THINKER-ONLY May 8, 2026
4f8eff0
refactor: unify mode switching under /mode
reidliu41 May 9, 2026
24ec083
Add runtime status command
reidliu41 May 8, 2026
0ccd4e7
Add feedback command for GitHub links
reidliu41 May 8, 2026
0fedee0
feat(tui): add session artifact metadata
THINKER-ONLY May 9, 2026
c227a80
docs(readme): sync zh-CN with run pr dispatcher path
whtis May 8, 2026
665801b
fix(cli): forward --yolo to TUI binary via DEEPSEEK_YOLO env
fuleinist May 8, 2026
fddda04
fix(tui): add composer_arrows_scroll config option for trackpad termi…
lbcheng888 May 8, 2026
cdcb907
feat(project-context): load global AGENTS fallback
manaskarra May 8, 2026
0866fd6
fix(tui): honor deepseekignore in mention fallback
FluxForgeLab May 9, 2026
a617e3a
fix: add missing closing brace in project_context tests
Hmbown May 10, 2026
9f2b8a5
fix(tui): move tolerance to module-level const, add total helpers
lbcheng888 May 8, 2026
3cbd336
perf(tui): pre-compute tool output summaries and collapse live view
lbcheng888 May 7, 2026
0ab0d77
feat(tui): add card-rail (╭ │ ╰) boxing to tool output cells
lbcheng888 May 7, 2026
b024a92
feat: persist provider/model per-provider in settings
imkingjh999 May 9, 2026
9fae156
fix: address PR review feedback
imkingjh999 May 9, 2026
a80c318
fix: only use default_model fallback for DeepSeek providers
imkingjh999 May 9, 2026
5065092
fix: let OPENAI_MODEL env override config.toml provider model
imkingjh999 May 9, 2026
cb084d1
style: fix fmt and clippy warnings
imkingjh999 May 9, 2026
6c25a18
chore(release): bump to v0.8.27, add CHANGELOG
Hmbown May 10, 2026
4c3b24a
chore: update Cargo.lock for v0.8.27
Hmbown May 10, 2026
b8f01f1
fix: resolve clippy warnings from cherry-picked PRs
Hmbown May 10, 2026
fe0673d
test: ignore unwired #1270 tests; mark for v0.8.28 follow-up
Hmbown May 10, 2026
abf3fa6
fix(tui): drop destructive 2J/3J from viewport reset to fix flicker
Hmbown May 10, 2026
328e3bd
fix(skills): surface common-cause hints on /skills --remote / sync er…
Hmbown May 10, 2026
aea6bb5
feat(tui): pager copy-out via c / y key (#1354)
Hmbown May 10, 2026
be54a04
fix(markdown): hard-break overlong words to stop right-edge overflow
Hmbown May 10, 2026
21f9e9d
feat(tui): context-sensitive Ctrl+C — copy / cancel / arm-exit (#1337…
Hmbown May 10, 2026
0ee7017
feat(mcp): lazy auto-reload of pool on mcp.json content change (#1267…
Hmbown May 10, 2026
499937b
feat(tools): add model-callable notify tool (#1322)
Hmbown May 10, 2026
675a3c3
docs(changelog): reframe v0.8.27 opener to reflect bug-sweep scope
Hmbown May 10, 2026
524c513
chore: workspace clippy + missing-field fix-up for preflight
Hmbown May 10, 2026
8bf2557
feat(tui): consolidate large pastes at paste-time + auto-disable burst
Hmbown May 10, 2026
f267d4b
fix(tui): paste-burst detects short CJK first line as paste (#1302)
Hmbown May 10, 2026
3abd4dd
feat(tui): localize onboarding screens (api key, trust, tips, picker)
Hmbown May 10, 2026
c871968
feat(skills): /skills <prefix> filters the local list (#1318)
Hmbown May 10, 2026
8956b69
fix(mcp): validate path inside mcp_config_mtime (CodeQL defensive)
Hmbown May 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
642 changes: 642 additions & 0 deletions .claude/HANDOFF_v0.8.27_user_issues.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
# DEEPSEEK_APPROVAL_POLICY=on-request
# DEEPSEEK_SANDBOX_MODE=workspace-write
# DEEPSEEK_ALLOW_SHELL=true
# DEEPSEEK_YOLO=true

# Optional extension paths
# DEEPSEEK_SKILLS_DIR=~/.deepseek/skills
Expand Down
232 changes: 232 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,232 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.8.27] - 2026-05-10

A polish release bundling 17 community PRs plus a focused user-issue
sweep over the 24–48 hours after v0.8.26 shipped. Headline fixes:
cross-terminal flicker on Ghostty / VSCode / Win10 conhost (most-
reported v0.8.26 regression), long-text right-edge overflow, an
in-app pager copy-out, context-sensitive Ctrl+C, an MCP pool that
auto-reloads on config changes, and a model-callable `notify` tool.
Big thanks to every contributor below.

### Added

- **Unified `/mode` command** (#1247) — `/mode [agent|plan|yolo|1|2|3]`
replaces the separate `/agent`, `/plan`, and `/yolo` commands. Running
`/mode` without arguments opens a picker modal. The legacy aliases
(`/yolo`, `/agent`, `/plan`) are kept as compatibility shorthands.
Thanks **@reidliu41**.
- **`/status` runtime diagnostics** (#1223) — shows version, provider,
model, workspace, mode, permissions, context-window usage, cache
hit/miss, and session cost. Previously `/status` was an alias for
`/statusline` (footer config); that alias is now `/statusline` only.
Thanks **@reidliu41**.
- **`/feedback` command** (#1185) — opens the matching GitHub issue
template (bug report, feature request) in the browser. Security
vulnerability reports route through the project's security policy
page first. Thanks **@reidliu41**.
- **Session artifact metadata** (#1220) — large tool outputs spilled to
the session artifacts directory are now tracked in a durable metadata
index, so saved sessions retain references across save/restore cycles.
Thanks **@THINKER-ONLY**.
- **Subagent results are self-reports** (#1140) — the compacted result
summary now notes that child-agent outputs are unverified self-reports.
The parent model should verify side effects with tools like `read_file`
or `list_dir` before claiming success. Thanks **@THINKER-ONLY**.
- **Global AGENTS.md fallback** (#1197) — when the workspace and its
parents don't provide project instructions, the TUI now loads
`~/.deepseek/AGENTS.md` before falling back to auto-generated
instructions. Repo-local context still takes priority.
Thanks **@manaskarra**.
- **`--yolo` forwarded from CLI to TUI** (#1233) — the `deepseek --yolo`
flag now propagates through the dispatcher to the TUI binary via
`DEEPSEEK_YOLO=true`. Previously the flag set `yolo` in the CLI
process but the TUI session started in its default mode.
Thanks **@fuleinist**.
- **`composer_arrows_scroll` config** (#1211) — a new
`tui.composer_arrows_scroll` option (default `false`) makes plain
Up/Down arrow keys scroll the transcript when the composer is empty,
instead of navigating input history. Helpful for terminals that map
trackpad gestures to arrow keys. Thanks **@lbcheng888**.
- **Session cost persistence** (#1192) — accumulated costs (session +
sub-agents, both USD and CNY) and the displayed-cost high-water mark
now survive session save/restore, so the monotonic cost guarantee
(#244) holds across restarts. Thanks **@lbcheng888**.
- **Provider-aware model picker and provider persistence** (#1320) —
switching providers now persists the choice to
`~/.deepseek/settings.toml` so it survives restarts. The model
picker hides DeepSeek-specific models when a non-DeepSeek provider
is active. `OPENAI_MODEL` env var now overrides the per-provider
model rather than the global `default_text_model`. Bailian / ZhiPu
Coding Plan endpoints are now supported.
Thanks **@imkingjh999**.
- **HTTP User-Agent header** (#1320) — all outbound API requests now
carry `deepseek-tui/{version}` in the User-Agent, matching the format
`fetch_url` already uses. Thanks **@imkingjh999**.

### Fixed

- **Cross-terminal flicker on TurnComplete / focus / resize** (#1119,
#1260, #1295, #1352, #1356, #1363, #1366) — the viewport-reset
sequence emitted before each forced repaint no longer includes
`\x1b[2J\x1b[3J`. Combined with the immediately-following ratatui
`terminal.clear()`, the destructive pair produced a double-clear that
Ghostty, the VSCode integrated terminal, and Win10 conhost rendered
as a visible blank-then-repaint flicker. The lighter sequence
(`\x1b[r\x1b[?6l\x1b[H`) plus the alt-screen buffer's double-buffering
handles viewport correctness without flicker. macOS Terminal.app /
iTerm2 / alacritty users were already unaffected and remain so.
- **`/skills --remote` and `/skills sync` diagnostics** (#1329) — the
underlying anyhow chain has always been formatted with `{err:#}`, but
the chain alone is often opaque (e.g. "error sending request"). The
error message now appends a one-line hint when the chain matches a
common failure pattern: DNS / connection refused / TLS / 4xx / 429 /
timeout. Each hint points at the most likely cause and a concrete
next step.

### Added

- **Pager copy-out** (#1354) — full-screen pagers (`Alt+V` tool details,
`Ctrl+O` thinking content, shell-job / task / MCP-manager pagers, and
the selection pager) now accept `c` or `y` to copy the entire body to
the system clipboard. The pager intercepts mouse capture so terminal-
native selection isn't available inside it; this restores the
copy-out path that users on macOS / Windows / WSL expect. The footer
hint now reads `… / search c copy q/Esc close`. A status toast
confirms success ("Pager content copied"), empty-body, or failure.
- **`notify` tool** (#1322) — model-callable desktop notification.
Always-loaded (no ToolSearch round-trip). Routes through the existing
`tui::notifications` infrastructure: OSC 9 on iTerm2 / Ghostty /
WezTerm, BEL fallback on macOS / Linux, `MessageBeep` on Windows when
explicitly opted in. Honours the user's `[notifications].method`
config — when set to `off`, the tool is a silent no-op. Title and
body are length-capped (80 / 200 chars) on character (not byte)
boundaries to keep the OSC 9 escape clean and avoid mid-grapheme
truncation. The tool description steers the model away from chatter:
use only when a long-running task completes or genuinely needs the
user's attention.

### Fixed (cont.)

- **Long output text overflowed the right edge** (#1344, #1351) —
paragraph rendering (`render_line_with_links`) and code-block
wrapping (`wrap_text` for `Block::Code`) were word-based: a single
word wider than the available column was placed alone on a line and
silently overflowed. Long URLs, paths, hashes, and no-whitespace CJK
runs all hit this. Both paths now hard-break overlong words at the
character level, matching the v0.8.25 fix for table cells. The
rendered width is capped at the budget for every line; full content
is preserved across wrapped segments. Snapshot-style tests pin the
invariant at widths 40, 60, 80, and 120.

### Changed

- **`Ctrl+C` now copies an active transcript selection** (#1337) — on
Windows, plain `Ctrl+C` is the OS-wide copy chord, and treating it
as "exit" stole work whenever a user copy-pasted from the
transcript. `Ctrl+C` is now a four-stage decision: 1) selection
active → copy + clear (matches the OS convention); 2) turn in
flight → cancel (unchanged); 3) quit-armed within 2s → exit cleanly
(unchanged); 4) idle, no selection → arm the 2-second
"press Ctrl+C again to quit" prompt (unchanged). The decision is
factored into a `CtrlCDisposition` helper with a unit-tested
priority table. `Cmd+C` (macOS) and `Ctrl+Shift+C` continue to copy
unchanged.
- **Cancel-key discoverability hint on turn start** (#1367) — when a
turn begins, the status-message slot now surfaces "Press Esc or
Ctrl+C to cancel" if the slot is otherwise empty. Real transient
status messages still take precedence; the hint clears as soon as
any other update fires. Closes the loop on users who didn't know
how to interrupt a long-running turn.
- **Lazy auto-reload of MCP pool on config-file change** (#1267 part 2) —
v0.8.26 surfaced the underlying spawn errors; v0.8.27 closes the
loop on the second half of the report (manual `/mcp reload` after
`~/.deepseek/mcp.json` edits). `McpPool::get_or_connect` now does a
cheap `stat` + content-hash check before each connection lookup. If
the on-disk file's mtime moved AND its content hash changed since
the pool was loaded, all live connections are dropped so the next
`get_or_connect` reattaches under the new config. Pool-construction
via `McpPool::new` (tests, ad-hoc snapshots) is unaffected — only
pools built with `from_config_path` watch the source file. No file
watcher; no long-lived task. mtime-only churn (touched but
byte-unchanged content) does not trigger a reload, so networked
filesystems with coarse mtime granularity won't churn the pool.
- **Paste consolidation now happens at paste time, not submit time** —
large bracketed pastes that exceed the 16 000-char safety cap are
now folded into a workspace `.deepseek/pastes/paste-…md` file and
swapped for an `@`-mention immediately on paste, instead of waiting
until the user presses Enter. The user sees the `@`-mention in the
composer (and the "consolidated → @mention" toast) before deciding
whether to send, eliminating the "I pressed Enter and an `@`-mention
appeared in the chat I didn't authorise" surprise. The submit-time
consolidation remains as a safety net for any other code path that
fills the buffer above the cap, so the cap is still enforced exactly
once.
- **Auto-disable paste-burst once bracketed paste verified** — the
rapid-keystroke paste-burst heuristic (default-on for terminals
without bracketed paste) used to keep running on every session.
Once a real `Event::Paste` arrives in a session, paste-burst now
short-circuits — bracketed paste is verified working, and running
the heuristic alongside it just creates false positives on fast
typing / IME commits / autocomplete bursts. Terminals that never
deliver bracketed paste (the original target audience) are
unaffected; the heuristic still fires there.
- **Short CJK multi-line paste no longer auto-submits first line**
(#1302) — pasting `请联网搜索:\nSTM32 …` (short non-ASCII first line
followed by a newline) used to fail the paste-burst detection
heuristic because the first line had no whitespace and was under
the 16-char threshold; the trailing pasted newline then fell
through as a real Enter and submitted the first line on its own.
The heuristic now treats any non-ASCII run as paste-like, so the
Enter is absorbed into the burst buffer. Thanks **@reidliu41**
(PR #1342).
- **Onboarding screens render in the selected language** — when a
user picked 简体中文 / 日本語 / Português (Brasil) at the language
step, every subsequent screen (API key entry, workspace trust
prompt, final tips) used to remain in English. The
`set_locale_from_onboarding` path now drives the title, body
copy, hints, and footer of each onboarding screen through the
localization table, so once you pick your language the rest of
the flow is in that language. Particularly nice for users on
CJK input methods who want to avoid IME juggling during setup.
- **`/skills <prefix>` filters the local skills list** (#1318) — on
top of the v0.8.26 inter-row spacing (#1328 from @reidliu41), the
list now narrows to skills whose names start with the typed
prefix. Case-insensitive. The header reflects matched count vs
registry total; an empty match set says so explicitly and points
back at unfiltered `/skills`. `--remote` and `sync` stay
reserved as subcommands; any `--`-prefixed argument is rejected
rather than being silently treated as a no-match prefix.
- **HTTP 400 quota errors retried** (#1203) — some OpenAI-compatible
gateways return quota/rate-limit errors as HTTP 400 instead of 429.
These are now classified as retryable `RateLimited` errors.
Thanks **@dst1213**.
- **Explicit hidden/ignored file completions** (#1270) — when the user
types an explicit path starting with `.` (e.g., `.deepseek/commands/`),
the file-completion system now surfaces hidden and gitignored entries
while still respecting `.deepseekignore`. Thanks **@SamhandsomeLee**.

### Changed

- **Windows mouse capture docs** (#1181) — the `--mouse-capture` help
text and the configuration docs now mention scrollbar dragging and
note that raw terminal selection on Windows may cross the sidebar.
Thanks **@Oliver-ZPLiu**.
- **README zh-CN sync** (#1235) — the Chinese README's quickstart section
now shows `deepseek run pr <N>` instead of the outdated
`deepseek pr <N>`. Thanks **@whtis**.
- **Tool output render perf** (#1098) — tool output summaries and the
"is this a diff?" check are now pre-computed once at cell creation
instead of re-parsed every frame. Tool output cells also got a visual
card-rail (`╭ │ ╰`) for clearer grouping. Thanks **@lbcheng888**.

### Internal

- Test coverage for approval decision branches (@tuohai666, #1316)
- Test coverage for hook event dispatch paths (@tuohai666, #1317)

## [0.8.26] - 2026-05-09

A security + polish release. Two responsibly-disclosed issues were
Expand Down Expand Up @@ -473,6 +699,12 @@ TUI, runtime, and docs. Big thanks to **Reid (@reidliu41)**,

## [0.8.20] - 2026-05-08

### Added
- **Global AGENTS.md fallback** - when a workspace and its parents do not
provide project instructions, DeepSeek TUI now loads `~/.deepseek/AGENTS.md`
before falling back to auto-generated `.deepseek/instructions.md`, keeping
repo-local instructions higher priority while supporting shared defaults.

### Fixed
- **Chinese reasoning stays Chinese** - restore the #588 language contract after
the deterministic environment prompt regressed it. The latest user message now
Expand Down
28 changes: 14 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ default-members = ["crates/cli", "crates/app-server", "crates/tui"]
resolver = "2"

[workspace.package]
version = "0.8.26"
version = "0.8.27"
edition = "2024"
# Rust 1.88 stabilized `let_chains` in `if`/`while` conditions, which the
# codebase relies on extensively. Cargo enforces this so users on older
Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ deepseek resume --last # 恢复最近会话
deepseek resume <SESSION_ID> # 按 UUID 恢复指定会话
deepseek fork <SESSION_ID> # 在指定轮次分叉会话
deepseek serve --http # HTTP/SSE API 服务
deepseek pr <N> # 获取 PR 并预填审查提示
deepseek run pr <N> # 获取 PR 并预填审查提示
deepseek mcp list # 列出已配置 MCP 服务器
deepseek mcp validate # 校验 MCP 配置和连接
deepseek mcp-server # 启动 dispatcher MCP stdio 服务器
Expand Down
Loading
Loading