返回 CodeWhale
debug_group.rs
根目录 / crates / tui / src / commands / debug_group.rs
1 //! Host registration/action adapter for the portable debug group. Replaces
2 //! groups/debug/mod.rs's concrete-App dispatcher; the existing central
3 //! dispatcher still constructs the declared envelope and consumes the result.
4
5 use super::CommandResult;
6 use super::groups::debug::*;
7 use super::traits::{Command, CommandGroup, ContextualCommand};
8 use crate::tui::app::AppAction;
9 use codewhale_command_contract::handler::CommandHandler;
10 use codewhale_command_contract::metadata::{CommandInfo, RegisterCommand};
11 use codewhale_command_contract::outcome::{DebugAction, DebugCommandResult};
12 use std::marker::PhantomData;
13
14 pub(super) struct DebugCommands;
15
16 struct HostRegistration<C>(PhantomData<C>);
17 impl<C: RegisterCommand<DebugCommandResult>> RegisterCommand<CommandResult>
18 for HostRegistration<C>
19 {
20 fn info() -> &'static CommandInfo {
21 C::info()
22 }
23 fn handler() -> CommandHandler<CommandResult> {
24 match C::handler() {
25 CommandHandler::Pure(_) => CommandHandler::Pure(|args| match C::handler() {
26 CommandHandler::Pure(run) => host_result(run(args)),
27 _ => CommandResult::error("command handler shape changed"),
28 }),
29 CommandHandler::Contextual { capabilities, .. } => CommandHandler::Contextual {
30 capabilities,
31 handler: |contexts, args| match C::handler() {
32 CommandHandler::Contextual { handler, .. } => {
33 host_result(handler(contexts, args))
34 }
35 _ => CommandResult::error("command handler shape changed"),
36 },
37 },
38 }
39 }
40 }
41
42 impl CommandGroup for DebugCommands {
43 fn commands(&self) -> &'static [Box<dyn Command>] {
44 static COMMANDS: std::sync::OnceLock<Vec<Box<dyn Command>>> = std::sync::OnceLock::new();
45 COMMANDS.get_or_init(|| {
46 let commands: Vec<Box<dyn Command>> = vec![
47 Box::new(ContextualCommand::from_contract::<HostRegistration<tokens::TokensCmd>>().expect("debug registration")),
48 Box::new(ContextualCommand::from_contract::<HostRegistration<tokens::CostCmd>>().expect("debug registration")),
49 Box::new(ContextualCommand::from_contract::<HostRegistration<receipts::ReceiptsCmd>>().expect("debug registration")),
50 Box::new(ContextualCommand::from_contract::<HostRegistration<balance::BalanceCmd>>().expect("debug registration")),
51 Box::new(ContextualCommand::from_contract::<HostRegistration<cache::CacheCmd>>().expect("debug registration")),
52 Box::new(ContextualCommand::from_contract::<HostRegistration<preview_request::PreviewRequestCmd>>().expect("debug registration")),
53 Box::new(ContextualCommand::from_contract::<HostRegistration<tool_inspection::ToolsCmd>>().expect("debug registration")),
54 Box::new(ContextualCommand::from_contract::<HostRegistration<change::ChangeCmd>>().expect("debug registration")),
55 Box::new(ContextualCommand::from_contract::<HostRegistration<tokens::SystemCmd>>().expect("debug registration")),
56 Box::new(ContextualCommand::from_contract::<HostRegistration<tokens::ContextCmd>>().expect("debug registration")),
57 Box::new(ContextualCommand::from_contract::<HostRegistration<undo::EditCmd>>().expect("debug registration")),
58 Box::new(ContextualCommand::from_contract::<HostRegistration<undo::DiffCmd>>().expect("debug registration")),
59 Box::new(ContextualCommand::from_contract::<HostRegistration<undo::UndoCmd>>().expect("debug registration")),
60 Box::new(ContextualCommand::from_contract::<HostRegistration<undo::RetryCmd>>().expect("debug registration")),
61 ];
62 assert_eq!(commands.iter().map(|command| command.info().name).collect::<Vec<_>>(),
63 portable_handlers().iter().map(|(info, _)| info.name).collect::<Vec<_>>(),
64 "host registry must cover the complete portable debug inventory");
65 commands
66 }).as_slice()
67 }
68 }
69
70 fn sync_session(sync: codewhale_command_contract::facets::SessionSyncPayload) -> AppAction {
71 AppAction::SyncSession {
72 session_id: sync.session_id,
73 messages: sync.messages,
74 system_prompt: sync.system_prompt,
75 model: sync.model,
76 workspace: sync.workspace,
77 mode: super::contract::from_command_mode(sync.mode),
78 }
79 }
80
81 pub(in crate::commands) fn host_result(result: DebugCommandResult) -> CommandResult {
82 let action = result.action.map(|action| match action {
83 DebugAction::FetchBalance => AppAction::FetchBalance,
84 DebugAction::CacheWarmup => AppAction::CacheWarmup,
85 DebugAction::PreviewOutboundRequest {
86 json,
87 base_prompt_only,
88 hypothetical_prompt,
89 } => AppAction::PreviewOutboundRequest {
90 json,
91 base_prompt_only,
92 hypothetical_prompt,
93 },
94 DebugAction::OpenTextPager { title, content } => {
95 AppAction::OpenTextPager { title, content }
96 }
97 DebugAction::OpenContextInspector => AppAction::OpenContextInspector,
98 DebugAction::SendMessage(input) => AppAction::SendMessage(input),
99 DebugAction::SyncSession(sync) => sync_session(sync),
100 DebugAction::ConversationUndo { sync, retry_input } => AppAction::ConversationUndo {
101 sync,
102 retry_input,
103 edit_replacement: false,
104 },
105 });
106 CommandResult {
107 message: result.message,
108 action,
109 is_error: result.is_error,
110 }
111 }
112
112 lines RUST