Shared post-tool-use daemon notification. Fail-open and silent. Behavior note: empty shell commands are skipped for both agents. The Claude path always did this; the Codex path previously forwarded empty commands (which produced no-op daemon events), so the two were unified on the safer skip-empty behavior.
(spec: &PostToolUseSpec, event_json: &str)
| 71 | /// commands (which produced no-op daemon events), so the two were unified on |
| 72 | /// the safer skip-empty behavior. |
| 73 | pub(crate) async fn notify_post_tool_use(spec: &PostToolUseSpec, event_json: &str) { |
| 74 | let Ok(parsed) = serde_json::from_str::<Value>(event_json) else { |
| 75 | return; |
| 76 | }; |
| 77 | let tool_name = parsed |
| 78 | .get("tool_name") |
| 79 | .and_then(Value::as_str) |
| 80 | .unwrap_or_default(); |
| 81 | let Some(cwd) = event_cwd_from_parsed(&parsed) else { |
| 82 | return; |
| 83 | }; |
| 84 | let Some(root) = crate::config::discover_project_root(&cwd) |
| 85 | .or_else(|| crate::worktree::git_worktree_root(&cwd)) |
| 86 | else { |
| 87 | return; |
| 88 | }; |
| 89 | if !crate::tracedecay::TraceDecay::has_initialized_store(&root).await { |
| 90 | return; |
| 91 | } |
| 92 | |
| 93 | if (spec.is_edit_tool)(tool_name) { |
| 94 | let rels = (spec.edit_rel_paths)(&parsed, &cwd, &root); |
| 95 | if rels.is_empty() { |
| 96 | return; |
| 97 | } |
| 98 | crate::daemon::notify_hook_event( |
| 99 | &root, |
| 100 | crate::daemon::DaemonHookEvent::post_tool_use_edit(spec.agent, rels, cwd) |
| 101 | .with_route(Some(hook_route_metadata_from_parsed(&parsed, &root))), |
| 102 | ) |
| 103 | .await; |
| 104 | } else if (spec.is_shell_tool)(tool_name) { |
| 105 | let command = tool_input_command(&parsed); |
| 106 | if command.is_empty() { |
| 107 | return; |
| 108 | } |
| 109 | crate::daemon::notify_hook_event( |
| 110 | &root, |
| 111 | crate::daemon::DaemonHookEvent::post_tool_use_shell( |
| 112 | spec.agent, |
| 113 | command.to_string(), |
| 114 | cwd, |
| 115 | ) |
| 116 | .with_route(Some(hook_route_metadata_from_parsed(&parsed, &root))), |
| 117 | ) |
| 118 | .await; |
| 119 | } |
| 120 | } |
| 121 | |
| 122 | fn tool_input_command(parsed: &Value) -> &str { |
| 123 | parsed |
no test coverage detected