mirror of
https://github.com/openai/codex.git
synced 2026-09-17 12:23:33 +00:00
CHAINED PR - note that base is eternal/hooks-pretooluse-bash, not main -- so the following PR should be first Matching post-tool hook to the pre-tool functionality here: https://github.com/openai/codex/pull/15211 So, PreToolUse calls for plain shell calls, allows blocking. This PostToolUse call runs after the command executed example run: ``` › as a test, run in parallel the following commands: - echo 'one' - echo '[block-pre-tool-use]' - echo '[block-post-tool-use]' ⚠ MCP startup incomplete (failed: notion, linear) • Cruising through those three commands in parallel now, and I’ll share the exact outputs right after they land. • Running PreToolUse hook: checking the observatory runes • Running PreToolUse hook: checking the observatory runes • Running PreToolUse hook: checking the observatory runes 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 'one' PreToolUse hook (completed) warning: wizard-tower PreToolUse demo inspected Bash: echo '[block-post-tool-use]' • Ran echo '[block-post-tool-use]' └ [block-post-tool-use] • Ran echo 'one' └ one • Running PostToolUse hook: reading the observatory aftermath • Running PostToolUse hook: reading the observatory aftermath PostToolUse hook (blocked) warning: wizard-tower PostToolUse demo blocked the Bash follow-through on purpose. feedback: PostToolUse demo blocked the result after execution. Remove [block-post-tool-use] to continue. PostToolUse hook (completed) warning: wizard-tower PostToolUse demo inspected Bash: echo 'one' hook context: PostToolUse demo saw the Bash result. Response preview: one ────────────────────────────────────────────────────────────────────────────────────────────────────── • Ran them in parallel. Little wave report: - echo 'one' completed and returned one. - echo '[block-pre-tool-use]' was blocked before execution by the PreToolUse hook. - echo '[block-post-tool-use]' ran, but its result was blocked afterward by the PostToolUse hook. The hook messages were: - PreToolUse demo blocked the command. Remove [block-pre-tool-use] to continue. - PostToolUse demo blocked the result after execution. Remove [block-post-tool-use] to continue. › for the blocked messages (correctly blocked in this test) did the tool output land back into context? • Yeah, from this run: - PreToolUse block: the command itself did not execute, so no command output landed in context. Only the block message did. - PostToolUse block: the command did execute, but the actual stdout did not come back into context. Only the post-tool block message did. So the blocked notifications landed in context, but the blocked command payloads themselves did not. Nice clean guardrail, aloha. ```
91 lines
3.8 KiB
Rust
91 lines
3.8 KiB
Rust
use std::sync::OnceLock;
|
|
|
|
use serde_json::Value;
|
|
|
|
#[allow(dead_code)]
|
|
pub(crate) struct GeneratedHookSchemas {
|
|
pub post_tool_use_command_input: Value,
|
|
pub post_tool_use_command_output: Value,
|
|
pub pre_tool_use_command_input: Value,
|
|
pub pre_tool_use_command_output: Value,
|
|
pub session_start_command_input: Value,
|
|
pub session_start_command_output: Value,
|
|
pub user_prompt_submit_command_input: Value,
|
|
pub user_prompt_submit_command_output: Value,
|
|
pub stop_command_input: Value,
|
|
pub stop_command_output: Value,
|
|
}
|
|
|
|
pub(crate) fn generated_hook_schemas() -> &'static GeneratedHookSchemas {
|
|
static SCHEMAS: OnceLock<GeneratedHookSchemas> = OnceLock::new();
|
|
SCHEMAS.get_or_init(|| GeneratedHookSchemas {
|
|
post_tool_use_command_input: parse_json_schema(
|
|
"post-tool-use.command.input",
|
|
include_str!("../../schema/generated/post-tool-use.command.input.schema.json"),
|
|
),
|
|
post_tool_use_command_output: parse_json_schema(
|
|
"post-tool-use.command.output",
|
|
include_str!("../../schema/generated/post-tool-use.command.output.schema.json"),
|
|
),
|
|
pre_tool_use_command_input: parse_json_schema(
|
|
"pre-tool-use.command.input",
|
|
include_str!("../../schema/generated/pre-tool-use.command.input.schema.json"),
|
|
),
|
|
pre_tool_use_command_output: parse_json_schema(
|
|
"pre-tool-use.command.output",
|
|
include_str!("../../schema/generated/pre-tool-use.command.output.schema.json"),
|
|
),
|
|
session_start_command_input: parse_json_schema(
|
|
"session-start.command.input",
|
|
include_str!("../../schema/generated/session-start.command.input.schema.json"),
|
|
),
|
|
session_start_command_output: parse_json_schema(
|
|
"session-start.command.output",
|
|
include_str!("../../schema/generated/session-start.command.output.schema.json"),
|
|
),
|
|
user_prompt_submit_command_input: parse_json_schema(
|
|
"user-prompt-submit.command.input",
|
|
include_str!("../../schema/generated/user-prompt-submit.command.input.schema.json"),
|
|
),
|
|
user_prompt_submit_command_output: parse_json_schema(
|
|
"user-prompt-submit.command.output",
|
|
include_str!("../../schema/generated/user-prompt-submit.command.output.schema.json"),
|
|
),
|
|
stop_command_input: parse_json_schema(
|
|
"stop.command.input",
|
|
include_str!("../../schema/generated/stop.command.input.schema.json"),
|
|
),
|
|
stop_command_output: parse_json_schema(
|
|
"stop.command.output",
|
|
include_str!("../../schema/generated/stop.command.output.schema.json"),
|
|
),
|
|
})
|
|
}
|
|
|
|
fn parse_json_schema(name: &str, schema: &str) -> Value {
|
|
serde_json::from_str(schema)
|
|
.unwrap_or_else(|err| panic!("invalid generated hooks schema {name}: {err}"))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::generated_hook_schemas;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn loads_generated_hook_schemas() {
|
|
let schemas = generated_hook_schemas();
|
|
|
|
assert_eq!(schemas.post_tool_use_command_input["type"], "object");
|
|
assert_eq!(schemas.post_tool_use_command_output["type"], "object");
|
|
assert_eq!(schemas.pre_tool_use_command_input["type"], "object");
|
|
assert_eq!(schemas.pre_tool_use_command_output["type"], "object");
|
|
assert_eq!(schemas.session_start_command_input["type"], "object");
|
|
assert_eq!(schemas.session_start_command_output["type"], "object");
|
|
assert_eq!(schemas.user_prompt_submit_command_input["type"], "object");
|
|
assert_eq!(schemas.user_prompt_submit_command_output["type"], "object");
|
|
assert_eq!(schemas.stop_command_input["type"], "object");
|
|
assert_eq!(schemas.stop_command_output["type"], "object");
|
|
}
|
|
}
|