aboutsummaryrefslogtreecommitdiff
path: root/src/app/api
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-08-14 01:22:46 +0300
committerGitHub <noreply@github.com>2026-08-14 01:22:46 +0300
commit9351b058f34973016a5d5973297d0567513e67a4 (patch)
tree6b31e2700258170685297e08c03084e21d459e44 /src/app/api
parent2075de5db083f1d1f4a9c67f6b36a8eeb250754e (diff)
fix: reject prompts to blocked agents (#2790)
* fix: reject prompts to blocked agents refs #2788 * docs: clarify agent prompt timing refs #2788 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src/app/api')
-rw-r--r--src/app/api/agents.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/app/api/agents.rs b/src/app/api/agents.rs
index e5e5525f..1ed13efc 100644
--- a/src/app/api/agents.rs
+++ b/src/app/api/agents.rs
@@ -79,6 +79,16 @@ impl App {
let Some(terminal) = self.state.terminals.get(&terminal_id) else {
return agent_not_found(id, &params.target);
};
+ if terminal.state == crate::detect::AgentState::Blocked {
+ return encode_error(
+ id,
+ "agent_blocked",
+ format!(
+ "agent {} is blocked and requires interactive input",
+ params.target
+ ),
+ );
+ }
let Some(expected_agent) = terminal.effective_known_agent() else {
return agent_not_ready(id, &params.target);
};
@@ -407,6 +417,41 @@ mod tests {
}
#[tokio::test]
+ async fn agent_prompt_rejects_blocked_agent_without_writing() {
+ let mut app = app_with_agent();
+ let pane_id = app.state.workspaces[0].tabs[0].root_pane;
+ let terminal_id = app.state.workspaces[0].tabs[0].panes[&pane_id]
+ .attached_terminal_id
+ .clone();
+ let terminal = app.state.terminals.get_mut(&terminal_id).unwrap();
+ terminal.set_agent_name("reviewer".into());
+ terminal.set_detected_state(Some(Agent::GithubCopilot), AgentState::Blocked);
+ let (runtime, mut rx) = crate::terminal::TerminalRuntime::test_with_channel(80, 24);
+ app.state.insert_test_runtime(pane_id, runtime);
+
+ let response = app.handle_agent_prompt(
+ "req".into(),
+ AgentPromptParams {
+ target: "reviewer".into(),
+ text: "unrelated prompt".into(),
+ wait: None,
+ },
+ );
+
+ let error: crate::api::schema::ErrorResponse = serde_json::from_str(&response).unwrap();
+ assert_eq!(error.error.code, "agent_blocked");
+ assert!(
+ tokio::time::timeout(
+ AGENT_PROMPT_SUBMIT_DELAY + Duration::from_millis(100),
+ rx.recv()
+ )
+ .await
+ .is_err(),
+ "blocked prompt wrote or scheduled terminal input"
+ );
+ }
+
+ #[tokio::test]
async fn agent_prompt_focuses_copilot_before_submitting() {
let mut app = app_with_agent();
let pane_id = app.state.workspaces[0].tabs[0].root_pane;