qwen-code/packages/cli/src/ui/commands
Shaojin Wen afbb5e71db
fix(cli): rework session recap rendering and add blur threshold setting (#3482)
* feat(cli): make recap away-threshold configurable

The 5-minute blur threshold was hard-coded. Confirmed from Claude
Code's own binary (v2.1.113) that 5 minutes is their default as well
(and that they shift to 60 minutes when 1h prompt-cache is active) —
so the default stays, but expose it as `general.sessionRecapAway
ThresholdMinutes` for users who briefly alt-tab often and don't want
recaps piling up, or who want to lower it for testing.

Non-positive / unset values fall back to the 5-minute default, so
dropping the key has the same behavior as before.

* fix(core): align recap prompt with Claude Code (1-2 sentences, ≤40 words)

The earlier "exactly one sentence, 80-char cap" was an over-correction
to a single in-the-moment ask. Going back to it: the natural shape of
"current task + next action" is two clauses, and forcing them into a
single sentence either crams them with a semicolon or drops the next
action entirely on complex sessions.

Adopt Claude Code's prompt verbatim (extracted from the v2.1.113
binary): "under 40 words, 1-2 plain sentences, no markdown. Lead with
the overall goal and current task, then the one next action. Skip
root-cause narrative, fix internals, secondary to-dos, and em-dash
tangents." Add a Chinese-budget note (~80 chars) and keep the
<recap>...</recap> wrapping that protects against reasoning-model
preambles leaking into the UI.

The sticky banner already re-measures controls height when the
recap toggles, so a 2-line render lays out cleanly.

Sweep "one-line" out of user-facing copy (settings description,
slash-command description, feature docs, design doc) so the
documentation matches the new shape.

* fix(cli): restore "one-line" in user-facing recap copy

Verified from the Claude Code v2.1.113 binary that the slash-command
description IS literally "Generate a one-line session recap now" even
though the underlying prompt allows 1-2 sentences. Claude Code is
deliberately setting a tighter user expectation than the prompt
guarantees, which keeps the surface feel "glanceable".

Mirror that asymmetry: keep the prompt at 1-2 sentences (the previous
commit) for behavioral parity, but put "one-line" back in the user-
visible copy (slash-command description, settings description, user
docs). Internal design doc keeps the accurate "1-2 sentence" wording.

* fix(cli): render recap inline in history to match Claude Code

Earlier I read the user's complaint that the recap "scrolled away" as
"the recap should be sticky above the input box," and built a sticky
banner accordingly. Disassembly of the Claude Code v2.1.113 binary
shows the actual behavior is the opposite: their away_summary is a
plain `type:"system", subtype:"away_summary"` message dispatched
through the standard message renderer (no Static, no anchor, no
flexbox pinning) — it scrolls with the conversation like every other
system message.

Tear out the sticky-banner machinery so recap matches that:

- Recap is back in the `HistoryItemWithoutId` union and `addItem`'d
  into history (both from `/recap` and from auto-trigger), so it
  serializes into session saves and behaves like every other history
  item — no special clear paths, no resume-wrapper, no layout-effect
  re-measure dance.
- `useAwaySummary` takes `addItem` again instead of a setter callback.
- `AwayRecapMessage` renders the way Claude Code does: a 2-column
  gutter with `※`, then bold "recap: " and italic content, all in
  dim color. Drop the prior `StatusMessage`-shaped layout that fused
  prefix and label into "※ recap:".
- Remove the AppContainer plumbing, the slashCommandProcessor state,
  the UIStateContext fields, the DefaultAppLayout / ScreenReader
  placement blocks, the test-utils mocks, and the noninteractive
  stub. Restore `useResumeCommand.handleResume` to a void return
  since callers no longer need the success boolean.

Sweep the design doc so the architecture diagram, files table, and
hook deps reflect the inline-history flow.

* fix(cli): dedupe back-to-back auto-recaps with no new user turns between

Two consecutive blur cycles, each over the threshold but with no new
user activity in between, would each fire their own auto-recap and
add two near-duplicate entries to history (same task, slightly
different wording from temperature-driven LLM variance). Reported
case: leaving the terminal twice while a /review of one PR was
still on screen produced two recaps both about that same review.

Add a `shouldFireRecap` gate before kicking off the LLM call:

