| 1 | //! Session command area: saving, forking, resuming, exporting, and the |
| 2 | //! `/relay` session-handoff artifact. |
| 3 | |
| 4 | mod branch; |
| 5 | mod compact; |
| 6 | mod export; |
| 7 | mod fork; |
| 8 | mod load; |
| 9 | mod new; |
| 10 | mod purge; |
| 11 | mod relay; |
| 12 | mod remote_control; |
| 13 | mod remote_env; |
| 14 | mod rename; |
| 15 | mod resume; |
| 16 | mod save; |
| 17 | mod sessions; |
| 18 | mod structcopy; |
| 19 | mod title; |
| 20 | mod tree; |
| 21 | // This group dir intentionally has a `session.rs` child module with the same |
| 22 | // name. The module_inception allow is a permanent structure rationale, not |
| 23 | // migration scaffolding; see docs/architecture/command-dispatch.md. |
| 24 | #[allow(clippy::module_inception)] |
| 25 | mod session; |
| 26 | |
| 27 | use crate::commands::CommandResult; |
| 28 | |
| 29 | /// Shared user-facing length policy for `/rename` and `/title`. |
| 30 | pub(in crate::commands) const MAX_TITLE_LEN: usize = 100; |
| 31 | use crate::commands::traits::{ |
| 32 | Command, CommandGroup, ContextualCommand, FunctionCommand, RegisterCommand, |
| 33 | }; |
| 34 | |
| 35 | pub struct SessionCommands; |
| 36 | |
| 37 | impl CommandGroup for SessionCommands { |
| 38 | fn commands(&self) -> &'static [Box<dyn Command>] { |
| 39 | cached_command_list!(vec![ |
| 40 | Box::new( |
| 41 | ContextualCommand::from_contract::<rename::RenameCmd>() |
| 42 | .expect("rename registration") |
| 43 | ), |
| 44 | Box::new( |
| 45 | ContextualCommand::from_contract::<title::TitleCmd>().expect("title registration") |
| 46 | ), |
| 47 | Box::new( |
| 48 | ContextualCommand::from_contract::<save::SaveCmd>().expect("save registration") |
| 49 | ), |
| 50 | Box::new( |
| 51 | ContextualCommand::from_contract::<fork::ForkCmd>().expect("fork registration") |
| 52 | ), |
| 53 | Box::new(ContextualCommand::from_contract::<new::NewCmd>().expect("new registration")), |
| 54 | Box::new( |
| 55 | ContextualCommand::from_contract::<sessions::SessionsCmd>() |
| 56 | .expect("sessions registration") |
| 57 | ), |
| 58 | Box::new( |
| 59 | ContextualCommand::from_contract::<load::LoadCmd>().expect("load registration") |
| 60 | ), |
| 61 | Box::new( |
| 62 | ContextualCommand::from_contract::<resume::ResumeCmd>() |
| 63 | .expect("resume registration") |
| 64 | ), |
| 65 | Box::new( |
| 66 | ContextualCommand::from_contract::<tree::TreeCmd>().expect("tree registration") |
| 67 | ), |
| 68 | Box::new( |
| 69 | ContextualCommand::from_contract::<branch::BranchCmd>() |
| 70 | .expect("branch registration") |
| 71 | ), |
| 72 | Box::new( |
| 73 | ContextualCommand::from_contract::<compact::CompactCmd>() |
| 74 | .expect("compact registration") |
| 75 | ), |
| 76 | Box::new( |
| 77 | ContextualCommand::from_contract::<purge::PurgeCmd>().expect("purge registration") |
| 78 | ), |
| 79 | Box::new( |
| 80 | ContextualCommand::from_contract::<relay::RelayCmd>().expect("relay registration") |
| 81 | ), |
| 82 | Box::new( |
| 83 | ContextualCommand::from_contract::<remote_control::RemoteControlCmd>() |
| 84 | .expect("remote_control registration") |
| 85 | ), |
| 86 | Box::new( |
| 87 | ContextualCommand::from_contract::<remote_env::RemoteEnvCmd>() |
| 88 | .expect("remote_env registration") |
| 89 | ), |
| 90 | Box::new( |
| 91 | ContextualCommand::from_contract::<export::ExportCmd>() |
| 92 | .expect("export registration") |
| 93 | ), |
| 94 | Box::new(FunctionCommand::new( |
| 95 | structcopy::StructcopyCmd::info(), |
| 96 | structcopy::StructcopyCmd::execute, |
| 97 | )), |
| 98 | ]) |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | // --------------------------------------------------------------------------- |
| 103 | // FEAT-023 Phase 4 (D6): map a portable lifecycle sync payload into the |
| 104 | // temporary `SyncSession` action. FEAT-037 owns the eventual shared outcome |
| 105 | // types; until then the mapping lives here so every portable handler composes |
| 106 | // the same action from the same receipt. |
| 107 | // --------------------------------------------------------------------------- |
| 108 | pub(in crate::commands) fn sync_session_action( |
| 109 | sync: codewhale_command_contract::facets::SessionSyncPayload, |
| 110 | ) -> crate::tui::app::AppAction { |
| 111 | crate::tui::app::AppAction::SyncSession { |
| 112 | session_id: sync.session_id, |
| 113 | messages: sync.messages, |
| 114 | system_prompt: sync.system_prompt, |
| 115 | model: sync.model, |
| 116 | workspace: sync.workspace, |
| 117 | mode: crate::commands::contract::from_command_mode(sync.mode), |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | #[cfg(test)] |
| 122 | mod control_test_support; |
| 123 | #[cfg(test)] |
| 124 | mod lifecycle_portable_tests; |
| 125 | #[cfg(test)] |
| 126 | mod lifecycle_test_support; |
| 127 |