aboutsummaryrefslogtreecommitdiff
path: root/src/terminal/state.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-17 20:06:52 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-17 20:07:18 +0300
commitf161be04613211d8fee7ef18e6e506df09da3ba1 (patch)
treeec65649c42f95104ec04c33d19c056f169a41189 /src/terminal/state.rs
parent45a4318bbbcb2c91d95faee6f31e5846ae3f9ec0 (diff)
fix: detect Grok Build agent state
refs #133
Diffstat (limited to 'src/terminal/state.rs')
-rw-r--r--src/terminal/state.rs71
1 files changed, 66 insertions, 5 deletions
diff --git a/src/terminal/state.rs b/src/terminal/state.rs
index f9d5b522..8c27f1a5 100644
--- a/src/terminal/state.rs
+++ b/src/terminal/state.rs
@@ -78,11 +78,13 @@ impl TerminalState {
let previous_detected_agent = self.detected_agent;
self.detected_agent = agent;
self.fallback_state = fallback_state;
- if previous_detected_agent.is_some()
- && agent != previous_detected_agent
- && self.hook_authority.as_ref().is_some_and(|authority| {
- crate::detect::parse_agent_label(&authority.agent_label) == previous_detected_agent
- })
+ if self.hook_authority_conflicts_with_detected_agent(agent)
+ || (previous_detected_agent.is_some()
+ && agent != previous_detected_agent
+ && self.hook_authority.as_ref().is_some_and(|authority| {
+ crate::detect::parse_agent_label(&authority.agent_label)
+ == previous_detected_agent
+ }))
{
self.hook_authority = None;
}
@@ -117,6 +119,9 @@ impl TerminalState {
let previous_agent_label = self.effective_agent_label().map(str::to_string);
let previous_known_agent = self.effective_known_agent();
let previous_state = self.state;
+ if self.known_agent_label_conflicts_with_detected_agent(&agent_label) {
+ return None;
+ }
self.hook_authority = Some(HookAuthority {
source,
agent_label,
@@ -127,6 +132,24 @@ impl TerminalState {
self.recompute_effective_state(previous_agent_label, previous_known_agent, previous_state)
}
+ fn hook_authority_conflicts_with_detected_agent(&self, detected_agent: Option<Agent>) -> bool {
+ let Some(detected_agent) = detected_agent else {
+ return false;
+ };
+ self.hook_authority.as_ref().is_some_and(|authority| {
+ crate::detect::parse_agent_label(&authority.agent_label)
+ .is_some_and(|hook_agent| hook_agent != detected_agent)
+ })
+ }
+
+ fn known_agent_label_conflicts_with_detected_agent(&self, agent_label: &str) -> bool {
+ let Some(detected_agent) = self.detected_agent else {
+ return false;
+ };
+ crate::detect::parse_agent_label(agent_label)
+ .is_some_and(|hook_agent| hook_agent != detected_agent)
+ }
+
fn accept_hook_report(&mut self, source: &str, seq: Option<u64>) -> bool {
let Some(seq) = seq else {
return !self.hook_report_sequences.contains_key(source);
@@ -418,6 +441,44 @@ mod tests {
}
#[test]
+ fn known_hook_authority_does_not_override_different_detected_agent() {
+ let mut terminal = test_terminal();
+ terminal.set_detected_state(Some(Agent::Grok), AgentState::Working);
+ let change = terminal.set_hook_authority(
+ "herdr:claude".into(),
+ "claude".into(),
+ AgentState::Blocked,
+ None,
+ None,
+ );
+
+ assert!(change.is_none());
+ assert!(terminal.hook_authority.is_none());
+ assert_eq!(terminal.detected_agent, Some(Agent::Grok));
+ assert_eq!(terminal.effective_agent_label(), Some("grok"));
+ assert_eq!(terminal.state, AgentState::Working);
+ }
+
+ #[test]
+ fn detected_agent_clears_conflicting_known_hook_authority() {
+ let mut terminal = test_terminal();
+ terminal.set_hook_authority(
+ "herdr:claude".into(),
+ "claude".into(),
+ AgentState::Blocked,
+ None,
+ None,
+ );
+
+ terminal.set_detected_state(Some(Agent::Grok), AgentState::Working);
+
+ assert!(terminal.hook_authority.is_none());
+ assert_eq!(terminal.detected_agent, Some(Agent::Grok));
+ assert_eq!(terminal.effective_agent_label(), Some("grok"));
+ assert_eq!(terminal.state, AgentState::Working);
+ }
+
+ #[test]
fn border_label_prefers_manual_label_over_agent_label() {
let mut terminal = test_terminal();
terminal.set_detected_state(Some(Agent::Claude), AgentState::Idle);