- Need at least 3 user messages in history total (don't fire on a
  near-empty session).
- If a previous away_recap is already in history, need at least 2
  new user messages since that one before another can fire.

Same shape as Claude Code's `Ic1` gate (`Sc1=3`, `Rc1=2`). Read
history through a ref so this isn't in the effect's deps and the
effect doesn't re-run on every message.

* fix(cli): type useResumeCommand.handleResume as Promise<void>

Per gemini review on #3482: the interface declared this as `() => void`
but the implementation is `async` and returns `Promise<void>`. The
mismatch silently lost the chainable promise — tests had to launder
it through `as unknown as Promise<void> | undefined` just to await.

Tighten the interface to `Promise<void>` and drop the cast in the
"closes the dialog immediately" test.

* fix(cli): persist auto-fired recap to chat recording so /resume keeps it

Per yiliang114 review on #3482: the manual `/recap` path persists across
`/resume` because the slash-command processor records every output
history item via `chatRecorder.recordSlashCommand({ phase: 'result',
outputHistoryItems })`, but the auto path called `addItem` directly
and bypassed that recorder. The result was an asymmetry where users
who triggered recap manually saw it after `/resume`, while users whose
recap fired automatically lost it.

Mirror the manual recording from useAwaySummary's `.then` callback —
record only the `result` phase (not invocation, since we don't want
a fake `> /recap` user line replayed) with the away-recap item as the
single output. Wrapped in try/catch because recap is best-effort and
must never surface a failure to the user.

Add useAwaySummary.test.ts covering:
- the recording path is taken on a successful auto-trigger
- the dedup gate (`shouldFireRecap`) suppresses the LLM call entirely,
  including the recording, when no new user turns happened since the
  last recap

* fix(cli): cast recap item via spread to satisfy strict tsc --build

