diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-20 15:17:54 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-20 15:18:03 +0300 |
| commit | 28b628d79d755afbb3ac45f9184a03c204c26784 (patch) | |
| tree | 93ee9f4c9939430c5e82b22da7c080f99f882fe0 /src | |
| parent | 9450b168c727e9e4cbee95e6edf4f11cfe6f2154 (diff) | |
fix: report kimi questions as blocked
Diffstat (limited to 'src')
| -rw-r--r-- | src/integration/assets/kimi/herdr-agent-state.ps1 | 2 | ||||
| -rw-r--r-- | src/integration/assets/kimi/herdr-agent-state.sh | 2 | ||||
| -rw-r--r-- | src/integration/config_edit.rs | 16 | ||||
| -rw-r--r-- | src/integration/mod.rs | 39 | ||||
| -rw-r--r-- | src/integration/tests.rs | 35 |
5 files changed, 73 insertions, 21 deletions
diff --git a/src/integration/assets/kimi/herdr-agent-state.ps1 b/src/integration/assets/kimi/herdr-agent-state.ps1 index ff6bcefe..16c9eb4d 100644 --- a/src/integration/assets/kimi/herdr-agent-state.ps1 +++ b/src/integration/assets/kimi/herdr-agent-state.ps1 @@ -2,7 +2,7 @@ # managed by herdr; reinstalling or updating the integration overwrites this file. # add custom hooks beside this file instead of editing it. # HERDR_INTEGRATION_ID=kimi -# HERDR_INTEGRATION_VERSION=4 +# HERDR_INTEGRATION_VERSION=5 param([string]$Action = "") diff --git a/src/integration/assets/kimi/herdr-agent-state.sh b/src/integration/assets/kimi/herdr-agent-state.sh index b5b6cc4b..9c307b4a 100644 --- a/src/integration/assets/kimi/herdr-agent-state.sh +++ b/src/integration/assets/kimi/herdr-agent-state.sh @@ -3,7 +3,7 @@ # managed by herdr; reinstalling or updating the integration overwrites this file. # add custom hooks beside this file instead of editing it. # HERDR_INTEGRATION_ID=kimi -# HERDR_INTEGRATION_VERSION=4 +# HERDR_INTEGRATION_VERSION=5 set -eu diff --git a/src/integration/config_edit.rs b/src/integration/config_edit.rs index 63c18845..630682ce 100644 --- a/src/integration/config_edit.rs +++ b/src/integration/config_edit.rs @@ -749,18 +749,26 @@ pub(crate) fn build_kimi_config_with_hooks(content: &str, hook_path: &Path) -> S result.push_str(KIMI_CONFIG_BLOCK_BEGIN); result.push('\n'); - for (event, action) in KIMI_HOOK_EVENTS { - result.push_str(&kimi_hook_table(event, hook_path, action)); + for (event, matcher, action) in KIMI_HOOK_EVENTS { + result.push_str(&kimi_hook_table(event, matcher, hook_path, action)); } result.push_str(KIMI_CONFIG_BLOCK_END); result.push('\n'); result } -pub(crate) fn kimi_hook_table(event: &str, hook_path: &Path, action: &str) -> String { +pub(crate) fn kimi_hook_table( + event: &str, + matcher: Option<&str>, + hook_path: &Path, + action: &str, +) -> String { let command = hook_command(hook_path, Some(action)); + let matcher = matcher + .map(|matcher| format!("matcher = {}\n", toml_basic_string(matcher))) + .unwrap_or_default(); format!( - "[[hooks]]\nevent = {}\ncommand = {}\ntimeout = 10\n\n", + "[[hooks]]\nevent = {}\n{matcher}command = {}\ntimeout = 10\n\n", toml_basic_string(event), toml_basic_string(&command) ) diff --git a/src/integration/mod.rs b/src/integration/mod.rs index fdc1c5bd..73c23fc6 100644 --- a/src/integration/mod.rs +++ b/src/integration/mod.rs @@ -58,20 +58,37 @@ const KIMI_HOOK_ASSET: &str = if cfg!(windows) { } else { include_str!("assets/kimi/herdr-agent-state.sh") }; -const KIMI_INTEGRATION_VERSION: u32 = 4; +const KIMI_INTEGRATION_VERSION: u32 = 5; const KIMI_CONFIG_BLOCK_BEGIN: &str = "# >>> herdr kimi integration"; const KIMI_CONFIG_BLOCK_END: &str = "# <<< herdr kimi integration"; const KIMI_MIN_VERSION: &str = "0.14.0"; -const KIMI_HOOK_EVENTS: [(&str, &str); 9] = [ - ("SessionStart", "session"), - ("UserPromptSubmit", "working"), - ("PreToolUse", "working"), - ("SubagentStart", "working"), - ("PreCompact", "working"), - ("PermissionRequest", "blocked"), - ("PermissionResult", "working"), - ("Stop", "idle"), - ("Interrupt", "idle"), +const KIMI_ASK_USER_QUESTION_MATCHER: &str = "^AskUserQuestion$"; +const KIMI_OTHER_TOOL_MATCHER: &str = "^(?!AskUserQuestion$).*$"; +const KIMI_HOOK_EVENTS: [(&str, Option<&str>, &str); 12] = [ + ("SessionStart", None, "session"), + ("UserPromptSubmit", None, "working"), + ("PreToolUse", Some(KIMI_OTHER_TOOL_MATCHER), "working"), + ( + "PreToolUse", + Some(KIMI_ASK_USER_QUESTION_MATCHER), + "blocked", + ), + ( + "PostToolUse", + Some(KIMI_ASK_USER_QUESTION_MATCHER), + "working", + ), + ( + "PostToolUseFailure", + Some(KIMI_ASK_USER_QUESTION_MATCHER), + "working", + ), + ("SubagentStart", None, "working"), + ("PreCompact", None, "working"), + ("PermissionRequest", None, "blocked"), + ("PermissionResult", None, "working"), + ("Stop", None, "idle"), + ("Interrupt", None, "idle"), ]; const COPILOT_HOOK_INSTALL_NAME: &str = if cfg!(windows) { "herdr-agent-state.ps1" diff --git a/src/integration/tests.rs b/src/integration/tests.rs index 41714ffa..786e67fb 100644 --- a/src/integration/tests.rs +++ b/src/integration/tests.rs @@ -116,16 +116,23 @@ fn kimi_config_hooks(config: &str) -> Vec<toml::Value> { .unwrap_or_default() } -fn assert_kimi_hook(config: &str, hook_path: &Path, event: &str, action: &str) { +fn assert_kimi_hook( + config: &str, + hook_path: &Path, + event: &str, + matcher: Option<&str>, + action: &str, +) { let command = kimi_hook_command(hook_path, action); let hooks = kimi_config_hooks(config); assert!( hooks.iter().any(|hook| { hook.get("event").and_then(toml::Value::as_str) == Some(event) + && hook.get("matcher").and_then(toml::Value::as_str) == matcher && hook.get("command").and_then(toml::Value::as_str) == Some(command.as_str()) && hook.get("timeout").and_then(toml::Value::as_integer) == Some(10) }), - "missing kimi hook for {event} -> {action}" + "missing kimi hook for {event} ({matcher:?}) -> {action}" ); } @@ -1434,8 +1441,8 @@ fn install_kimi_writes_hook_and_updates_config() { assert!(config.contains("command = \"echo keep\"")); assert!(config.contains(KIMI_CONFIG_BLOCK_BEGIN)); assert!(config.contains(KIMI_CONFIG_BLOCK_END)); - for (event, action) in KIMI_HOOK_EVENTS { - assert_kimi_hook(&config, &installed.hook_path, event, action); + for (event, matcher, action) in KIMI_HOOK_EVENTS { + assert_kimi_hook(&config, &installed.hook_path, event, matcher, action); } std::env::remove_var("HOME"); @@ -1443,6 +1450,26 @@ fn install_kimi_writes_hook_and_updates_config() { } #[test] +fn kimi_question_hooks_report_blocked_until_the_question_finishes() { + assert!(KIMI_HOOK_EVENTS.contains(&( + "PreToolUse", + Some(KIMI_ASK_USER_QUESTION_MATCHER), + "blocked", + ))); + assert!(KIMI_HOOK_EVENTS.contains(&( + "PostToolUse", + Some(KIMI_ASK_USER_QUESTION_MATCHER), + "working", + ))); + assert!(KIMI_HOOK_EVENTS.contains(&( + "PostToolUseFailure", + Some(KIMI_ASK_USER_QUESTION_MATCHER), + "working", + ))); + assert!(KIMI_HOOK_EVENTS.contains(&("PreToolUse", Some(KIMI_OTHER_TOOL_MATCHER), "working",))); +} + +#[test] fn install_kimi_uses_kimi_code_home_env() { let _lock = integration_env_lock(); let base = unique_base(); |
