Răsfoiți Sursa

wip: hook progress UI + documentation

Yeachan-Heo 2 luni în urmă
părinte
comite
555a245456

+ 73 - 72
rust/crates/runtime/src/conversation.rs

@@ -5,7 +5,7 @@ use crate::compact::{
     compact_session, estimate_session_tokens, CompactionConfig, CompactionResult,
 };
 use crate::config::RuntimeFeatureConfig;
-use crate::hooks::{HookAbortSignal, HookRunResult, HookRunner};
+use crate::hooks::{HookAbortSignal, HookProgressReporter, HookRunResult, HookRunner};
 use crate::permissions::{
     PermissionContext, PermissionOutcome, PermissionPolicy, PermissionPrompter,
 };
@@ -100,6 +100,7 @@ pub struct ConversationRuntime<C, T> {
     usage_tracker: UsageTracker,
     hook_runner: HookRunner,
     hook_abort_signal: HookAbortSignal,
+    hook_progress_reporter: Option<Box<dyn HookProgressReporter>>,
 }
 
 impl<C, T> ConversationRuntime<C, T>
@@ -171,6 +172,77 @@ where
         self
     }
 
+    fn run_pre_tool_use_hook(&mut self, tool_name: &str, input: &str) -> HookRunResult {
+        if let Some(reporter) = self.hook_progress_reporter.as_mut() {
+            self.hook_runner.run_pre_tool_use_with_context(
+                tool_name,
+                input,
+                Some(&self.hook_abort_signal),
+                Some(reporter.as_mut()),
+            )
+        } else {
+            self.hook_runner.run_pre_tool_use_with_context(
+                tool_name,
+                input,
+                Some(&self.hook_abort_signal),
+                None,
+            )
+        }
+    }
+
+    fn run_post_tool_use_hook(
+        &mut self,
+        tool_name: &str,
+        input: &str,
+        output: &str,
+        is_error: bool,
+    ) -> HookRunResult {
+        if let Some(reporter) = self.hook_progress_reporter.as_mut() {
+            self.hook_runner.run_post_tool_use_with_context(
+                tool_name,
+                input,
+                output,
+                is_error,
+                Some(&self.hook_abort_signal),
+                Some(reporter.as_mut()),
+            )
+        } else {
+            self.hook_runner.run_post_tool_use_with_context(
+                tool_name,
+                input,
+                output,
+                is_error,
+                Some(&self.hook_abort_signal),
+                None,
+            )
+        }
+    }
+
+    fn run_post_tool_use_failure_hook(
+        &mut self,
+        tool_name: &str,
+        input: &str,
+        output: &str,
+    ) -> HookRunResult {
+        if let Some(reporter) = self.hook_progress_reporter.as_mut() {
+            self.hook_runner.run_post_tool_use_failure_with_context(
+                tool_name,
+                input,
+                output,
+                Some(&self.hook_abort_signal),
+                Some(reporter.as_mut()),
+            )
+        } else {
+            self.hook_runner.run_post_tool_use_failure_with_context(
+                tool_name,
+                input,
+                output,
+                Some(&self.hook_abort_signal),
+                None,
+            )
+        }
+    }
+
     #[allow(clippy::too_many_lines)]
     pub fn run_turn(
         &mut self,
@@ -314,77 +386,6 @@ where
         })
     }
 
-    fn run_pre_tool_use_hook(&mut self, tool_name: &str, input: &str) -> HookRunResult {
-        if let Some(reporter) = self.hook_progress_reporter.as_mut() {
-            self.hook_runner.run_pre_tool_use_with_context(
-                tool_name,
-                input,
-                Some(&self.hook_abort_signal),
-                Some(reporter.as_mut()),
-            )
-        } else {
-            self.hook_runner.run_pre_tool_use_with_context(
-                tool_name,
-                input,
-                Some(&self.hook_abort_signal),
-                None,
-            )
-        }
-    }
-
-    fn run_post_tool_use_hook(
-        &mut self,
-        tool_name: &str,
-        input: &str,
-        output: &str,
-        is_error: bool,
-    ) -> HookRunResult {
-        if let Some(reporter) = self.hook_progress_reporter.as_mut() {
-            self.hook_runner.run_post_tool_use_with_context(
-                tool_name,
-                input,
-                output,
-                is_error,
-                Some(&self.hook_abort_signal),
-                Some(reporter.as_mut()),
-            )
-        } else {
-            self.hook_runner.run_post_tool_use_with_context(
-                tool_name,
-                input,
-                output,
-                is_error,
-                Some(&self.hook_abort_signal),
-                None,
-            )
-        }
-    }
-
-    fn run_post_tool_use_failure_hook(
-        &mut self,
-        tool_name: &str,
-        input: &str,
-        output: &str,
-    ) -> HookRunResult {
-        if let Some(reporter) = self.hook_progress_reporter.as_mut() {
-            self.hook_runner.run_post_tool_use_failure_with_context(
-                tool_name,
-                input,
-                output,
-                Some(&self.hook_abort_signal),
-                Some(reporter.as_mut()),
-            )
-        } else {
-            self.hook_runner.run_post_tool_use_failure_with_context(
-                tool_name,
-                input,
-                output,
-                Some(&self.hook_abort_signal),
-                None,
-            )
-        }
-    }
-
     #[must_use]
     pub fn compact(&self, config: CompactionConfig) -> CompactionResult {
         compact_session(&self.session, config)

+ 37 - 1
rust/crates/rusty-claude-cli/src/main.rs

@@ -1923,7 +1923,7 @@ fn build_runtime(
 ) -> Result<ConversationRuntime<AnthropicRuntimeClient, CliToolExecutor>, Box<dyn std::error::Error>>
 {
     let feature_config = build_runtime_feature_config()?;
-    let runtime = ConversationRuntime::new_with_features(
+    let mut runtime = ConversationRuntime::new_with_features(
         session,
         AnthropicRuntimeClient::new(model, enable_tools, emit_output, allowed_tools.clone())?,
         CliToolExecutor::new(allowed_tools, emit_output),
@@ -1931,9 +1931,45 @@ fn build_runtime(
         system_prompt,
         feature_config,
     );
+    if emit_output {
+        runtime = runtime.with_hook_progress_reporter(Box::new(CliHookProgressReporter));
+    }
     Ok(runtime)
 }
 
+struct CliHookProgressReporter;
+
+impl runtime::HookProgressReporter for CliHookProgressReporter {
+    fn on_event(&mut self, event: &runtime::HookProgressEvent) {
+        match event {
+            runtime::HookProgressEvent::Started {
+                event,
+                tool_name,
+                command,
+            } => eprintln!(
+                "[hook {event_name}] {tool_name}: {command}",
+                event_name = event.as_str()
+            ),
+            runtime::HookProgressEvent::Completed {
+                event,
+                tool_name,
+                command,
+            } => eprintln!(
+                "[hook done {event_name}] {tool_name}: {command}",
+                event_name = event.as_str()
+            ),
+            runtime::HookProgressEvent::Cancelled {
+                event,
+                tool_name,
+                command,
+            } => eprintln!(
+                "[hook cancelled {event_name}] {tool_name}: {command}",
+                event_name = event.as_str()
+            ),
+        }
+    }
+}
+
 struct CliPermissionPrompter {
     current_mode: PermissionMode,
 }