返回 CodeWhale
compact.rs
根目录 / crates / tui / src / commands / groups / session / compact.rs
1 //! `/compact` command.
2
3 use super::CommandResult;
4
5 pub(in crate::commands) struct CompactCmd;
6
7 // ---------------------------------------------------------------------------
8 // FEAT-023 Phase 4 (D3/D6): portable pure registration. `/compact` parses and
9 // normalizes its focus argument and emits the existing receipt + action with
10 // no host context bundle (the baseline `App` parameter is unused).
11 // ---------------------------------------------------------------------------
12
13 use codewhale_command_contract::handler::CommandHandler;
14 use codewhale_command_contract::metadata::{
15 CommandInfo as ContractInfo, RegisterCommand as ContractRegisterCommand,
16 };
17
18 use crate::tui::app::AppAction;
19
20 pub(in crate::commands) const CONTRACT_INFO: ContractInfo = ContractInfo {
21 name: "compact",
22 aliases: &["yasuo"],
23 usage: "/compact [focus]",
24 description_key: "cmd_compact_description",
25 };
26
27 impl ContractRegisterCommand<CommandResult> for CompactCmd {
28 fn info() -> &'static ContractInfo {
29 &CONTRACT_INFO
30 }
31
32 fn handler() -> CommandHandler<CommandResult> {
33 CommandHandler::Pure(compact_pure)
34 }
35 }
36
37 /// Pure `/compact` — byte-identical to the baseline `session::compact`.
38 pub(in crate::commands) fn compact_pure(arg: Option<&str>) -> CommandResult {
39 let focus = arg
40 .map(str::trim)
41 .filter(|focus| !focus.is_empty())
42 .map(str::to_string);
43 let receipt = match focus.as_deref() {
44 Some(focus) => format!("Context compaction triggered (focus: {focus})..."),
45 None => "Context compaction triggered...".to_string(),
46 };
47 CommandResult::with_message_and_action(receipt, AppAction::CompactContext { focus })
48 }
49
50 #[cfg(test)]
51 mod tests {
52 use super::*;
53 use crate::tui::app::AppAction;
54
55 #[test]
56 fn pure_compact_matches_baseline_receipts() {
57 let none = compact_pure(None);
58 assert_eq!(
59 none.message.as_deref(),
60 Some("Context compaction triggered...")
61 );
62 assert!(matches!(
63 none.action,
64 Some(AppAction::CompactContext { focus: None })
65 ));
66 assert!(!none.is_error);
67
68 let blank = compact_pure(Some(" "));
69 assert!(matches!(
70 blank.action,
71 Some(AppAction::CompactContext { focus: None })
72 ));
73
74 let focus = compact_pure(Some(" the auth refactor "));
75 assert_eq!(
76 focus.message.as_deref(),
77 Some("Context compaction triggered (focus: the auth refactor)...")
78 );
79 assert!(matches!(
80 focus.action,
81 Some(AppAction::CompactContext { focus: Some(ref f) }) if f == "the auth refactor"
82 ));
83 }
84 }
85
85 lines RUST