CI's `tsc --build` (stricter than local `tsc --noEmit`) rejected the
direct `item as Record<string, unknown>` cast: HistoryItemAwayRecap's
literal `type: 'away_recap'` field doesn't overlap with `unknown`,
TS2352. Use the `{ ...item } as Record<string, unknown>` spread
pattern that the rest of the codebase (arenaCommand,
slashCommandProcessor's serializer) already uses for the same
SlashCommandRecordPayload field.
2026-04-21 14:39:13 +08:00
..
aboutCommand.test.ts feat(cli): refactor about dialog and add proxy field 2026-01-19 10:54:45 +08:00
aboutCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
agentsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
approvalModeCommand.test.ts fix: handle setApprovalMode error in untrusted folders 2026-01-06 22:04:43 +08:00
approvalModeCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
arenaCommand.test.ts feat(core,cli)!: Implement in-process agent backend for arenas 2026-02-21 21:08:20 +08:00
arenaCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
authCommand.test.ts feat(i18n): add translations for "Configure authentication information for login" in multiple languages 2026-02-11 17:00:43 +08:00
authCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
btwCommand.test.ts fix(cli): use live context for /btw side questions (#3429) 2026-04-19 15:06:14 +08:00
btwCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
bugCommand.test.ts fix(cli): make /bug easier to open in terminals without hyperlink support (#3257) 2026-04-15 10:37:39 +08:00
bugCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
clearCommand.test.ts fix: resolve /clear command and ESC key lag caused by hooks system 2026-03-25 14:01:24 +08:00
clearCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
compressCommand.test.ts Merge tag 'v0.3.0' into chore/sync-gemini-cli-v0.3.0 2025-09-11 16:26:56 +08:00
compressCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
contextCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
copyCommand.test.ts refactor(debug): replace ConsolePatcher with debugLogger and update error reporting 2026-02-02 17:37:54 +08:00
copyCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
directoryCommand.test.tsx chore: clean up orphaned bfsFileSearch code and discoveryMaxDirs setting 2026-01-19 14:10:42 +08:00
directoryCommand.tsx refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
docsCommand.test.ts # 🚀 Sync Gemini CLI v0.2.1 - Major Feature Update (#483) 2025-09-01 14:48:55 +08:00
docsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
doctorCommand.test.ts feat(cli): add /doctor diagnostic command (#3404) 2026-04-19 19:25:55 +08:00
doctorCommand.ts feat(cli): add /doctor diagnostic command (#3404) 2026-04-19 19:25:55 +08:00
dreamCommand.ts feat(memory): managed auto-memory and auto-dream system (#3087) 2026-04-16 20:05:45 +08:00
editorCommand.test.ts update /editor to new slash command arch (#4153) 2025-07-17 00:27:36 +00:00
editorCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
exportCommand.test.ts fix: export command should use current session ID instead of loadLastSession 2026-03-11 11:16:29 +08:00
exportCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
extensionsCommand.test.ts fix mcp ui 2026-03-09 15:20:30 +08:00
extensionsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
forgetCommand.ts feat(memory): managed auto-memory and auto-dream system (#3087) 2026-04-16 20:05:45 +08:00
helpCommand.test.ts sync gemini-cli 0.1.17 2025-08-05 17:09:19 +08:00
helpCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
hooksCommand.test.ts feat(hooks): Add HTTP Hook, Function Hook and Async Hook support (#2827) 2026-04-16 10:10:33 +08:00
hooksCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
ideCommand.test.ts Add Gemini provider, remove legacy Google OAuth, and tune generation defaults 2025-12-19 16:26:54 +08:00
ideCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
initCommand.test.ts Merge branch 'main' into chore/sync-gemini-cli-v0.3.4 2025-09-16 19:51:32 +08:00
initCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
insightCommand.test.ts feat(vscode-ide-companion): support /insight command (#2593) 2026-04-20 10:02:18 +08:00
insightCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
languageCommand.test.ts fix: prevent output-language.md from being overwritten on startup 2026-04-03 10:13:44 +08:00
languageCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
mcpCommand.test.ts feat(mcp): update i18n locales and tests for MCP TUI 2026-02-25 16:28:29 +08:00
mcpCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
memoryCommand.test.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
memoryCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
modelCommand.test.ts fix: add --fast hint to /model description for discoverability (#3086) 2026-04-10 13:49:28 +08:00
modelCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
permissionsCommand.test.ts feat test tool permissions 2026-03-10 16:30:22 +08:00
permissionsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
planCommand.test.ts fix: rename /plan execute to /plan exit 2026-04-08 10:21:00 +08:00
planCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
quitCommand.test.ts updated /quit to use new slash command arch (#4259) 2025-07-17 02:40:56 +00:00
quitCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
recapCommand.ts fix(cli): rework session recap rendering and add blur threshold setting (#3482) 2026-04-21 14:39:13 +08:00
rememberCommand.ts feat(memory): managed auto-memory and auto-dream system (#3087) 2026-04-16 20:05:45 +08:00
restoreCommand.test.ts Rename more references 2025-12-11 11:14:11 +01:00
restoreCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
resumeCommand.test.ts Add tests for /resume command and update SettingsDialog snapshots 2025-12-13 14:03:35 +01:00
resumeCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
settingsCommand.test.ts fix: yargs locale 2025-08-25 18:34:41 +08:00
settingsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
setupGithubCommand.test.ts feat(core,cli): migrate console.debug to debugLogger (M3 Phase 1-3) 2026-01-25 20:57:25 +08:00
setupGithubCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
skillsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
statsCommand.test.ts updated /stats to use new slash command arch (#4146) 2025-07-15 20:10:04 +00:00
statsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
statuslineCommand.test.ts test: add comprehensive tests for useStatusLine hook and statuslineCommand 2026-04-09 15:50:41 +08:00
statuslineCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
summaryCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
terminalSetupCommand.test.ts Explict imports & exports with type modifier (#3774) 2025-08-25 22:04:53 +00:00
terminalSetupCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
themeCommand.test.ts pre-release commit 2025-07-22 23:26:01 +08:00
themeCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
toolsCommand.test.ts Sync upstream Gemini-CLI v0.8.2 (#838) 2025-10-23 09:27:04 +08:00
toolsCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
trustCommand.test.ts feat(permissions): add permission system and rename folder trust command 2026-03-04 19:24:43 +08:00
trustCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00
types.ts fix(cli): rework session recap rendering and add blur threshold setting (#3482) 2026-04-21 14:39:13 +08:00
vimCommand.ts refactor(cli): replace slash command whitelist with capability-based filtering (Phase 1) (#3283) 2026-04-20 14:34:43 +08:00