mirror of
https://github.com/openai/codex.git
synced 2026-09-08 15:50:34 +00:00
Move tool hook compatibility under hook runtime
This commit is contained in:
@@ -38,6 +38,8 @@ use crate::session::turn_context::TurnContext;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::sandboxing::PermissionRequestPayload;
|
||||
|
||||
pub(crate) mod tool_compat;
|
||||
|
||||
pub(crate) struct HookRuntimeOutcome {
|
||||
pub should_stop: bool,
|
||||
pub additional_contexts: Vec<String>,
|
||||
|
||||
@@ -11,7 +11,20 @@ use crate::tools::handlers::shell_command_payload_command;
|
||||
use crate::tools::handlers::shell_function_payload_command;
|
||||
use crate::tools::handlers::unified_exec::ExecCommandArgs;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::registry::PreToolUsePayload;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct PreToolUsePayload {
|
||||
/// Hook-facing tool name model.
|
||||
///
|
||||
/// The canonical name is serialized to hook stdin, while aliases are used
|
||||
/// only for matcher compatibility.
|
||||
pub(crate) tool_name: HookToolName,
|
||||
/// Tool-specific input exposed at `tool_input`.
|
||||
///
|
||||
/// Shell-like tools use `{ "command": ... }`; MCP tools use their resolved
|
||||
/// JSON arguments.
|
||||
pub(crate) tool_input: Value,
|
||||
}
|
||||
|
||||
/// Projects native tool payloads into the stable input shape exposed to hooks.
|
||||
///
|
||||
@@ -14,12 +14,12 @@ use std::sync::Arc;
|
||||
use tempfile::TempDir;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::hook_runtime::tool_compat;
|
||||
use crate::hook_runtime::tool_compat::PreToolUsePayload;
|
||||
use crate::session::tests::make_session_and_context;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::hook_compat;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::registry::PostToolUsePayload;
|
||||
use crate::tools::registry::PreToolUsePayload;
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
|
||||
fn sample_patch() -> &'static str {
|
||||
@@ -51,7 +51,7 @@ async fn pre_tool_use_payload_uses_json_patch_input() {
|
||||
};
|
||||
let invocation = invocation_for_payload(payload).await;
|
||||
assert_eq!(
|
||||
hook_compat::pre_tool_use_payload(&invocation),
|
||||
tool_compat::pre_tool_use_payload(&invocation),
|
||||
Some(PreToolUsePayload {
|
||||
tool_name: HookToolName::apply_patch(),
|
||||
tool_input: json!({ "command": patch }),
|
||||
@@ -67,7 +67,7 @@ async fn pre_tool_use_payload_uses_freeform_patch_input() {
|
||||
};
|
||||
let invocation = invocation_for_payload(payload).await;
|
||||
assert_eq!(
|
||||
hook_compat::pre_tool_use_payload(&invocation),
|
||||
tool_compat::pre_tool_use_payload(&invocation),
|
||||
Some(PreToolUsePayload {
|
||||
tool_name: HookToolName::apply_patch(),
|
||||
tool_input: json!({ "command": patch }),
|
||||
|
||||
@@ -104,9 +104,9 @@ impl ToolHandler for McpHandler {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::hook_runtime::tool_compat;
|
||||
use crate::session::tests::make_session_and_context;
|
||||
use crate::tools::context::ToolCallSource;
|
||||
use crate::tools::hook_compat;
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
@@ -128,7 +128,7 @@ mod tests {
|
||||
};
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
assert_eq!(
|
||||
hook_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
tool_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
session: session.into(),
|
||||
turn: turn.into(),
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
@@ -138,7 +138,7 @@ mod tests {
|
||||
source: ToolCallSource::Direct,
|
||||
payload,
|
||||
}),
|
||||
Some(crate::tools::registry::PreToolUsePayload {
|
||||
Some(tool_compat::PreToolUsePayload {
|
||||
tool_name: HookToolName::new("mcp__memory__create_entities"),
|
||||
tool_input: json!({
|
||||
"entities": [{
|
||||
@@ -214,6 +214,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn mcp_hook_tool_input_defaults_empty_args_to_object() {
|
||||
assert_eq!(hook_compat::mcp_hook_tool_input(" "), json!({}));
|
||||
assert_eq!(tool_compat::mcp_hook_tool_input(" "), json!({}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use core_test_support::test_path_buf;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use crate::exec_env::create_env;
|
||||
use crate::hook_runtime::tool_compat;
|
||||
use crate::sandboxing::SandboxPermissions;
|
||||
use crate::session::tests::make_session_and_context;
|
||||
use crate::shell::Shell;
|
||||
@@ -17,7 +18,6 @@ use crate::tools::context::ToolCallSource;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::handlers::ShellCommandHandler;
|
||||
use crate::tools::hook_compat;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::registry::ToolHandler;
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
@@ -223,7 +223,7 @@ async fn local_shell_pre_tool_use_payload_uses_joined_command() {
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
|
||||
assert_eq!(
|
||||
hook_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
tool_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
session: session.into(),
|
||||
turn: turn.into(),
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
@@ -233,7 +233,7 @@ async fn local_shell_pre_tool_use_payload_uses_joined_command() {
|
||||
source: crate::tools::context::ToolCallSource::Direct,
|
||||
payload,
|
||||
}),
|
||||
Some(crate::tools::registry::PreToolUsePayload {
|
||||
Some(tool_compat::PreToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_input: json!({ "command": "bash -lc 'printf hi'" }),
|
||||
})
|
||||
@@ -248,7 +248,7 @@ async fn shell_command_pre_tool_use_payload_uses_raw_command() {
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
|
||||
assert_eq!(
|
||||
hook_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
tool_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
session: session.into(),
|
||||
turn: turn.into(),
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
@@ -258,7 +258,7 @@ async fn shell_command_pre_tool_use_payload_uses_raw_command() {
|
||||
source: crate::tools::context::ToolCallSource::Direct,
|
||||
payload,
|
||||
}),
|
||||
Some(crate::tools::registry::PreToolUsePayload {
|
||||
Some(tool_compat::PreToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_input: json!({ "command": "printf shell command" }),
|
||||
})
|
||||
|
||||
@@ -6,12 +6,12 @@ use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::hook_runtime::tool_compat;
|
||||
use crate::session::tests::make_session_and_context;
|
||||
use crate::tools::context::ExecCommandToolOutput;
|
||||
use crate::tools::context::ToolCallSource;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::hook_compat;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::registry::ToolHandler;
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
@@ -186,7 +186,7 @@ async fn exec_command_pre_tool_use_payload_uses_raw_command() {
|
||||
};
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
assert_eq!(
|
||||
hook_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
tool_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
session: session.into(),
|
||||
turn: turn.into(),
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
@@ -196,7 +196,7 @@ async fn exec_command_pre_tool_use_payload_uses_raw_command() {
|
||||
source: crate::tools::context::ToolCallSource::Direct,
|
||||
payload,
|
||||
}),
|
||||
Some(crate::tools::registry::PreToolUsePayload {
|
||||
Some(tool_compat::PreToolUsePayload {
|
||||
tool_name: HookToolName::bash(),
|
||||
tool_input: serde_json::json!({ "command": "printf exec command" }),
|
||||
})
|
||||
@@ -210,7 +210,7 @@ async fn exec_command_pre_tool_use_payload_skips_write_stdin() {
|
||||
};
|
||||
let (session, turn) = make_session_and_context().await;
|
||||
assert_eq!(
|
||||
hook_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
tool_compat::pre_tool_use_payload(&ToolInvocation {
|
||||
session: session.into(),
|
||||
turn: turn.into(),
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
|
||||
@@ -2,7 +2,6 @@ pub(crate) mod code_mode;
|
||||
pub(crate) mod context;
|
||||
pub(crate) mod events;
|
||||
pub(crate) mod handlers;
|
||||
pub(crate) mod hook_compat;
|
||||
pub(crate) mod hook_names;
|
||||
pub(crate) mod network_approval;
|
||||
pub(crate) mod orchestrator;
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::hook_runtime::PreToolUseHookResult;
|
||||
use crate::hook_runtime::record_additional_contexts;
|
||||
use crate::hook_runtime::run_post_tool_use_hooks;
|
||||
use crate::hook_runtime::run_pre_tool_use_hooks;
|
||||
use crate::hook_runtime::tool_compat;
|
||||
use crate::memory_usage::emit_metric_for_tool_read;
|
||||
use crate::sandbox_tags::permission_profile_policy_tag;
|
||||
use crate::sandbox_tags::permission_profile_sandbox_tag;
|
||||
@@ -17,7 +18,6 @@ use crate::tools::context::FunctionToolOutput;
|
||||
use crate::tools::context::ToolInvocation;
|
||||
use crate::tools::context::ToolOutput;
|
||||
use crate::tools::context::ToolPayload;
|
||||
use crate::tools::hook_compat;
|
||||
use crate::tools::hook_names::HookToolName;
|
||||
use crate::tools::tool_dispatch_trace::ToolDispatchTrace;
|
||||
use codex_hooks::HookEvent;
|
||||
@@ -131,20 +131,6 @@ impl AnyToolResult {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(crate) struct PreToolUsePayload {
|
||||
/// Hook-facing tool name model.
|
||||
///
|
||||
/// The canonical name is serialized to hook stdin, while aliases are used
|
||||
/// only for matcher compatibility.
|
||||
pub(crate) tool_name: HookToolName,
|
||||
/// Tool-specific input exposed at `tool_input`.
|
||||
///
|
||||
/// Shell-like tools use `{ "command": ... }`; MCP tools use their resolved
|
||||
/// JSON arguments.
|
||||
pub(crate) tool_input: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub(crate) struct PostToolUsePayload {
|
||||
/// Hook-facing tool name model.
|
||||
@@ -342,7 +328,7 @@ impl ToolRegistry {
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
if let Some(pre_tool_use_payload) = hook_compat::pre_tool_use_payload(&invocation) {
|
||||
if let Some(pre_tool_use_payload) = tool_compat::pre_tool_use_payload(&invocation) {
|
||||
match run_pre_tool_use_hooks(
|
||||
&invocation.session,
|
||||
&invocation.turn,
|
||||
@@ -360,9 +346,9 @@ impl ToolRegistry {
|
||||
PreToolUseHookResult::Continue {
|
||||
updated_input: Some(updated_input),
|
||||
} => {
|
||||
invocation = hook_compat::apply_updated_input(invocation, updated_input)?;
|
||||
invocation = tool_compat::apply_updated_input(invocation, updated_input)?;
|
||||
}
|
||||
crate::hook_runtime::PreToolUseHookResult::Continue {
|
||||
PreToolUseHookResult::Continue {
|
||||
updated_input: None,
|
||||
} => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user