返回 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 codewhale_command_contract::outcome::SessionAction;
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!("Making room (focus: {focus})…"),
45 None => "Making room…".to_string(),
46 };
47 CommandResult::with_message_and_action(receipt, SessionAction::CompactContext { focus })
48 }
49
50 #[cfg(test)]
51 mod tests {
52 use super::*;
53 use codewhale_command_contract::outcome::SessionAction;
54
55 #[test]
56 fn pure_compact_matches_baseline_receipts() {
57 let none = compact_pure(None);
58 assert_eq!(none.message.as_deref(), Some("Making room…"));
59 assert!(matches!(
60 none.action,
61 Some(SessionAction::CompactContext { focus: None })
62 ));
63 assert!(!none.is_error);
64
65 let blank = compact_pure(Some(" "));
66 assert!(matches!(
67 blank.action,
68 Some(SessionAction::CompactContext { focus: None })
69 ));
70
71 let focus = compact_pure(Some(" the auth refactor "));
72 assert_eq!(
73 focus.message.as_deref(),
74 Some("Making room (focus: the auth refactor)…")
75 );
76 assert!(matches!(
77 focus.action,
78 Some(SessionAction::CompactContext { focus: Some(ref f) }) if f == "the auth refactor"
79 ));
80 }
81 }
82
82 lines RUST