diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c4dcc53..ed922227 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.8.40] - 2026-05-18 +### Added + +- **Configurable sub-agent per-step API timeout.** A new + `[subagents] api_timeout_secs` setting in `~/.deepseek/config.toml` + controls how long each sub-agent step will wait on a DeepSeek + `create_message` response before falling back. The value is clamped to + `1..=1800`; `0` or unset preserves the legacy 120-second default, so + existing installs see no behavior change. Long-thinking children (e.g. + heavy plan or review work behind `agent_open`) can extend the timeout + without recompiling (#1806, #1808). +- **Delegated file-write permissions for write-capable sub-agent roles.** + `implementer` and `custom` sub-agents may now run `Suggest`-level write + tools (`write_file`, `edit_file`, `apply_patch`) without the parent + runtime being auto-approved. Read-only stances (`explore`, `plan`, + `review`, `verifier`) and the default `general` role still bounce + approval-gated tools so they can't quietly mutate the workspace, and + `Required`-level tools (shell, etc.) still need parent auto-approve + regardless of role. Pick `implementer` (or pass an explicit `custom` + allowlist) when the delegated task needs to land file changes + (#1828, #1833). + ### Fixed - **WSL2 and headless Linux startup no longer blocks on clipboard init.** The @@ -73,6 +94,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 to persisted active turns after the long-connection client starts, and text chunking no longer splits emoji or other multi-code-unit characters. +### Changed + +- **Slash-command autocomplete ranks exact alias matches first.** Typing + `/q` now surfaces `/exit` (whose alias `q` is an exact match) above + `/clear` (which only matches by the longer pinyin alias `qingping`). + Within each rank tier the menu still falls back to alphabetical name + order for deterministic display (#1811). + ### Thanks Thanks to **jayzhu ([@zlh124](https://github.com/zlh124))** for the WSL2 @@ -85,8 +114,18 @@ composer work in #1748/#1749, plus the per-process log filename follow-up in passthrough, reasoning replay, thinking-only turn, and Windows quoting fixes in #1740, #1743, #1742, and #1744. Thanks to **Nightt ([@nightt5879](https://github.com/nightt5879))** for the Ctrl+C prompt restore -fix in #1764. Thanks to **Bevis** and the community reports that surfaced the -compaction failure mode addressed in this release. +fix in #1764. Thanks to **Ling ([@LING71671](https://github.com/LING71671); +commits as `www17 `)** for the configurable sub-agent API +timeout in #1808, harvested with `1..=1800` clamping and a fail-fast guard +so a stray `api_timeout_secs = 0` keeps the legacy 120-second default. +Thanks to **[@knqiufan](https://github.com/knqiufan)** for the sub-agent +file-write delegation work in #1833, harvested with structured approval- +gate semantics (`Implementer` and `Custom` only, never `Required`-level +tools) so write-capable children can actually land code without bypassing +the `Required` approval class. Thanks to **[@IIzzaya](https://github.com/IIzzaya)** +for the exact-alias-first slash-completion ordering idea in #1811, landed +with a focused regression test. Thanks to **Bevis** and the community reports +that surfaced the compaction failure mode addressed in this release. ## [0.8.39] - 2026-05-17 diff --git a/crates/tui/CHANGELOG.md b/crates/tui/CHANGELOG.md index 6c4dcc53..ed922227 100644 --- a/crates/tui/CHANGELOG.md +++ b/crates/tui/CHANGELOG.md @@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.8.40] - 2026-05-18 +### Added + +- **Configurable sub-agent per-step API timeout.** A new + `[subagents] api_timeout_secs` setting in `~/.deepseek/config.toml` + controls how long each sub-agent step will wait on a DeepSeek + `create_message` response before falling back. The value is clamped to + `1..=1800`; `0` or unset preserves the legacy 120-second default, so + existing installs see no behavior change. Long-thinking children (e.g. + heavy plan or review work behind `agent_open`) can extend the timeout + without recompiling (#1806, #1808). +- **Delegated file-write permissions for write-capable sub-agent roles.** + `implementer` and `custom` sub-agents may now run `Suggest`-level write + tools (`write_file`, `edit_file`, `apply_patch`) without the parent + runtime being auto-approved. Read-only stances (`explore`, `plan`, + `review`, `verifier`) and the default `general` role still bounce + approval-gated tools so they can't quietly mutate the workspace, and + `Required`-level tools (shell, etc.) still need parent auto-approve + regardless of role. Pick `implementer` (or pass an explicit `custom` + allowlist) when the delegated task needs to land file changes + (#1828, #1833). + ### Fixed - **WSL2 and headless Linux startup no longer blocks on clipboard init.** The @@ -73,6 +94,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 to persisted active turns after the long-connection client starts, and text chunking no longer splits emoji or other multi-code-unit characters. +### Changed + +- **Slash-command autocomplete ranks exact alias matches first.** Typing + `/q` now surfaces `/exit` (whose alias `q` is an exact match) above + `/clear` (which only matches by the longer pinyin alias `qingping`). + Within each rank tier the menu still falls back to alphabetical name + order for deterministic display (#1811). + ### Thanks Thanks to **jayzhu ([@zlh124](https://github.com/zlh124))** for the WSL2 @@ -85,8 +114,18 @@ composer work in #1748/#1749, plus the per-process log filename follow-up in passthrough, reasoning replay, thinking-only turn, and Windows quoting fixes in #1740, #1743, #1742, and #1744. Thanks to **Nightt ([@nightt5879](https://github.com/nightt5879))** for the Ctrl+C prompt restore -fix in #1764. Thanks to **Bevis** and the community reports that surfaced the -compaction failure mode addressed in this release. +fix in #1764. Thanks to **Ling ([@LING71671](https://github.com/LING71671); +commits as `www17 `)** for the configurable sub-agent API +timeout in #1808, harvested with `1..=1800` clamping and a fail-fast guard +so a stray `api_timeout_secs = 0` keeps the legacy 120-second default. +Thanks to **[@knqiufan](https://github.com/knqiufan)** for the sub-agent +file-write delegation work in #1833, harvested with structured approval- +gate semantics (`Implementer` and `Custom` only, never `Required`-level +tools) so write-capable children can actually land code without bypassing +the `Required` approval class. Thanks to **[@IIzzaya](https://github.com/IIzzaya)** +for the exact-alias-first slash-completion ordering idea in #1811, landed +with a focused regression test. Thanks to **Bevis** and the community reports +that surfaced the compaction failure mode addressed in this release. ## [0.8.39] - 2026-05-17 diff --git a/crates/tui/src/tui/widgets/mod.rs b/crates/tui/src/tui/widgets/mod.rs index 03b9a83b..2eb2c63a 100644 --- a/crates/tui/src/tui/widgets/mod.rs +++ b/crates/tui/src/tui/widgets/mod.rs @@ -2125,7 +2125,32 @@ pub(crate) fn slash_completion_hints( } } - entries.sort_by(|a, b| a.name.cmp(&b.name)); + // Rank exact-alias matches above prefix/alias matches so e.g. typing + // `/q` ranks `/exit` (alias `q` is an exact hit) above `/clear` (alias + // `qingping` only matches by prefix). Inside each tier, fall back to + // alphabetical name order for deterministic display (#1811). + let rank = |entry: &SlashMenuEntry| -> u8 { + if entry.is_skill { + return 3; + } + let command_key = entry.name.trim_start_matches('/'); + if command_key.eq_ignore_ascii_case(&prefix_lower) { + return 0; + } + if let Some(info) = commands::get_command_info(command_key) + && info + .aliases + .iter() + .any(|a| a.eq_ignore_ascii_case(&prefix_lower)) + { + return 0; + } + if command_key.to_ascii_lowercase().starts_with(&prefix_lower) { + return 1; + } + 2 + }; + entries.sort_by(|a, b| rank(a).cmp(&rank(b)).then_with(|| a.name.cmp(&b.name))); entries.dedup_by(|a, b| a.name == b.name); entries.into_iter().take(limit).collect() } @@ -2484,6 +2509,50 @@ mod tests { assert!(hints.iter().any(|hint| hint.name == "/links")); } + #[test] + fn slash_completion_hints_rank_exact_alias_above_prefix_alias() { + // `/q` should rank `/exit` (exact alias `q`) above `/clear` (alias + // `qingping` only matches by prefix). Before #1811 the entries were + // sorted alphabetically, so `/clear` shadowed `/exit` even though + // the user typed the exact alias for `/exit`. + let hints = slash_completion_hints("/q", 128, &[], Locale::En, None, ApiProvider::Deepseek); + let names: Vec<&str> = hints.iter().map(|h| h.name.as_str()).collect(); + let exit_pos = names + .iter() + .position(|n| *n == "/exit") + .expect("/exit should appear when typing /q (alias `q`)"); + let clear_pos = names + .iter() + .position(|n| *n == "/clear") + .expect("/clear should still appear when typing /q (alias `qingping`)"); + assert!( + exit_pos < clear_pos, + "expected /exit to rank above /clear for prefix /q, got {names:?}" + ); + } + + #[test] + fn slash_completion_hints_keep_prefix_match_alphabetical_within_tier() { + // Within the same rank tier (no exact-alias match), entries fall + // back to alphabetical name order, same as the prior behavior. + let hints = + slash_completion_hints("/co", 128, &[], Locale::En, None, ApiProvider::Deepseek); + let names: Vec<&str> = hints + .iter() + .map(|h| h.name.as_str()) + .filter(|n| n.starts_with("/co")) + .collect(); + let sorted = { + let mut copy = names.clone(); + copy.sort(); + copy + }; + assert_eq!( + names, sorted, + "tied entries (no exact-alias match) should stay alphabetical" + ); + } + #[test] fn slash_completion_hints_exclude_set_and_deepseek_commands() { let hints = slash_completion_hints("/", 128, &[], Locale::En, None, ApiProvider::Deepseek);