mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[hooks] add non-streaming (non-stdin style) shell-only PreToolUse support (#15211)
- add `PreToolUse` hook for bash-like tool execution only at first - block shell execution before dispatch with deny-only hook behavior - introduces common.rs matcher framework for matching when hooks are run example run: ``` › run three parallel echo commands, and the second one should echo "[block-pre-tool-use]" as a test • Running the three echo commands in parallel now and I’ll report the output directly. • Running PreToolUse hook: name for demo pre tool use hook • Running PreToolUse hook: name for demo pre tool use hook • Running PreToolUse hook: name for demo pre tool use hook PreToolUse hook (completed) warning: wizard-tower PreToolUse demo inspected Bash: echo "first parallel echo" PreToolUse hook (blocked) warning: wizard-tower PreToolUse demo blocked a Bash command on purpose. feedback: PreToolUse demo blocked the command. Remove [block-pre-tool-use] to continue. PreToolUse hook (completed) warning: wizard-tower PreToolUse demo inspected Bash: echo "third parallel echo" • Ran echo "first parallel echo" └ first parallel echo • Ran echo "third parallel echo" └ third parallel echo • Three little waves went out in parallel. 1. printed first parallel echo 2. was blocked before execution because it contained the exact test string [block-pre-tool-use] 3. printed third parallel echo There was also an unrelated macOS defaults warning around the successful commands, but the echoes themselves worked fine. If you want, I can rerun the second one with a slightly modified string so it passes cleanly. ```
This commit is contained in:
committed by
GitHub
Unverified
parent
18f1a08bc9
commit
73bbb07ba8
@@ -10774,6 +10774,7 @@ fn extract_first_bold(s: &str) -> Option<String> {
|
||||
|
||||
fn hook_event_label(event_name: codex_protocol::protocol::HookEventName) -> &'static str {
|
||||
match event_name {
|
||||
codex_protocol::protocol::HookEventName::PreToolUse => "PreToolUse",
|
||||
codex_protocol::protocol::HookEventName::SessionStart => "SessionStart",
|
||||
codex_protocol::protocol::HookEventName::UserPromptSubmit => "UserPromptSubmit",
|
||||
codex_protocol::protocol::HookEventName::Stop => "Stop",
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests.rs
|
||||
assertion_line: 8586
|
||||
expression: combined
|
||||
---
|
||||
• Running SessionStart hook: warming the shell
|
||||
|
||||
SessionStart hook (completed)
|
||||
warning: Heads up from the hook
|
||||
hook context: Remember the startup checklist.
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
---
|
||||
source: tui_app_server/src/chatwidget/tests.rs
|
||||
expression: combined
|
||||
---
|
||||
• Running PreToolUse hook: warming the shell
|
||||
|
||||
PreToolUse hook (completed)
|
||||
warning: Heads up from the hook
|
||||
hook context: Remember the startup checklist.
|
||||
@@ -12465,7 +12465,33 @@ async fn deltas_then_same_final_message_are_rendered_snapshot() {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn hook_events_render_snapshot() {
|
||||
async fn pre_tool_use_hook_events_render_snapshot() {
|
||||
assert_hook_events_snapshot(
|
||||
codex_protocol::protocol::HookEventName::PreToolUse,
|
||||
"pre-tool-use:0:/tmp/hooks.json",
|
||||
"warming the shell",
|
||||
"pre_tool_use_hook_events_render_snapshot",
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn session_start_hook_events_render_snapshot() {
|
||||
assert_hook_events_snapshot(
|
||||
codex_protocol::protocol::HookEventName::SessionStart,
|
||||
"session-start:0:/tmp/hooks.json",
|
||||
"warming the shell",
|
||||
"session_start_hook_events_render_snapshot",
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn assert_hook_events_snapshot(
|
||||
event_name: codex_protocol::protocol::HookEventName,
|
||||
run_id: &str,
|
||||
status_message: &str,
|
||||
snapshot_name: &str,
|
||||
) {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;
|
||||
|
||||
chat.handle_codex_event(Event {
|
||||
@@ -12473,15 +12499,15 @@ async fn hook_events_render_snapshot() {
|
||||
msg: EventMsg::HookStarted(codex_protocol::protocol::HookStartedEvent {
|
||||
turn_id: None,
|
||||
run: codex_protocol::protocol::HookRunSummary {
|
||||
id: "session-start:0:/tmp/hooks.json".to_string(),
|
||||
event_name: codex_protocol::protocol::HookEventName::SessionStart,
|
||||
id: run_id.to_string(),
|
||||
event_name,
|
||||
handler_type: codex_protocol::protocol::HookHandlerType::Command,
|
||||
execution_mode: codex_protocol::protocol::HookExecutionMode::Sync,
|
||||
scope: codex_protocol::protocol::HookScope::Thread,
|
||||
scope: codex_protocol::protocol::HookScope::Turn,
|
||||
source_path: PathBuf::from("/tmp/hooks.json"),
|
||||
display_order: 0,
|
||||
status: codex_protocol::protocol::HookRunStatus::Running,
|
||||
status_message: Some("warming the shell".to_string()),
|
||||
status_message: Some(status_message.to_string()),
|
||||
started_at: 1,
|
||||
completed_at: None,
|
||||
duration_ms: None,
|
||||
@@ -12495,15 +12521,15 @@ async fn hook_events_render_snapshot() {
|
||||
msg: EventMsg::HookCompleted(codex_protocol::protocol::HookCompletedEvent {
|
||||
turn_id: None,
|
||||
run: codex_protocol::protocol::HookRunSummary {
|
||||
id: "session-start:0:/tmp/hooks.json".to_string(),
|
||||
event_name: codex_protocol::protocol::HookEventName::SessionStart,
|
||||
id: run_id.to_string(),
|
||||
event_name,
|
||||
handler_type: codex_protocol::protocol::HookHandlerType::Command,
|
||||
execution_mode: codex_protocol::protocol::HookExecutionMode::Sync,
|
||||
scope: codex_protocol::protocol::HookScope::Thread,
|
||||
scope: codex_protocol::protocol::HookScope::Turn,
|
||||
source_path: PathBuf::from("/tmp/hooks.json"),
|
||||
display_order: 0,
|
||||
status: codex_protocol::protocol::HookRunStatus::Completed,
|
||||
status_message: Some("warming the shell".to_string()),
|
||||
status_message: Some(status_message.to_string()),
|
||||
started_at: 1,
|
||||
completed_at: Some(11),
|
||||
duration_ms: Some(10),
|
||||
@@ -12526,7 +12552,7 @@ async fn hook_events_render_snapshot() {
|
||||
.iter()
|
||||
.map(|lines| lines_to_single_string(lines))
|
||||
.collect::<String>();
|
||||
assert_snapshot!("hook_events_render_snapshot", combined);
|
||||
assert_snapshot!(snapshot_name, combined);
|
||||
}
|
||||
|
||||
// Combined visual snapshot using vt100 for history + direct buffer overlay for UI.
|
||||
|
||||
Reference in New Issue
Block a user