From 874e8b4b78a3f888008aea7ef6e1858b6bb4cd17 Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Mon, 4 May 2026 04:22:38 -0500 Subject: [PATCH] feat(prompts,tui): cache awareness in agent prompt + slash prefix Enter (#573) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two related polish items wrapped together because both touch how the user perceives the model's context behavior. ### Cache awareness in the agent prompt The system prompt's Context Management section already lives inside the volatile-content-last invariant — but the model never knew *why* the prompt is shaped that way, or that it has any agency over keeping the cache hit rate up. Added a `### Prompt-cache awareness` subsection (Agent / Yolo modes) with five concrete dos-and-don'ts: - Append, don't reorder. - Don't paraphrase quoted content (refer back by path). - Use `/compact` as a hard reset, not a tweak. - Read once, refer back instead of re-reading. - Watch the `cache hit %` chip — red < 40%, yellow < 80%. The chip itself already exists in the default footer status set (`StatusItem::Cache`); the prompt addition closes the loop so the model treats it as a real signal instead of a passive readout. ### #573 — typing `/mo` + Enter activates the first matching command Previously a partial slash command + Enter sent the literal `/mo` as a turn. The popup was already showing `/model` highlighted, so the user expectation (and the OPENCODE behavior the issue cites) is that Enter runs the highlight. The fix routes Enter through `apply_slash_menu_selection` first when the popup is open and the input starts with `/`. If the popup is empty (no matches) the legacy submit path still fires — Enter on a non-slash line is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/tui/src/prompts.rs | 9 ++++++++- crates/tui/src/tui/ui.rs | 13 +++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/tui/src/prompts.rs b/crates/tui/src/prompts.rs index 26913357..9f1eeb76 100644 --- a/crates/tui/src/prompts.rs +++ b/crates/tui/src/prompts.rs @@ -357,7 +357,14 @@ pub fn system_prompt_for_mode_with_context_skills_and_session( 1. Use `/compact` to summarize earlier context and free up space\n\ 2. The system will preserve important information (files you're working on, recent messages, tool results)\n\ 3. After compaction, you'll see a summary of what was discussed and can continue seamlessly\n\n\ - If you notice context is getting long (>80%), proactively suggest using `/compact` to the user." + If you notice context is getting long (>80%), proactively suggest using `/compact` to the user.\n\n\ + ### Prompt-cache awareness\n\n\ + DeepSeek caches the longest *byte-stable prefix* of every request and charges roughly 100× less for cache-hit tokens than miss tokens. The system prompt above is layered most-static-first specifically so the prefix stays stable turn-over-turn. To keep cache hits high:\n\ + - **Append, don't reorder.** New context goes at the end (latest user / tool messages). Reshuffling earlier messages or rewriting their content invalidates the cache for everything after the change.\n\ + - **Don't paraphrase quoted content.** If you've already read a file, refer to it by path or line range instead of re-quoting it with different formatting.\n\ + - **Use `/compact` as a hard reset, not a tweak.** Compaction is meant for when the cache is already losing — it intentionally rewrites the prefix to a shorter summary. Don't trigger it for small wins.\n\ + - **Read once, refer back.** Re-reading the same file produces a different tool-result envelope than the prior read; it's cheaper to scroll back than to re-fetch.\n\ + - **Footer chip:** the `cache hit %` chip turns red below 40% and yellow below 80%. If it's been red for several turns, that's a signal to consolidate." ); } diff --git a/crates/tui/src/tui/ui.rs b/crates/tui/src/tui/ui.rs index f16aa259..23f1588d 100644 --- a/crates/tui/src/tui/ui.rs +++ b/crates/tui/src/tui/ui.rs @@ -2381,6 +2381,19 @@ async fn run_event_loop( } } KeyCode::Enter => { + // #573: when the user typed a slash-command prefix that + // the popup is matching (e.g. `/mo` → `/model`), Enter + // should run the *highlighted match* rather than + // sending the literal `/mo` text. Only kick in when the + // popup has at least one entry; otherwise fall through + // to the legacy submit path. + if slash_menu_open + && !slash_menu_entries.is_empty() + && app.input.starts_with('/') + && apply_slash_menu_selection(app, &slash_menu_entries, false) + { + app.close_slash_menu(); + } if let Some(input) = app.submit_input() { if handle_plan_choice(app, &engine_handle, &input).await? { continue;