chore(release): v0.8.17
A community-driven reliability release. Plan-mode safety, paste-Enter auto-submit, slash-menu skills coverage, the deepseek-cn endpoint preset, and a handful of platform / streaming / gateway-compat fixes, plus a small PTY-driven QA harness. See CHANGELOG.md for the full annotated change list with credits. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+100
@@ -5,6 +5,106 @@ 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.17] - 2026-05-07
|
||||
|
||||
A focused reliability release built almost entirely from community contributions.
|
||||
Fixes Plan-mode safety, paste-Enter auto-submit, slash-menu skills coverage, the
|
||||
`deepseek-cn` endpoint preset, and a handful of platform / streaming /
|
||||
gateway-compatibility issues. Also lands a small PTY-driven QA harness so the
|
||||
next round of TUI fixes can be verified against real terminal behaviour.
|
||||
|
||||
### Added
|
||||
- **`/theme` command** (#1057) — toggle between dark and light themes inline,
|
||||
without round-tripping through `/config`. Thanks @MengZ-super.
|
||||
- **PTY/frame-capture TUI QA harness** — new
|
||||
`crates/tui/tests/support/qa_harness/` lets integration tests spawn
|
||||
`deepseek-tui` in a real pseudo-terminal, send scripted keys / paste /
|
||||
resize, and assert on the parsed terminal frame plus the workspace
|
||||
filesystem. Initial scenarios cover boot smoke and the #1073 paste regression.
|
||||
Adding-a-scenario walkthrough lives in `crates/tui/tests/support/qa_harness/README.md`.
|
||||
|
||||
### Changed
|
||||
- **`deepseek-cn` provider preset now defaults to the official
|
||||
`https://api.deepseek.com` host** (#1079, #1084) — matches
|
||||
[api-docs.deepseek.com](https://api-docs.deepseek.com/). The legacy typo
|
||||
host `api.deepseeki.com` is still recognized in URL heuristics and chat-client
|
||||
normalization so existing user configs keep working. Thanks @Jefsky.
|
||||
- **Plan mode runs shell commands in a read-only sandbox** (#1077) — was
|
||||
`WorkspaceWrite` with the workspace as a writable root, which let
|
||||
`python -c "open('f','w').write('x')"` mutate files inside the workspace.
|
||||
Now `SandboxPolicy::ReadOnly`: no writes anywhere on the filesystem, no
|
||||
network. Read-only inspection commands (`ls`, `git log`, `grep`,
|
||||
`cargo metadata`, …) keep working through the per-platform sandbox; for
|
||||
anything that creates or modifies files, switch to Agent mode (`/agent`).
|
||||
Thanks @DI-HUO-MING-YI.
|
||||
|
||||
### Fixed
|
||||
- **Pasting multi-line text with a trailing newline no longer auto-submits**
|
||||
(#1073) — the composer's Enter handler now consults the paste-burst
|
||||
suppression state and either appends `\n` to the in-flight burst buffer or
|
||||
inserts it into the composer text directly, instead of falling through to
|
||||
`submit_input()`. Reproduced from the original Windows / PowerShell
|
||||
symptom; fix covers both the bracketed-paste and rapid-keystroke detection
|
||||
paths. Thanks @bevis-wong for the precise reproducer.
|
||||
- **Slash menu, `/skills`, and `/skill <name>` show project-local AND global
|
||||
skills** (#1068, #1083) — switched the cache to `discover_in_workspace`, so
|
||||
the UI surfaces stay in sync with the system-prompt skills block. Bonus
|
||||
fix: `SKILL.md` frontmatter values are now stripped of surrounding YAML
|
||||
quotes, so `name: "hud"` registers as `hud` and matches prefix lookup.
|
||||
Thanks @AlphaGogoo / @Duducoco.
|
||||
- **Windows shell output is decoded as UTF-8 even on non-UTF-8 system code
|
||||
pages** (#982, #1018) — Windows shell commands are now wrapped with
|
||||
`chcp 65001 >NUL & ` so subprocesses output UTF-8 instead of GBK / other
|
||||
ANSI code pages. `display_command` strips the prefix so transcripts and
|
||||
approval prompts stay clean. Thanks @chnjames.
|
||||
- **Stale snapshot `tmp_pack_*` files are cleaned up on startup** (#975,
|
||||
#1055) — interrupted side-repo git pack operations no longer leak orphaned
|
||||
temp files; `prune_unreachable_objects` runs during the regular prune
|
||||
cycle to drop loose objects from rolled-back snapshots. Closes the
|
||||
~30 GB+ disk-usage report. Thanks @axobase001.
|
||||
- **Window-resize artifacts on macOS Terminal.app and Windows ConHost are
|
||||
gone** (#993) — forces the resize-event size during the post-resize draw
|
||||
so ratatui's internal `autoresize()` cannot shrink the viewport back to a
|
||||
stale dimension and leave the newly-expanded area filled with stale
|
||||
content. Same class as #582 for additional emulator families. Thanks
|
||||
@ArronAI007.
|
||||
- **Streaming thinking blocks finalize cleanly on stream errors and
|
||||
restarts** (#861 partial, #1078) — the engine-error handler now drains
|
||||
the in-flight thinking block into the transcript instead of leaving the
|
||||
partial reasoning orphaned in `StreamingState`. Refactor extracts the
|
||||
thinking lifecycle into named helpers (`start_streaming_thinking_block`,
|
||||
`finalize_current_streaming_thinking`, `stash_reasoning_buffer_into_last_reasoning`).
|
||||
Thanks @reidliu41.
|
||||
- **OpenRouter and other custom-endpoint providers preserve explicit model
|
||||
IDs** (#1066) — when a provider has an explicit model AND a custom
|
||||
`base_url` (different from the provider default), the model name is no
|
||||
longer rewritten by provider-specific normalization. Lets OpenAI-compatible
|
||||
gateways accept bare IDs like `deepseek/deepseek-v4-pro`,
|
||||
`accounts/fireworks/models/...`, or `glm-5`. Thanks @THINKER-ONLY.
|
||||
- **Auto-generated `.deepseek/instructions.md` stabilizes the KV prefix
|
||||
cache** (#1080) — replaces the per-turn filesystem-scan fallback in
|
||||
`prompts.rs` with a real on-disk artifact when no context file exists, so
|
||||
the system prompt's prefix stays byte-stable across turns and prefix-cache
|
||||
hit-rate improves. The auto-generated file is plainly labelled and the
|
||||
user can edit or delete it freely. Thanks @lloydzhou.
|
||||
- **SSE responses behind compressing gateways decode correctly** (#1061) —
|
||||
enables reqwest's `gzip` and `brotli` features so streams through proxies
|
||||
that compress the response come through clean instead of as protocol
|
||||
corruption. Quiets one of the failure modes behind some "stuck working"
|
||||
reports. Thanks @MengZ-super.
|
||||
|
||||
### Notes for contributors
|
||||
|
||||
This release shifts the project's PR-handling philosophy: every contribution
|
||||
has value somewhere; the maintainer's job is to find it, use it, and credit
|
||||
the contributor — never to close a PR with nothing taken. If a PR is too
|
||||
large or scope-mixed to merge whole, useful commits / files / ideas are
|
||||
harvested directly rather than asking the contributor to split it. Trust
|
||||
boundary on credentials, sandbox, providers, publishing, telemetry,
|
||||
sponsorship, branding, and global prompts still requires explicit
|
||||
maintainer sign-off, but the burden of getting there is on us. See
|
||||
`AGENTS.md` for the full text.
|
||||
|
||||
## [0.8.16] - 2026-05-07
|
||||
|
||||
A focused hotfix for v0.8.15 regressions in RLM, sub-agent visibility, and
|
||||
|
||||
Generated
+14
-14
@@ -1152,7 +1152,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-agent"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"deepseek-config",
|
||||
"serde",
|
||||
@@ -1160,7 +1160,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-app-server"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -1182,7 +1182,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-config"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deepseek-secrets",
|
||||
@@ -1194,7 +1194,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-core"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@@ -1212,7 +1212,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-execpolicy"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deepseek-protocol",
|
||||
@@ -1221,7 +1221,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-hooks"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -1235,7 +1235,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-mcp"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -1244,7 +1244,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-protocol"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1252,7 +1252,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-secrets"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"keyring",
|
||||
@@ -1265,7 +1265,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-state"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@@ -1277,7 +1277,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-tools"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -1290,7 +1290,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-tui"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arboard",
|
||||
@@ -1351,7 +1351,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-tui-cli"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@@ -1375,7 +1375,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deepseek-tui-core"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ default-members = ["crates/cli", "crates/app-server", "crates/tui"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
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
|
||||
|
||||
@@ -7,5 +7,5 @@ repository.workspace = true
|
||||
description = "Model/provider registry and fallback strategy for DeepSeek workspace architecture"
|
||||
|
||||
[dependencies]
|
||||
deepseek-config = { path = "../config", version = "0.8.16" }
|
||||
deepseek-config = { path = "../config", version = "0.8.17" }
|
||||
serde.workspace = true
|
||||
|
||||
@@ -10,15 +10,15 @@ description = "Codex-style app-server transport for DeepSeek workspace architect
|
||||
anyhow.workspace = true
|
||||
axum.workspace = true
|
||||
clap.workspace = true
|
||||
deepseek-agent = { path = "../agent", version = "0.8.16" }
|
||||
deepseek-config = { path = "../config", version = "0.8.16" }
|
||||
deepseek-core = { path = "../core", version = "0.8.16" }
|
||||
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.16" }
|
||||
deepseek-hooks = { path = "../hooks", version = "0.8.16" }
|
||||
deepseek-mcp = { path = "../mcp", version = "0.8.16" }
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.16" }
|
||||
deepseek-state = { path = "../state", version = "0.8.16" }
|
||||
deepseek-tools = { path = "../tools", version = "0.8.16" }
|
||||
deepseek-agent = { path = "../agent", version = "0.8.17" }
|
||||
deepseek-config = { path = "../config", version = "0.8.17" }
|
||||
deepseek-core = { path = "../core", version = "0.8.17" }
|
||||
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.17" }
|
||||
deepseek-hooks = { path = "../hooks", version = "0.8.17" }
|
||||
deepseek-mcp = { path = "../mcp", version = "0.8.17" }
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.17" }
|
||||
deepseek-state = { path = "../state", version = "0.8.17" }
|
||||
deepseek-tools = { path = "../tools", version = "0.8.17" }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
@@ -14,13 +14,13 @@ path = "src/main.rs"
|
||||
anyhow.workspace = true
|
||||
clap.workspace = true
|
||||
clap_complete.workspace = true
|
||||
deepseek-agent = { path = "../agent", version = "0.8.16" }
|
||||
deepseek-app-server = { path = "../app-server", version = "0.8.16" }
|
||||
deepseek-config = { path = "../config", version = "0.8.16" }
|
||||
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.16" }
|
||||
deepseek-mcp = { path = "../mcp", version = "0.8.16" }
|
||||
deepseek-secrets = { path = "../secrets", version = "0.8.16" }
|
||||
deepseek-state = { path = "../state", version = "0.8.16" }
|
||||
deepseek-agent = { path = "../agent", version = "0.8.17" }
|
||||
deepseek-app-server = { path = "../app-server", version = "0.8.17" }
|
||||
deepseek-config = { path = "../config", version = "0.8.17" }
|
||||
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.17" }
|
||||
deepseek-mcp = { path = "../mcp", version = "0.8.17" }
|
||||
deepseek-secrets = { path = "../secrets", version = "0.8.17" }
|
||||
deepseek-state = { path = "../state", version = "0.8.17" }
|
||||
chrono.workspace = true
|
||||
dirs.workspace = true
|
||||
serde.workspace = true
|
||||
|
||||
@@ -8,7 +8,7 @@ description = "Config schema and precedence model for DeepSeek workspace archite
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
deepseek-secrets = { path = "../secrets", version = "0.8.16" }
|
||||
deepseek-secrets = { path = "../secrets", version = "0.8.17" }
|
||||
dirs.workspace = true
|
||||
serde.workspace = true
|
||||
toml.workspace = true
|
||||
|
||||
@@ -9,13 +9,13 @@ description = "Core runtime boundaries for DeepSeek workspace architecture"
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
chrono.workspace = true
|
||||
deepseek-agent = { path = "../agent", version = "0.8.16" }
|
||||
deepseek-config = { path = "../config", version = "0.8.16" }
|
||||
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.16" }
|
||||
deepseek-hooks = { path = "../hooks", version = "0.8.16" }
|
||||
deepseek-mcp = { path = "../mcp", version = "0.8.16" }
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.16" }
|
||||
deepseek-state = { path = "../state", version = "0.8.16" }
|
||||
deepseek-tools = { path = "../tools", version = "0.8.16" }
|
||||
deepseek-agent = { path = "../agent", version = "0.8.17" }
|
||||
deepseek-config = { path = "../config", version = "0.8.17" }
|
||||
deepseek-execpolicy = { path = "../execpolicy", version = "0.8.17" }
|
||||
deepseek-hooks = { path = "../hooks", version = "0.8.17" }
|
||||
deepseek-mcp = { path = "../mcp", version = "0.8.17" }
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.17" }
|
||||
deepseek-state = { path = "../state", version = "0.8.17" }
|
||||
deepseek-tools = { path = "../tools", version = "0.8.17" }
|
||||
serde_json.workspace = true
|
||||
uuid.workspace = true
|
||||
|
||||
@@ -8,5 +8,5 @@ description = "Execution policy and approval model parity for DeepSeek workspace
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.16" }
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.17" }
|
||||
serde.workspace = true
|
||||
|
||||
@@ -10,7 +10,7 @@ description = "Hook dispatch and notifications parity for DeepSeek workspace arc
|
||||
anyhow.workspace = true
|
||||
async-trait.workspace = true
|
||||
chrono.workspace = true
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.16" }
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.17" }
|
||||
reqwest.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
@@ -9,7 +9,7 @@ description = "Tool invocation lifecycle, schema validation, and scheduler paral
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
async-trait.workspace = true
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.16" }
|
||||
deepseek-protocol = { path = "../protocol", version = "0.8.17" }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
@@ -21,8 +21,8 @@ path = "src/main.rs"
|
||||
[dependencies]
|
||||
anyhow = "1.0.100"
|
||||
arboard = "3.4"
|
||||
deepseek-secrets = { path = "../secrets", version = "0.8.16" }
|
||||
deepseek-tools = { path = "../tools", version = "0.8.16" }
|
||||
deepseek-secrets = { path = "../secrets", version = "0.8.17" }
|
||||
deepseek-tools = { path = "../tools", version = "0.8.17" }
|
||||
schemaui = { version = "0.12.0", default-features = false, optional = true }
|
||||
async-stream = "0.3.6"
|
||||
async-trait = "0.1"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "deepseek-tui",
|
||||
"version": "0.8.16",
|
||||
"deepseekBinaryVersion": "0.8.16",
|
||||
"version": "0.8.17",
|
||||
"deepseekBinaryVersion": "0.8.17",
|
||||
"description": "Install and run deepseek and deepseek-tui binaries from GitHub release artifacts.",
|
||||
"author": "Hmbown",
|
||||
"license": "MIT",
|
||||
|
||||
Reference in New Issue
Block a user